]> code.citadel.org Git - citadel.git/blob - webcit/roomops.c
* Replaced _most_ gotoroom() calls with smart_goto(), a version
[citadel.git] / webcit / roomops.c
1 /* $Id$ */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #ifdef HAVE_UNISTD_H
6 #include <unistd.h>
7 #endif
8 #include <stdio.h>
9 #include <signal.h>
10 #include <sys/types.h>
11 #include "webcit.h"
12 #include "child.h"
13
14 /*
15  * This struct holds a list of rooms for <G>oto operations.
16  */
17 struct march {
18         struct march *next;
19         char march_name[32];
20         int march_floor;
21         int march_order;
22 };
23
24 /* 
25  * This struct holds a list of rooms for client display.
26  * (oooh, a tree!)
27  */
28 struct roomlisting {
29         struct roomlisting *lnext;
30         struct roomlisting *rnext;
31         char rlname[64];
32         unsigned rlflags;
33         int rlfloor;
34         int rlorder;
35 };
36
37
38 char floorlist[128][256];
39 char ugname[128];
40 long uglsn = (-1L);
41 unsigned room_flags;
42 int is_aide = 0;
43 int is_room_aide = 0;
44
45 struct march *march = NULL;
46
47 /*
48  * load the list of floors
49  */
50 void load_floorlist(void)
51 {
52         int a;
53         char buf[256];
54
55         for (a = 0; a < 128; ++a)
56                 floorlist[a][0] = 0;
57
58         serv_puts("LFLR");
59         serv_gets(buf);
60         if (buf[0] != '1') {
61                 strcpy(floorlist[0], "Main Floor");
62                 return;
63         }
64         while (serv_gets(buf), strcmp(buf, "000")) {
65                 extract(floorlist[extract_int(buf, 0)], buf, 1);
66         }
67 }
68
69
70 /*
71  * remove a room from the march list
72  */
73 void remove_march(char *aaa)
74 {
75         struct march *mptr, *mptr2;
76
77         if (march == NULL)
78                 return;
79
80         if (!strcasecmp(march->march_name, aaa)) {
81                 mptr = march->next;
82                 free(march);
83                 march = mptr;
84                 return;
85         }
86         mptr2 = march;
87         for (mptr = march; mptr != NULL; mptr = mptr->next) {
88                 if (!strcasecmp(mptr->march_name, aaa)) {
89                         mptr2->next = mptr->next;
90                         free(mptr);
91                         mptr = mptr2;
92                 } else {
93                         mptr2 = mptr;
94                 }
95         }
96 }
97
98
99
100
101
102 void room_tree_list(struct roomlisting *rp)
103 {
104         char rmname[64];
105         int f;
106
107         if (rp == NULL)
108                 return;
109
110         if (rp->lnext != NULL) {
111                 room_tree_list(rp->lnext);
112         }
113         strcpy(rmname, rp->rlname);
114         f = rp->rlflags;
115
116         wprintf("<A HREF=\"/dotgoto&room=");
117         urlescputs(rmname);
118         wprintf("\"");
119         if (!noframes) wprintf("TARGET=\"top\"");
120         wprintf(">");
121         escputs1(rmname, 1);
122         if ((f & QR_DIRECTORY) && (f & QR_NETWORK))
123                 wprintf("}");
124         else if (f & QR_DIRECTORY)
125                 wprintf("]");
126         else if (f & QR_NETWORK)
127                 wprintf(")");
128         else
129                 wprintf("&gt;");
130         wprintf("</A><TT> </TT>\n");
131
132         if (rp->rnext != NULL) {
133                 room_tree_list(rp->rnext);
134         }
135         free(rp);
136 }
137
138
139 /* 
140  * Room ordering stuff (compare first by floor, then by order)
141  */
142 int rordercmp(struct roomlisting *r1, struct roomlisting *r2)
143 {
144         if ((r1 == NULL) && (r2 == NULL))
145                 return (0);
146         if (r1 == NULL)
147                 return (-1);
148         if (r2 == NULL)
149                 return (1);
150         if (r1->rlfloor < r2->rlfloor)
151                 return (-1);
152         if (r1->rlfloor > r2->rlfloor)
153                 return (1);
154         if (r1->rlorder < r2->rlorder)
155                 return (-1);
156         if (r1->rlorder > r2->rlorder)
157                 return (1);
158         return (0);
159 }
160
161
162 /*
163  * Common code for all room listings
164  */
165 void listrms(char *variety)
166 {
167         char buf[256];
168         int num_rooms = 0;
169
170         struct roomlisting *rl = NULL;
171         struct roomlisting *rp;
172         struct roomlisting *rs;
173
174
175         /* Ask the server for a room list */
176         serv_puts(variety);
177         serv_gets(buf);
178         if (buf[0] != '1') {
179                 wprintf("&nbsp;");
180                 return;
181         }
182         while (serv_gets(buf), strcmp(buf, "000")) {
183                 ++num_rooms;
184                 rp = malloc(sizeof(struct roomlisting));
185                 extract(rp->rlname, buf, 0);
186                 rp->rlflags = extract_int(buf, 1);
187                 rp->rlfloor = extract_int(buf, 2);
188                 rp->rlorder = extract_int(buf, 3);
189                 rp->lnext = NULL;
190                 rp->rnext = NULL;
191
192                 rs = rl;
193                 if (rl == NULL) {
194                         rl = rp;
195                 } else
196                         while (rp != NULL) {
197                                 if (rordercmp(rp, rs) < 0) {
198                                         if (rs->lnext == NULL) {
199                                                 rs->lnext = rp;
200                                                 rp = NULL;
201                                         } else {
202                                                 rs = rs->lnext;
203                                         }
204                                 } else {
205                                         if (rs->rnext == NULL) {
206                                                 rs->rnext = rp;
207                                                 rp = NULL;
208                                         } else {
209                                                 rs = rs->rnext;
210                                         }
211                                 }
212                         }
213         }
214
215         room_tree_list(rl);
216
217         /* If no rooms were listed, print an nbsp to make the cell
218          * borders show up anyway.
219          */
220         if (num_rooms == 0) wprintf("&nbsp;");
221 }
222
223
224
225
226
227
228
229
230
231 /*
232  * list all rooms by floor
233  */
234 void list_all_rooms_by_floor(void)
235 {
236         int a;
237         char buf[256];
238
239         load_floorlist();
240
241         printf("HTTP/1.0 200 OK\n");
242         output_headers(1);
243
244         wprintf("<TABLE width=100% border><TR><TH>Floor</TH>");
245         wprintf("<TH><FONT FACE=\"Arial,Helvetica,sans-serif\">Rooms with new messages</FONT></TH>");
246         wprintf("<TH><FONT FACE=\"Arial,Helvetica,sans-serif\">Rooms with no new messages</FONT></TH></TR>\n");
247
248         for (a = 0; a < 128; ++a)
249                 if (floorlist[a][0] != 0) {
250
251                         /* Floor name column */
252                         wprintf("<TR><TD><FONT FACE=\"Arial,Helvetica,sans-serif\">");
253
254                         serv_printf("OIMG _floorpic_|%d", a);
255                         serv_gets(buf);
256                         if (buf[0] == '2') {
257                                 serv_puts("CLOS");
258                                 serv_gets(buf);
259                                 wprintf("<IMG SRC=\"/image&name=_floorpic_&parm=%d\" ALT=\"%s\">",
260                                         a, &floorlist[a][0]);
261                         } else {
262                                 escputs(&floorlist[a][0]);
263                         }
264
265                         wprintf("</FONT></TD>");
266
267                         /* Rooms with new messages column */
268                         wprintf("<TD><FONT FACE=\"Arial,Helvetica,sans-serif\">");
269                         sprintf(buf, "LKRN %d", a);
270                         listrms(buf);
271                         wprintf("</FONT></TD>\n<TD><FONT FACE=\"Arial,Helvetica,sans-serif\">");
272
273                         /* Rooms with old messages column */
274                         sprintf(buf, "LKRO %d", a);
275                         listrms(buf);
276                         wprintf("</FONT></TD></TR>\n");
277                 }
278         wprintf("</TABLE>\n");
279         wDumpContent(1);
280 }
281
282
283 /*
284  * list all forgotten rooms
285  */
286 void zapped_list(void)
287 {
288         printf("HTTP/1.0 200 OK\n");
289         output_headers(1);
290         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
291         wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" SIZE=+1 COLOR=\"FFFFFF\"");
292         wprintf("<B>Zapped (forgotten) rooms</B>\n");
293         wprintf("</FONT></TD></TR></TABLE><BR>\n");
294         listrms("LZRM -1");
295         wprintf("<BR><BR>\n");
296         wprintf("Click on any room to un-zap it and goto that room.\n");
297         wDumpContent(1);
298 }
299
300
301 /*
302  * read this room's info file (set v to 1 for verbose mode)
303  */
304 void readinfo(int v)
305 {
306         char buf[256];
307
308         serv_puts("RINF");
309         serv_gets(buf);
310         if (buf[0] == '1')
311                 fmout(NULL);
312         else {
313                 if (v == 1)
314                         wprintf("<EM>%s</EM><BR>\n", &buf[4]);
315         }
316 }
317
318
319
320 void embed_room_banner(char *got) {
321         char buf[256];
322         char fakegot[256];
323
324         if (got == NULL) {
325                 serv_printf("GOTO %s", wc_roomname);
326                 serv_gets(fakegot);
327                 got = fakegot;
328         }
329
330         wprintf("<CENTER><TABLE border=0><TR>");
331
332         if ((strlen(ugname) > 0) && (strcasecmp(ugname, wc_roomname))) {
333                 wprintf("<TD VALIGN=TOP><A HREF=\"/ungoto\">");
334                 wprintf("<IMG SRC=\"/static/back.gif\" BORDER=0></A></TD>");
335         }
336         wprintf("<TD VALIGN=TOP><FONT FACE=\"Arial,Helvetica,sans-serif\"><FONT SIZE=+2>%s</FONT><BR>", wc_roomname);
337         wprintf("%d new of %d messages</FONT></TD>\n",
338                 extract_int(&got[4], 1),
339                 extract_int(&got[4], 2));
340
341         /* Display room graphic.  The server doesn't actually
342          * need the room name, but we supply it in order to
343          * keep the browser from using a cached graphic from 
344          * another room.
345          */
346         serv_puts("OIMG _roompic_");
347         serv_gets(buf);
348         if (buf[0] == '2') {
349                 wprintf("<TD><FONT FACE=\"Arial,Helvetica,sans-serif\">");
350                 wprintf("<IMG SRC=\"/image&name=_roompic_&room=");
351                 escputs(wc_roomname);
352                 wprintf("\"></FONT></TD>");
353                 serv_puts("CLOS");
354                 serv_gets(buf);
355         }
356         wprintf("<TD VALIGN=TOP><FONT FACE=\"Arial,Helvetica,sans-serif\">");
357         readinfo(0);
358         wprintf("</FONT></TD>");
359
360         wprintf("<TD VALIGN=TOP><A HREF=\"/gotonext\">");
361         wprintf("<IMG SRC=\"/static/forward.gif\" border=0></A></TD>");
362         wprintf("</TR></TABLE></CENTER>\n");
363 }
364
365
366
367
368
369 /*
370  * generic routine to take the session to a new room
371  *
372  * display_name values:  0 = goto only
373  *                       1 = goto and display
374  *                       2 = display only
375  */
376 void gotoroom(char *gname, int display_name)
377 {
378         char buf[256];
379         static long ls = (-1L);
380
381
382         if (display_name) {
383                 printf("HTTP/1.0 200 OK\n");
384                 printf("Pragma: no-cache\n");
385                 printf("Cache-Control: no-store\n");
386                 output_headers(0);
387
388                 wprintf("<HTML><HEAD></HEAD>\n<BODY ");
389
390                 /* automatically fire up a read-new-msgs in the bottom frame */
391                 if (!noframes)
392                         wprintf("onload=parent.frames.bottom.location=\"/readnew\" ");
393
394                 wprintf("BACKGROUND=\"/image&name=background\" TEXT=\"#000000\" LINK=\"#004400\">\n");
395         }
396         if (display_name != 2) {
397                 /* store ungoto information */
398                 strcpy(ugname, wc_roomname);
399                 uglsn = ls;
400         }
401         /* move to the new room */
402         serv_printf("GOTO %s", gname);
403         serv_gets(buf);
404         if (buf[0] != '2') {
405                 serv_puts("GOTO _BASEROOM_");
406                 serv_gets(buf);
407         }
408         if (buf[0] != '2') {
409                 if (display_name) {
410                         wprintf("<EM>%s</EM><BR>\n", &buf[4]);
411                         wDumpContent(1);
412                 }
413                 return;
414         }
415         extract(wc_roomname, &buf[4], 0);
416         room_flags = extract_int(&buf[4], 4);
417         /* highest_msg_read = extract_int(&buf[4],6);
418            maxmsgnum = extract_int(&buf[4],5);
419            is_mail = (char) extract_int(&buf[4],7); */
420         ls = extract_long(&buf[4], 6);
421
422         if (is_aide)
423                 is_room_aide = is_aide;
424         else
425                 is_room_aide = (char) extract_int(&buf[4], 8);
426
427         remove_march(wc_roomname);
428         if (!strcasecmp(gname, "_BASEROOM_"))
429                 remove_march(gname);
430
431         /* Display the room banner */
432         if (display_name) {
433                 embed_room_banner(buf);
434                 wDumpContent(1);
435         }
436         strcpy(wc_roomname, wc_roomname);
437 }
438
439
440 /*
441  * Locate the room on the march list which we most want to go to.  Each room
442  * is measured given a "weight" of preference based on various factors.
443  */
444 char *pop_march(int desired_floor)
445 {
446         static char TheRoom[64];
447         int TheFloor = 0;
448         int TheOrder = 32767;
449         int TheWeight = 0;
450         int weight;
451         struct march *mptr = NULL;
452
453         strcpy(TheRoom, "_BASEROOM_");
454         if (march == NULL)
455                 return (TheRoom);
456
457         for (mptr = march; mptr != NULL; mptr = mptr->next) {
458                 weight = 0;
459                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
460                         weight = weight + 10000;
461                 if (mptr->march_floor == desired_floor)
462                         weight = weight + 5000;
463
464                 weight = weight + ((128 - (mptr->march_floor)) * 128);
465                 weight = weight + (128 - (mptr->march_order));
466
467                 if (weight > TheWeight) {
468                         TheWeight = weight;
469                         strcpy(TheRoom, mptr->march_name);
470                         TheFloor = mptr->march_floor;
471                         TheOrder = mptr->march_order;
472                 }
473         }
474         return (TheRoom);
475 }
476
477
478
479 /* Goto next room having unread messages.
480  * We want to skip over rooms that the user has already been to, and take the
481  * user back to the lobby when done.  The room we end up in is placed in
482  * newroom - which is set to 0 (the lobby) initially.
483  * We start the search in the current room rather than the beginning to prevent
484  * two or more concurrent users from dragging each other back to the same room.
485  */
486 void gotonext(void)
487 {
488         char buf[256];
489         struct march *mptr, *mptr2;
490         char next_room[32];
491
492         /* First check to see if the march-mode list is already allocated.
493          * If it is, pop the first room off the list and go there.
494          */
495
496         if (march == NULL) {
497                 serv_puts("LKRN");
498                 serv_gets(buf);
499                 if (buf[0] == '1')
500                         while (serv_gets(buf), strcmp(buf, "000")) {
501                                 mptr = (struct march *) malloc(sizeof(struct march));
502                                 mptr->next = NULL;
503                                 extract(mptr->march_name, buf, 0);
504                                 mptr->march_floor = extract_int(buf, 2);
505                                 mptr->march_order = extract_int(buf, 3);
506                                 if (march == NULL) {
507                                         march = mptr;
508                                 } else {
509                                         mptr2 = march;
510                                         while (mptr2->next != NULL)
511                                                 mptr2 = mptr2->next;
512                                         mptr2->next = mptr;
513                                 }
514                         }
515 /* add _BASEROOM_ to the end of the march list, so the user will end up
516  * in the system base room (usually the Lobby>) at the end of the loop
517  */
518                 mptr = (struct march *) malloc(sizeof(struct march));
519                 mptr->next = NULL;
520                 strcpy(mptr->march_name, "_BASEROOM_");
521                 if (march == NULL) {
522                         march = mptr;
523                 } else {
524                         mptr2 = march;
525                         while (mptr2->next != NULL)
526                                 mptr2 = mptr2->next;
527                         mptr2->next = mptr;
528                 }
529 /*
530  * ...and remove the room we're currently in, so a <G>oto doesn't make us
531  * walk around in circles
532  */
533                 remove_march(wc_roomname);
534         }
535         if (march != NULL) {
536                 strcpy(next_room, pop_march(-1));
537         } else {
538                 strcpy(next_room, "_BASEROOM_");
539         }
540
541
542         smart_goto(next_room);
543 }
544
545
546 void smart_goto(char *next_room) {
547         /* In noframes mode, we goto the room silently, then do a
548          * read-new-messages which causes the banner to show up anyway.
549          */
550         if (noframes) {
551                 gotoroom(next_room, 0);
552                 readloop("readnew");
553         } else {
554         /* In frames mode, we let gotoroom() bring up the banner, which then
555          * uses JavaScript to bring up the new-messages display in the
556          * bottom frame.
557          */
558                 gotoroom(next_room, 1);
559         }
560 }
561
562
563
564 /*
565  * mark all messages in current room as having been read
566  */
567 void slrp_highest(void)
568 {
569         char buf[256];
570
571         /* set pointer */
572         serv_puts("SLRP HIGHEST");
573         serv_gets(buf);
574         if (buf[0] != '2') {
575                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
576                 return;
577         }
578 }
579
580
581 /*
582  * un-goto the previous room
583  */
584 void ungoto(void)
585 {
586         char buf[256];
587
588         if (!strcmp(ugname, "")) {
589                 smart_goto(wc_roomname);
590                 return;
591         }
592         serv_printf("GOTO %s", ugname);
593         serv_gets(buf);
594         if (buf[0] != '2') {
595                 smart_goto(wc_roomname);
596                 return;
597         }
598         if (uglsn >= 0L) {
599                 serv_printf("SLRP %ld", uglsn);
600                 serv_gets(buf);
601         }
602         strcpy(buf, ugname);
603         strcpy(ugname, "");
604         smart_goto(buf);
605 }
606
607 /*
608  * display the form for editing a room
609  */
610 void display_editroom(void)
611 {
612         char buf[256];
613         char er_name[20];
614         char er_password[10];
615         char er_dirname[15];
616         char er_roomaide[26];
617         unsigned er_flags;
618         int er_floor;
619         int i;
620
621         serv_puts("GETR");
622         serv_gets(buf);
623
624         if (buf[0] != '2') {
625                 display_error(&buf[4]);
626                 return;
627         }
628         extract(er_name, &buf[4], 0);
629         extract(er_password, &buf[4], 1);
630         extract(er_dirname, &buf[4], 2);
631         er_flags = extract_int(&buf[4], 3);
632         er_floor = extract_int(&buf[4], 4);
633
634
635         printf("HTTP/1.0 200 OK\n");
636         output_headers(1);
637
638         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
639         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
640         wprintf("<B>Edit this room</B>\n");
641         wprintf("</FONT></TD></TR></TABLE>\n");
642
643         wprintf("<FORM METHOD=\"POST\" ACTION=\"/editroom\">\n");
644
645         wprintf("<UL><LI>Name of room: ");
646         wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\"19\">\n", er_name);
647
648         wprintf("<LI>Resides on floor: ");
649         load_floorlist();
650         wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
651         for (i = 0; i < 128; ++i)
652                 if (strlen(floorlist[i]) > 0) {
653                         wprintf("<OPTION ");
654                         if (i == er_floor)
655                                 wprintf("SELECTED ");
656                         wprintf("VALUE=\"%d\">", i);
657                         escputs(floorlist[i]);
658                         wprintf("</OPTION>\n");
659                 }
660         wprintf("</SELECT>\n");
661
662         wprintf("<LI>Type of room:<UL>\n");
663
664         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
665         if ((er_flags & QR_PRIVATE) == 0)
666                 wprintf("CHECKED ");
667         wprintf("> Public room\n");
668
669         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
670         if ((er_flags & QR_PRIVATE) &&
671             (er_flags & QR_GUESSNAME))
672                 wprintf("CHECKED ");
673         wprintf("> Private - guess name\n");
674
675         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
676         if ((er_flags & QR_PRIVATE) &&
677             (er_flags & QR_PASSWORDED))
678                 wprintf("CHECKED ");
679         wprintf("> Private - require password:\n");
680         wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n", er_password);
681
682         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
683         if ((er_flags & QR_PRIVATE)
684             && ((er_flags & QR_GUESSNAME) == 0)
685             && ((er_flags & QR_PASSWORDED) == 0))
686                 wprintf("CHECKED ");
687         wprintf("> Private - invitation only\n");
688
689         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
690         wprintf("> If private, cause current users to forget room\n");
691
692         wprintf("</UL>\n");
693
694         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
695         if (er_flags & QR_PREFONLY)
696                 wprintf("CHECKED ");
697         wprintf("> Preferred users only\n");
698
699         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
700         if (er_flags & QR_READONLY)
701                 wprintf("CHECKED ");
702         wprintf("> Read-only room\n");
703
704 /* directory stuff */
705         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
706         if (er_flags & QR_DIRECTORY)
707                 wprintf("CHECKED ");
708         wprintf("> File directory room\n");
709
710         wprintf("<UL><LI>Directory name: ");
711         wprintf("<INPUT TYPE=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n", er_dirname);
712
713         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
714         if (er_flags & QR_UPLOAD)
715                 wprintf("CHECKED ");
716         wprintf("> Uploading allowed\n");
717
718         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
719         if (er_flags & QR_DOWNLOAD)
720                 wprintf("CHECKED ");
721         wprintf("> Downloading allowed\n");
722
723         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
724         if (er_flags & QR_VISDIR)
725                 wprintf("CHECKED ");
726         wprintf("> Visible directory</UL>\n");
727
728 /* end of directory stuff */
729
730         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
731         if (er_flags & QR_NETWORK)
732                 wprintf("CHECKED ");
733         wprintf("> Network shared room\n");
734
735 /* start of anon options */
736
737         wprintf("<LI>Anonymous messages<UL>\n");
738
739         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
740         if (((er_flags & QR_ANONONLY) == 0)
741             && ((er_flags & QR_ANONOPT) == 0))
742                 wprintf("CHECKED ");
743         wprintf("> No anonymous messages\n");
744
745         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
746         if (er_flags & QR_ANONONLY)
747                 wprintf("CHECKED ");
748         wprintf("> All messages are anonymous\n");
749
750         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
751         if (er_flags & QR_ANONOPT)
752                 wprintf("CHECKED ");
753         wprintf("> Prompt user when entering messages</UL>\n");
754
755 /* end of anon options */
756
757         wprintf("<LI>Room aide: \n");
758         serv_puts("GETA");
759         serv_gets(buf);
760         if (buf[0] != '2') {
761                 wprintf("<EM>%s</EM>\n", &buf[4]);
762         } else {
763                 extract(er_roomaide, &buf[4], 0);
764                 wprintf("<INPUT TYPE=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
765         }
766
767         wprintf("</UL><CENTER>\n");
768         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
769         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
770         wprintf("</CENTER>\n");
771
772         wDumpContent(1);
773 }
774
775
776 /*
777  * save new parameters for a room
778  */
779 void editroom(void)
780 {
781         char buf[256];
782         char er_name[20];
783         char er_password[10];
784         char er_dirname[15];
785         char er_roomaide[26];
786         int er_floor;
787         unsigned er_flags;
788         int bump;
789
790
791         if (strcmp(bstr("sc"), "OK")) {
792                 display_error("Cancelled.  Changes were not saved.");
793                 return;
794         }
795         serv_puts("GETR");
796         serv_gets(buf);
797
798         if (buf[0] != '2') {
799                 display_error(&buf[4]);
800                 return;
801         }
802         extract(er_name, &buf[4], 0);
803         extract(er_password, &buf[4], 1);
804         extract(er_dirname, &buf[4], 2);
805         er_flags = extract_int(&buf[4], 3);
806
807         strcpy(er_roomaide, bstr("er_roomaide"));
808         if (strlen(er_roomaide) == 0) {
809                 serv_puts("GETA");
810                 serv_gets(buf);
811                 if (buf[0] != '2') {
812                         strcpy(er_roomaide, "");
813                 } else {
814                         extract(er_roomaide, &buf[4], 0);
815                 }
816         }
817         strcpy(buf, bstr("er_name"));
818         buf[20] = 0;
819         if (strlen(buf) > 0)
820                 strcpy(er_name, buf);
821
822         strcpy(buf, bstr("er_password"));
823         buf[10] = 0;
824         if (strlen(buf) > 0)
825                 strcpy(er_password, buf);
826
827         strcpy(buf, bstr("er_dirname"));
828         buf[15] = 0;
829         if (strlen(buf) > 0)
830                 strcpy(er_dirname, buf);
831
832         strcpy(buf, bstr("type"));
833         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
834
835         if (!strcmp(buf, "invonly")) {
836                 er_flags |= (QR_PRIVATE);
837         }
838         if (!strcmp(buf, "guessname")) {
839                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
840         }
841         if (!strcmp(buf, "passworded")) {
842                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
843         }
844         if (!strcmp(bstr("prefonly"), "yes")) {
845                 er_flags |= QR_PREFONLY;
846         } else {
847                 er_flags &= ~QR_PREFONLY;
848         }
849
850         if (!strcmp(bstr("readonly"), "yes")) {
851                 er_flags |= QR_READONLY;
852         } else {
853                 er_flags &= ~QR_READONLY;
854         }
855
856         if (!strcmp(bstr("network"), "yes")) {
857                 er_flags |= QR_NETWORK;
858         } else {
859                 er_flags &= ~QR_NETWORK;
860         }
861
862         if (!strcmp(bstr("directory"), "yes")) {
863                 er_flags |= QR_DIRECTORY;
864         } else {
865                 er_flags &= ~QR_DIRECTORY;
866         }
867
868         if (!strcmp(bstr("ulallowed"), "yes")) {
869                 er_flags |= QR_UPLOAD;
870         } else {
871                 er_flags &= ~QR_UPLOAD;
872         }
873
874         if (!strcmp(bstr("dlallowed"), "yes")) {
875                 er_flags |= QR_DOWNLOAD;
876         } else {
877                 er_flags &= ~QR_DOWNLOAD;
878         }
879
880         if (!strcmp(bstr("visdir"), "yes")) {
881                 er_flags |= QR_VISDIR;
882         } else {
883                 er_flags &= ~QR_VISDIR;
884         }
885
886         strcpy(buf, bstr("anon"));
887
888         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
889         if (!strcmp(buf, "anononly"))
890                 er_flags |= QR_ANONONLY;
891         if (!strcmp(buf, "anon2"))
892                 er_flags |= QR_ANONOPT;
893
894         bump = 0;
895         if (!strcmp(bstr("bump"), "yes"))
896                 bump = 1;
897
898         er_floor = atoi(bstr("er_floor"));
899
900         sprintf(buf, "SETR %s|%s|%s|%u|%d|%d",
901              er_name, er_password, er_dirname, er_flags, bump, er_floor);
902         serv_puts(buf);
903         serv_gets(buf);
904         if (buf[0] != '2') {
905                 display_error(&buf[4]);
906                 return;
907         }
908         gotoroom(er_name, 0);
909
910         if (strlen(er_roomaide) > 0) {
911                 sprintf(buf, "SETA %s", er_roomaide);
912                 serv_puts(buf);
913                 serv_gets(buf);
914                 if (buf[0] != '2') {
915                         display_error(&buf[4]);
916                         return;
917                 }
918         }
919         smart_goto(er_name);
920 }
921
922
923
924 /*
925  * display the form for entering a new room
926  */
927 void display_entroom(void)
928 {
929         char buf[256];
930
931         serv_puts("CRE8 0");
932         serv_gets(buf);
933
934         if (buf[0] != '2') {
935                 display_error(&buf[4]);
936                 return;
937         }
938         printf("HTTP/1.0 200 OK\n");
939         output_headers(1);
940
941         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
942         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
943         wprintf("<B>Enter (create) a new room</B>\n");
944         wprintf("</FONT></TD></TR></TABLE>\n");
945
946         wprintf("<FORM METHOD=\"POST\" ACTION=\"/entroom\">\n");
947
948         wprintf("<UL><LI>Name of room: ");
949         wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" MAXLENGTH=\"19\">\n");
950
951         wprintf("<LI>Type of room:<UL>\n");
952
953         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
954         wprintf("CHECKED > Public room\n");
955
956         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
957         wprintf("> Private - guess name\n");
958
959         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
960         wprintf("> Private - require password:\n");
961         wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
962
963         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
964         wprintf("> Private - invitation only\n");
965
966         wprintf("<CENTER>\n");
967         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
968         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
969         wprintf("</CENTER>\n");
970         wprintf("</FORM>\n");
971         wDumpContent(1);
972 }
973
974
975
976 /*
977  * enter a new room
978  */
979 void entroom(void)
980 {
981         char buf[256];
982         char er_name[20];
983         char er_type[20];
984         char er_password[10];
985         int er_num_type;
986
987         if (strcmp(bstr("sc"), "OK")) {
988                 display_error("Cancelled.  No new room was created.");
989                 return;
990         }
991         strcpy(er_name, bstr("er_name"));
992         strcpy(er_type, bstr("type"));
993         strcpy(er_password, bstr("er_password"));
994
995         er_num_type = 0;
996         if (!strcmp(er_type, "guessname"))
997                 er_num_type = 1;
998         if (!strcmp(er_type, "passworded"))
999                 er_num_type = 2;
1000         if (!strcmp(er_type, "invonly"))
1001                 er_num_type = 3;
1002
1003         sprintf(buf, "CRE8 1|%s|%d|%s", er_name, er_num_type, er_password);
1004         serv_puts(buf);
1005         serv_gets(buf);
1006         if (buf[0] != '2') {
1007                 display_error(&buf[4]);
1008                 return;
1009         }
1010         smart_goto(er_name);
1011 }
1012
1013
1014 /*
1015  * display the screen to enter a private room
1016  */
1017 void display_private(char *rname, int req_pass)
1018 {
1019
1020         printf("HTTP/1.0 200 OK\n");
1021         output_headers(1);
1022
1023         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1024         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1025         wprintf("<B>Goto a private room</B>\n");
1026         wprintf("</FONT></TD></TR></TABLE>\n");
1027
1028         wprintf("<CENTER>\n");
1029         wprintf("If you know the name of a hidden (guess-name) or\n");
1030         wprintf("passworded room, you can enter that room by typing\n");
1031         wprintf("its name below.  Once you gain access to a private\n");
1032         wprintf("room, it will appear in your regular room listings\n");
1033         wprintf("so you don't have to keep returning here.\n");
1034         wprintf("<BR><BR>");
1035
1036         wprintf("<FORM METHOD=\"POST\" ACTION=\"/goto_private\">\n");
1037
1038         wprintf("<TABLE border><TR><TD>");
1039         wprintf("Enter room name:</TD><TD>");
1040         wprintf("<INPUT TYPE=\"text\" NAME=\"gr_name\" VALUE=\"%s\" MAXLENGTH=\"19\">\n", rname);
1041
1042         if (req_pass) {
1043                 wprintf("</TD></TR><TR><TD>");
1044                 wprintf("Enter room password:</TD><TD>");
1045                 wprintf("<INPUT TYPE=\"password\" NAME=\"gr_pass\" MAXLENGTH=\"9\">\n");
1046         }
1047         wprintf("</TD></TR></TABLE>\n");
1048
1049         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1050         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1051         wprintf("</FORM>\n");
1052         wDumpContent(1);
1053 }
1054
1055 /* 
1056  * goto a private room
1057  */
1058 void goto_private(void)
1059 {
1060         char hold_rm[32];
1061         char buf[256];
1062
1063         if (strcasecmp(bstr("sc"), "OK")) {
1064                 display_main_menu();
1065                 return;
1066         }
1067         strcpy(hold_rm, wc_roomname);
1068         strcpy(buf, "GOTO ");
1069         strcat(buf, bstr("gr_name"));
1070         strcat(buf, "|");
1071         strcat(buf, bstr("gr_pass"));
1072         serv_puts(buf);
1073         serv_gets(buf);
1074
1075         if (buf[0] == '2') {
1076                 smart_goto(bstr("gr_name"));
1077                 return;
1078         }
1079         if (!strncmp(buf, "540", 3)) {
1080                 display_private(bstr("gr_name"), 1);
1081                 return;
1082         }
1083         printf("HTTP/1.0 200 OK\n");
1084         output_headers(1);
1085         wprintf("%s\n", &buf[4]);
1086         wDumpContent(1);
1087         return;
1088 }
1089
1090
1091 /*
1092  * display the screen to zap a room
1093  */
1094 void display_zap(void)
1095 {
1096         printf("HTTP/1.0 200 OK\n");
1097         output_headers(1);
1098
1099         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1100         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1101         wprintf("<B>Zap (forget) the current room</B>\n");
1102         wprintf("</FONT></TD></TR></TABLE>\n");
1103
1104         wprintf("If you select this option, <em>%s</em> will ", wc_roomname);
1105         wprintf("disappear from your room list.  Is this what you wish ");
1106         wprintf("to do?<BR>\n");
1107
1108         wprintf("<FORM METHOD=\"POST\" ACTION=\"/zap\">\n");
1109         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1110         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1111         wprintf("</FORM>\n");
1112         wDumpContent(1);
1113 }
1114
1115
1116 /* 
1117  * zap a room
1118  */
1119 void zap(void)
1120 {
1121         char buf[256];
1122
1123         if (strcmp(bstr("sc"), "OK")) {
1124                 display_main_menu();
1125                 return;
1126         }
1127         serv_printf("GOTO %s", wc_roomname);
1128         serv_gets(buf);
1129         if (buf[0] != '2') {
1130                 display_error(&buf[4]);
1131                 return;
1132         }
1133         serv_puts("FORG");
1134         serv_gets(buf);
1135         if (buf[0] != '2') {
1136                 display_error(&buf[4]);
1137                 return;
1138         }
1139         smart_goto(bstr("_BASEROOM_"));
1140 }
1141
1142
1143
1144
1145 /*
1146  * Confirm deletion of the current room
1147  */
1148 void confirm_delete_room(void)
1149 {
1150         char buf[256];
1151
1152         serv_puts("KILL 0");
1153         serv_gets(buf);
1154         if (buf[0] != '2') {
1155                 display_error(&buf[4]);
1156                 return;
1157         }
1158         printf("HTTP/1.0 200 OK\n");
1159         output_headers(1);
1160         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1161         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1162         wprintf("<B>Confirm deletion of room</B>\n");
1163         wprintf("</FONT></TD></TR></TABLE>\n");
1164
1165         wprintf("<CENTER>");
1166         wprintf("<FORM METHOD=\"POST\" ACTION=\"/delete_room\">\n");
1167
1168         wprintf("Are you sure you want to delete <FONT SIZE=+1>");
1169         escputs(wc_roomname);
1170         wprintf("</FONT>?<BR>\n");
1171
1172         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Delete\">");
1173         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1174
1175         wprintf("</FORM></CENTER>\n");
1176         wDumpContent(1);
1177 }
1178
1179
1180 /*
1181  * Delete the current room
1182  */
1183 void delete_room(void)
1184 {
1185         char buf[256];
1186         char sc[256];
1187
1188         strcpy(sc, bstr("sc"));
1189
1190         if (strcasecmp(sc, "Delete")) {
1191                 display_error("Cancelled.  This room was not deleted.");
1192                 return;
1193         }
1194         serv_puts("KILL 1");
1195         serv_gets(buf);
1196         if (buf[0] != '2') {
1197                 display_error(&buf[4]);
1198         } else {
1199                 smart_goto("_BASEROOM_");
1200         }
1201 }