]> code.citadel.org Git - citadel.git/blob - webcit/roomops.c
* WebCit now sends the name of the end user's browser as the client
[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         static int remember_new_mail = (-1);
324
325         /* We need to have the information returned by a GOTO server command.
326          * If it isn't supplied, we fake it by issuing our own GOTO.
327          */
328         if (got == NULL) {
329                 serv_printf("GOTO %s", wc_roomname);
330                 serv_gets(fakegot);
331                 got = fakegot;
332         }
333
334         /* Check for new mail. */
335         new_mail = extract_int(&got[4], 9);
336
337         /* Now start spewing HTML. */
338         wprintf("<CENTER><TABLE border=0><TR>");
339
340         if ((strlen(ugname) > 0) && (strcasecmp(ugname, wc_roomname))) {
341                 wprintf("<TD VALIGN=TOP><A HREF=\"/ungoto\">");
342                 wprintf("<IMG SRC=\"/static/back.gif\" BORDER=0></A></TD>");
343         }
344         wprintf("<TD VALIGN=TOP><FONT FACE=\"Arial,Helvetica,sans-serif\"><FONT SIZE=+2>%s</FONT><BR>", wc_roomname);
345         wprintf("%d new of %d messages</FONT></TD>\n",
346                 extract_int(&got[4], 1),
347                 extract_int(&got[4], 2));
348
349         /* Display room graphic.  The server doesn't actually
350          * need the room name, but we supply it in order to
351          * keep the browser from using a cached graphic from 
352          * another room.
353          */
354         serv_puts("OIMG _roompic_");
355         serv_gets(buf);
356         if (buf[0] == '2') {
357                 wprintf("<TD><FONT FACE=\"Arial,Helvetica,sans-serif\">");
358                 wprintf("<IMG SRC=\"/image&name=_roompic_&room=");
359                 escputs(wc_roomname);
360                 wprintf("\"></FONT></TD>");
361                 serv_puts("CLOS");
362                 serv_gets(buf);
363         }
364         wprintf("<TD VALIGN=TOP><FONT FACE=\"Arial,Helvetica,sans-serif\">");
365         readinfo(0);
366         wprintf("</FONT></TD>");
367
368         /* Let the user know if new mail has arrived */
369         if ( (new_mail > remember_new_mail) && (new_mail>0) ) {
370                 wprintf("<TD VALIGN=TOP>"
371                         "<IMG SRC=\"/static/mail.gif\" border=0 "
372                         "ALT=\"You have new mail\">"
373                         "<BR><BLINK>%d</BLINK></TD>", new_mail);
374                 remember_new_mail = new_mail;
375         }
376
377         wprintf("<TD VALIGN=TOP><A HREF=\"/gotonext\">");
378         wprintf("<IMG SRC=\"/static/forward.gif\" border=0></A></TD>");
379         wprintf("</TR></TABLE></CENTER>\n");
380 }
381
382
383
384
385
386 /*
387  * generic routine to take the session to a new room
388  *
389  * display_name values:  0 = goto only
390  *                       1 = goto and display
391  *                       2 = display only
392  */
393 void gotoroom(char *gname, int display_name)
394 {
395         char buf[256];
396         static long ls = (-1L);
397
398
399         if (display_name) {
400                 printf("HTTP/1.0 200 OK\n");
401                 printf("Pragma: no-cache\n");
402                 printf("Cache-Control: no-store\n");
403                 output_headers(0);
404
405                 wprintf("<HTML><HEAD></HEAD>\n<BODY ");
406
407                 /* automatically fire up a read-new-msgs in the bottom frame */
408                 if (!noframes)
409                         wprintf("onload=parent.frames.bottom.location=\"/readnew\" ");
410
411                 wprintf("BACKGROUND=\"/image&name=background\" TEXT=\"#000000\" LINK=\"#004400\">\n");
412         }
413         if (display_name != 2) {
414                 /* store ungoto information */
415                 strcpy(ugname, wc_roomname);
416                 uglsn = ls;
417         }
418         /* move to the new room */
419         serv_printf("GOTO %s", gname);
420         serv_gets(buf);
421         if (buf[0] != '2') {
422                 serv_puts("GOTO _BASEROOM_");
423                 serv_gets(buf);
424         }
425         if (buf[0] != '2') {
426                 if (display_name) {
427                         wprintf("<EM>%s</EM><BR>\n", &buf[4]);
428                         wDumpContent(1);
429                 }
430                 return;
431         }
432         extract(wc_roomname, &buf[4], 0);
433         room_flags = extract_int(&buf[4], 4);
434         /* highest_msg_read = extract_int(&buf[4],6);
435            maxmsgnum = extract_int(&buf[4],5);
436            is_mail = (char) extract_int(&buf[4],7); */
437         ls = extract_long(&buf[4], 6);
438
439         if (is_aide)
440                 is_room_aide = is_aide;
441         else
442                 is_room_aide = (char) extract_int(&buf[4], 8);
443
444         remove_march(wc_roomname);
445         if (!strcasecmp(gname, "_BASEROOM_"))
446                 remove_march(gname);
447
448         /* Display the room banner */
449         if (display_name) {
450                 embed_room_banner(buf);
451                 wDumpContent(1);
452         }
453         strcpy(wc_roomname, wc_roomname);
454 }
455
456
457 /*
458  * Locate the room on the march list which we most want to go to.  Each room
459  * is measured given a "weight" of preference based on various factors.
460  */
461 char *pop_march(int desired_floor)
462 {
463         static char TheRoom[64];
464         int TheFloor = 0;
465         int TheOrder = 32767;
466         int TheWeight = 0;
467         int weight;
468         struct march *mptr = NULL;
469
470         strcpy(TheRoom, "_BASEROOM_");
471         if (march == NULL)
472                 return (TheRoom);
473
474         for (mptr = march; mptr != NULL; mptr = mptr->next) {
475                 weight = 0;
476                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
477                         weight = weight + 10000;
478                 if (mptr->march_floor == desired_floor)
479                         weight = weight + 5000;
480
481                 weight = weight + ((128 - (mptr->march_floor)) * 128);
482                 weight = weight + (128 - (mptr->march_order));
483
484                 if (weight > TheWeight) {
485                         TheWeight = weight;
486                         strcpy(TheRoom, mptr->march_name);
487                         TheFloor = mptr->march_floor;
488                         TheOrder = mptr->march_order;
489                 }
490         }
491         return (TheRoom);
492 }
493
494
495
496 /* Goto next room having unread messages.
497  * We want to skip over rooms that the user has already been to, and take the
498  * user back to the lobby when done.  The room we end up in is placed in
499  * newroom - which is set to 0 (the lobby) initially.
500  * We start the search in the current room rather than the beginning to prevent
501  * two or more concurrent users from dragging each other back to the same room.
502  */
503 void gotonext(void)
504 {
505         char buf[256];
506         struct march *mptr, *mptr2;
507         char next_room[32];
508
509         /* First check to see if the march-mode list is already allocated.
510          * If it is, pop the first room off the list and go there.
511          */
512
513         if (march == NULL) {
514                 serv_puts("LKRN");
515                 serv_gets(buf);
516                 if (buf[0] == '1')
517                         while (serv_gets(buf), strcmp(buf, "000")) {
518                                 mptr = (struct march *) malloc(sizeof(struct march));
519                                 mptr->next = NULL;
520                                 extract(mptr->march_name, buf, 0);
521                                 mptr->march_floor = extract_int(buf, 2);
522                                 mptr->march_order = extract_int(buf, 3);
523                                 if (march == NULL) {
524                                         march = mptr;
525                                 } else {
526                                         mptr2 = march;
527                                         while (mptr2->next != NULL)
528                                                 mptr2 = mptr2->next;
529                                         mptr2->next = mptr;
530                                 }
531                         }
532 /* add _BASEROOM_ to the end of the march list, so the user will end up
533  * in the system base room (usually the Lobby>) at the end of the loop
534  */
535                 mptr = (struct march *) malloc(sizeof(struct march));
536                 mptr->next = NULL;
537                 strcpy(mptr->march_name, "_BASEROOM_");
538                 if (march == NULL) {
539                         march = mptr;
540                 } else {
541                         mptr2 = march;
542                         while (mptr2->next != NULL)
543                                 mptr2 = mptr2->next;
544                         mptr2->next = mptr;
545                 }
546 /*
547  * ...and remove the room we're currently in, so a <G>oto doesn't make us
548  * walk around in circles
549  */
550                 remove_march(wc_roomname);
551         }
552         if (march != NULL) {
553                 strcpy(next_room, pop_march(-1));
554         } else {
555                 strcpy(next_room, "_BASEROOM_");
556         }
557
558
559         smart_goto(next_room);
560 }
561
562
563 void smart_goto(char *next_room) {
564         /* In noframes mode, we goto the room silently, then do a
565          * read-new-messages which causes the banner to show up anyway.
566          */
567         if (noframes) {
568                 gotoroom(next_room, 0);
569                 readloop("readnew");
570         } else {
571         /* In frames mode, we let gotoroom() bring up the banner, which then
572          * uses JavaScript to bring up the new-messages display in the
573          * bottom frame.
574          */
575                 gotoroom(next_room, 1);
576         }
577 }
578
579
580
581 /*
582  * mark all messages in current room as having been read
583  */
584 void slrp_highest(void)
585 {
586         char buf[256];
587
588         /* set pointer */
589         serv_puts("SLRP HIGHEST");
590         serv_gets(buf);
591         if (buf[0] != '2') {
592                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
593                 return;
594         }
595 }
596
597
598 /*
599  * un-goto the previous room
600  */
601 void ungoto(void)
602 {
603         char buf[256];
604
605         if (!strcmp(ugname, "")) {
606                 smart_goto(wc_roomname);
607                 return;
608         }
609         serv_printf("GOTO %s", ugname);
610         serv_gets(buf);
611         if (buf[0] != '2') {
612                 smart_goto(wc_roomname);
613                 return;
614         }
615         if (uglsn >= 0L) {
616                 serv_printf("SLRP %ld", uglsn);
617                 serv_gets(buf);
618         }
619         strcpy(buf, ugname);
620         strcpy(ugname, "");
621         smart_goto(buf);
622 }
623
624 /*
625  * display the form for editing a room
626  */
627 void display_editroom(void)
628 {
629         char buf[256];
630         char er_name[20];
631         char er_password[10];
632         char er_dirname[15];
633         char er_roomaide[26];
634         unsigned er_flags;
635         int er_floor;
636         int i;
637
638         serv_puts("GETR");
639         serv_gets(buf);
640
641         if (buf[0] != '2') {
642                 display_error(&buf[4]);
643                 return;
644         }
645         extract(er_name, &buf[4], 0);
646         extract(er_password, &buf[4], 1);
647         extract(er_dirname, &buf[4], 2);
648         er_flags = extract_int(&buf[4], 3);
649         er_floor = extract_int(&buf[4], 4);
650
651
652         printf("HTTP/1.0 200 OK\n");
653         output_headers(1);
654
655         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
656         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
657         wprintf("<B>Edit this room</B>\n");
658         wprintf("</FONT></TD></TR></TABLE>\n");
659
660         wprintf("<FORM METHOD=\"POST\" ACTION=\"/editroom\">\n");
661
662         wprintf("<UL><LI>Name of room: ");
663         wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\"19\">\n", er_name);
664
665         wprintf("<LI>Resides on floor: ");
666         load_floorlist();
667         wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
668         for (i = 0; i < 128; ++i)
669                 if (strlen(floorlist[i]) > 0) {
670                         wprintf("<OPTION ");
671                         if (i == er_floor)
672                                 wprintf("SELECTED ");
673                         wprintf("VALUE=\"%d\">", i);
674                         escputs(floorlist[i]);
675                         wprintf("</OPTION>\n");
676                 }
677         wprintf("</SELECT>\n");
678
679         wprintf("<LI>Type of room:<UL>\n");
680
681         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
682         if ((er_flags & QR_PRIVATE) == 0)
683                 wprintf("CHECKED ");
684         wprintf("> Public room\n");
685
686         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
687         if ((er_flags & QR_PRIVATE) &&
688             (er_flags & QR_GUESSNAME))
689                 wprintf("CHECKED ");
690         wprintf("> Private - guess name\n");
691
692         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
693         if ((er_flags & QR_PRIVATE) &&
694             (er_flags & QR_PASSWORDED))
695                 wprintf("CHECKED ");
696         wprintf("> Private - require password:\n");
697         wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n", er_password);
698
699         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
700         if ((er_flags & QR_PRIVATE)
701             && ((er_flags & QR_GUESSNAME) == 0)
702             && ((er_flags & QR_PASSWORDED) == 0))
703                 wprintf("CHECKED ");
704         wprintf("> Private - invitation only\n");
705
706         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
707         wprintf("> If private, cause current users to forget room\n");
708
709         wprintf("</UL>\n");
710
711         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
712         if (er_flags & QR_PREFONLY)
713                 wprintf("CHECKED ");
714         wprintf("> Preferred users only\n");
715
716         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
717         if (er_flags & QR_READONLY)
718                 wprintf("CHECKED ");
719         wprintf("> Read-only room\n");
720
721 /* directory stuff */
722         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
723         if (er_flags & QR_DIRECTORY)
724                 wprintf("CHECKED ");
725         wprintf("> File directory room\n");
726
727         wprintf("<UL><LI>Directory name: ");
728         wprintf("<INPUT TYPE=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n", er_dirname);
729
730         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
731         if (er_flags & QR_UPLOAD)
732                 wprintf("CHECKED ");
733         wprintf("> Uploading allowed\n");
734
735         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
736         if (er_flags & QR_DOWNLOAD)
737                 wprintf("CHECKED ");
738         wprintf("> Downloading allowed\n");
739
740         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
741         if (er_flags & QR_VISDIR)
742                 wprintf("CHECKED ");
743         wprintf("> Visible directory</UL>\n");
744
745 /* end of directory stuff */
746
747         wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
748         if (er_flags & QR_NETWORK)
749                 wprintf("CHECKED ");
750         wprintf("> Network shared room\n");
751
752 /* start of anon options */
753
754         wprintf("<LI>Anonymous messages<UL>\n");
755
756         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
757         if (((er_flags & QR_ANONONLY) == 0)
758             && ((er_flags & QR_ANONOPT) == 0))
759                 wprintf("CHECKED ");
760         wprintf("> No anonymous messages\n");
761
762         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
763         if (er_flags & QR_ANONONLY)
764                 wprintf("CHECKED ");
765         wprintf("> All messages are anonymous\n");
766
767         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
768         if (er_flags & QR_ANONOPT)
769                 wprintf("CHECKED ");
770         wprintf("> Prompt user when entering messages</UL>\n");
771
772 /* end of anon options */
773
774         wprintf("<LI>Room aide: \n");
775         serv_puts("GETA");
776         serv_gets(buf);
777         if (buf[0] != '2') {
778                 wprintf("<EM>%s</EM>\n", &buf[4]);
779         } else {
780                 extract(er_roomaide, &buf[4], 0);
781                 wprintf("<INPUT TYPE=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
782         }
783
784         wprintf("</UL><CENTER>\n");
785         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
786         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
787         wprintf("</CENTER>\n");
788
789         wDumpContent(1);
790 }
791
792
793 /*
794  * save new parameters for a room
795  */
796 void editroom(void)
797 {
798         char buf[256];
799         char er_name[20];
800         char er_password[10];
801         char er_dirname[15];
802         char er_roomaide[26];
803         int er_floor;
804         unsigned er_flags;
805         int bump;
806
807
808         if (strcmp(bstr("sc"), "OK")) {
809                 display_error("Cancelled.  Changes were not saved.");
810                 return;
811         }
812         serv_puts("GETR");
813         serv_gets(buf);
814
815         if (buf[0] != '2') {
816                 display_error(&buf[4]);
817                 return;
818         }
819         extract(er_name, &buf[4], 0);
820         extract(er_password, &buf[4], 1);
821         extract(er_dirname, &buf[4], 2);
822         er_flags = extract_int(&buf[4], 3);
823
824         strcpy(er_roomaide, bstr("er_roomaide"));
825         if (strlen(er_roomaide) == 0) {
826                 serv_puts("GETA");
827                 serv_gets(buf);
828                 if (buf[0] != '2') {
829                         strcpy(er_roomaide, "");
830                 } else {
831                         extract(er_roomaide, &buf[4], 0);
832                 }
833         }
834         strcpy(buf, bstr("er_name"));
835         buf[20] = 0;
836         if (strlen(buf) > 0)
837                 strcpy(er_name, buf);
838
839         strcpy(buf, bstr("er_password"));
840         buf[10] = 0;
841         if (strlen(buf) > 0)
842                 strcpy(er_password, buf);
843
844         strcpy(buf, bstr("er_dirname"));
845         buf[15] = 0;
846         if (strlen(buf) > 0)
847                 strcpy(er_dirname, buf);
848
849         strcpy(buf, bstr("type"));
850         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
851
852         if (!strcmp(buf, "invonly")) {
853                 er_flags |= (QR_PRIVATE);
854         }
855         if (!strcmp(buf, "guessname")) {
856                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
857         }
858         if (!strcmp(buf, "passworded")) {
859                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
860         }
861         if (!strcmp(bstr("prefonly"), "yes")) {
862                 er_flags |= QR_PREFONLY;
863         } else {
864                 er_flags &= ~QR_PREFONLY;
865         }
866
867         if (!strcmp(bstr("readonly"), "yes")) {
868                 er_flags |= QR_READONLY;
869         } else {
870                 er_flags &= ~QR_READONLY;
871         }
872
873         if (!strcmp(bstr("network"), "yes")) {
874                 er_flags |= QR_NETWORK;
875         } else {
876                 er_flags &= ~QR_NETWORK;
877         }
878
879         if (!strcmp(bstr("directory"), "yes")) {
880                 er_flags |= QR_DIRECTORY;
881         } else {
882                 er_flags &= ~QR_DIRECTORY;
883         }
884
885         if (!strcmp(bstr("ulallowed"), "yes")) {
886                 er_flags |= QR_UPLOAD;
887         } else {
888                 er_flags &= ~QR_UPLOAD;
889         }
890
891         if (!strcmp(bstr("dlallowed"), "yes")) {
892                 er_flags |= QR_DOWNLOAD;
893         } else {
894                 er_flags &= ~QR_DOWNLOAD;
895         }
896
897         if (!strcmp(bstr("visdir"), "yes")) {
898                 er_flags |= QR_VISDIR;
899         } else {
900                 er_flags &= ~QR_VISDIR;
901         }
902
903         strcpy(buf, bstr("anon"));
904
905         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
906         if (!strcmp(buf, "anononly"))
907                 er_flags |= QR_ANONONLY;
908         if (!strcmp(buf, "anon2"))
909                 er_flags |= QR_ANONOPT;
910
911         bump = 0;
912         if (!strcmp(bstr("bump"), "yes"))
913                 bump = 1;
914
915         er_floor = atoi(bstr("er_floor"));
916
917         sprintf(buf, "SETR %s|%s|%s|%u|%d|%d",
918              er_name, er_password, er_dirname, er_flags, bump, er_floor);
919         serv_puts(buf);
920         serv_gets(buf);
921         if (buf[0] != '2') {
922                 display_error(&buf[4]);
923                 return;
924         }
925         gotoroom(er_name, 0);
926
927         if (strlen(er_roomaide) > 0) {
928                 sprintf(buf, "SETA %s", er_roomaide);
929                 serv_puts(buf);
930                 serv_gets(buf);
931                 if (buf[0] != '2') {
932                         display_error(&buf[4]);
933                         return;
934                 }
935         }
936         smart_goto(er_name);
937 }
938
939
940
941 /*
942  * display the form for entering a new room
943  */
944 void display_entroom(void)
945 {
946         char buf[256];
947
948         serv_puts("CRE8 0");
949         serv_gets(buf);
950
951         if (buf[0] != '2') {
952                 display_error(&buf[4]);
953                 return;
954         }
955         printf("HTTP/1.0 200 OK\n");
956         output_headers(1);
957
958         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
959         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
960         wprintf("<B>Enter (create) a new room</B>\n");
961         wprintf("</FONT></TD></TR></TABLE>\n");
962
963         wprintf("<FORM METHOD=\"POST\" ACTION=\"/entroom\">\n");
964
965         wprintf("<UL><LI>Name of room: ");
966         wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" MAXLENGTH=\"19\">\n");
967
968         wprintf("<LI>Type of room:<UL>\n");
969
970         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
971         wprintf("CHECKED > Public room\n");
972
973         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"guessname\" ");
974         wprintf("> Private - guess name\n");
975
976         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
977         wprintf("> Private - require password:\n");
978         wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
979
980         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
981         wprintf("> Private - invitation only\n");
982
983         wprintf("<CENTER>\n");
984         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
985         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
986         wprintf("</CENTER>\n");
987         wprintf("</FORM>\n");
988         wDumpContent(1);
989 }
990
991
992
993 /*
994  * enter a new room
995  */
996 void entroom(void)
997 {
998         char buf[256];
999         char er_name[20];
1000         char er_type[20];
1001         char er_password[10];
1002         int er_num_type;
1003
1004         if (strcmp(bstr("sc"), "OK")) {
1005                 display_error("Cancelled.  No new room was created.");
1006                 return;
1007         }
1008         strcpy(er_name, bstr("er_name"));
1009         strcpy(er_type, bstr("type"));
1010         strcpy(er_password, bstr("er_password"));
1011
1012         er_num_type = 0;
1013         if (!strcmp(er_type, "guessname"))
1014                 er_num_type = 1;
1015         if (!strcmp(er_type, "passworded"))
1016                 er_num_type = 2;
1017         if (!strcmp(er_type, "invonly"))
1018                 er_num_type = 3;
1019
1020         sprintf(buf, "CRE8 1|%s|%d|%s", er_name, er_num_type, er_password);
1021         serv_puts(buf);
1022         serv_gets(buf);
1023         if (buf[0] != '2') {
1024                 display_error(&buf[4]);
1025                 return;
1026         }
1027         smart_goto(er_name);
1028 }
1029
1030
1031 /*
1032  * display the screen to enter a private room
1033  */
1034 void display_private(char *rname, int req_pass)
1035 {
1036
1037         printf("HTTP/1.0 200 OK\n");
1038         output_headers(1);
1039
1040         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1041         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1042         wprintf("<B>Goto a private room</B>\n");
1043         wprintf("</FONT></TD></TR></TABLE>\n");
1044
1045         wprintf("<CENTER>\n");
1046         wprintf("If you know the name of a hidden (guess-name) or\n");
1047         wprintf("passworded room, you can enter that room by typing\n");
1048         wprintf("its name below.  Once you gain access to a private\n");
1049         wprintf("room, it will appear in your regular room listings\n");
1050         wprintf("so you don't have to keep returning here.\n");
1051         wprintf("<BR><BR>");
1052
1053         wprintf("<FORM METHOD=\"POST\" ACTION=\"/goto_private\">\n");
1054
1055         wprintf("<TABLE border><TR><TD>");
1056         wprintf("Enter room name:</TD><TD>");
1057         wprintf("<INPUT TYPE=\"text\" NAME=\"gr_name\" VALUE=\"%s\" MAXLENGTH=\"19\">\n", rname);
1058
1059         if (req_pass) {
1060                 wprintf("</TD></TR><TR><TD>");
1061                 wprintf("Enter room password:</TD><TD>");
1062                 wprintf("<INPUT TYPE=\"password\" NAME=\"gr_pass\" MAXLENGTH=\"9\">\n");
1063         }
1064         wprintf("</TD></TR></TABLE>\n");
1065
1066         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1067         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1068         wprintf("</FORM>\n");
1069         wDumpContent(1);
1070 }
1071
1072 /* 
1073  * goto a private room
1074  */
1075 void goto_private(void)
1076 {
1077         char hold_rm[32];
1078         char buf[256];
1079
1080         if (strcasecmp(bstr("sc"), "OK")) {
1081                 display_main_menu();
1082                 return;
1083         }
1084         strcpy(hold_rm, wc_roomname);
1085         strcpy(buf, "GOTO ");
1086         strcat(buf, bstr("gr_name"));
1087         strcat(buf, "|");
1088         strcat(buf, bstr("gr_pass"));
1089         serv_puts(buf);
1090         serv_gets(buf);
1091
1092         if (buf[0] == '2') {
1093                 smart_goto(bstr("gr_name"));
1094                 return;
1095         }
1096         if (!strncmp(buf, "540", 3)) {
1097                 display_private(bstr("gr_name"), 1);
1098                 return;
1099         }
1100         printf("HTTP/1.0 200 OK\n");
1101         output_headers(1);
1102         wprintf("%s\n", &buf[4]);
1103         wDumpContent(1);
1104         return;
1105 }
1106
1107
1108 /*
1109  * display the screen to zap a room
1110  */
1111 void display_zap(void)
1112 {
1113         printf("HTTP/1.0 200 OK\n");
1114         output_headers(1);
1115
1116         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1117         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1118         wprintf("<B>Zap (forget) the current room</B>\n");
1119         wprintf("</FONT></TD></TR></TABLE>\n");
1120
1121         wprintf("If you select this option, <em>%s</em> will ", wc_roomname);
1122         wprintf("disappear from your room list.  Is this what you wish ");
1123         wprintf("to do?<BR>\n");
1124
1125         wprintf("<FORM METHOD=\"POST\" ACTION=\"/zap\"");
1126         if (!noframes) wprintf(" TARGET=top");
1127         wprintf(">\n<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"OK\">");
1128         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1129         wprintf("</FORM>\n");
1130         wDumpContent(1);
1131 }
1132
1133
1134 /* 
1135  * zap a room
1136  */
1137 void zap(void)
1138 {
1139         char buf[256];
1140         char final_destination[256];
1141
1142         /* If the forget-room routine fails for any reason, we fall back
1143          * to the current room; otherwise, we go to the Lobby
1144          */
1145         strcpy(final_destination, wc_roomname);
1146
1147         if (!strcasecmp(bstr("sc"), "OK")) {
1148                 serv_printf("GOTO %s", wc_roomname);
1149                 serv_gets(buf);
1150                 if (buf[0] != '2') {
1151                         ExpressMessageCat(&buf[4]);
1152                 } else {
1153                         serv_puts("FORG");
1154                         serv_gets(buf);
1155                         if (buf[0] != '2') {
1156                                 ExpressMessageCat(&buf[4]);
1157                         } else {
1158                                 strcpy(final_destination, "_BASEROOM_");
1159                         }
1160                 }
1161         }
1162         smart_goto(final_destination);
1163 }
1164
1165
1166
1167
1168 /*
1169  * Confirm deletion of the current room
1170  */
1171 void confirm_delete_room(void)
1172 {
1173         char buf[256];
1174
1175         serv_puts("KILL 0");
1176         serv_gets(buf);
1177         if (buf[0] != '2') {
1178                 display_error(&buf[4]);
1179                 return;
1180         }
1181         printf("HTTP/1.0 200 OK\n");
1182         output_headers(1);
1183         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
1184         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1185         wprintf("<B>Confirm deletion of room</B>\n");
1186         wprintf("</FONT></TD></TR></TABLE>\n");
1187
1188         wprintf("<CENTER>");
1189         wprintf("<FORM METHOD=\"POST\" ACTION=\"/delete_room\">\n");
1190
1191         wprintf("Are you sure you want to delete <FONT SIZE=+1>");
1192         escputs(wc_roomname);
1193         wprintf("</FONT>?<BR>\n");
1194
1195         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Delete\">");
1196         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
1197
1198         wprintf("</FORM></CENTER>\n");
1199         wDumpContent(1);
1200 }
1201
1202
1203 /*
1204  * Delete the current room
1205  */
1206 void delete_room(void)
1207 {
1208         char buf[256];
1209         char sc[256];
1210
1211         strcpy(sc, bstr("sc"));
1212
1213         if (strcasecmp(sc, "Delete")) {
1214                 display_error("Cancelled.  This room was not deleted.");
1215                 return;
1216         }
1217         serv_puts("KILL 1");
1218         serv_gets(buf);
1219         if (buf[0] != '2') {
1220                 display_error(&buf[4]);
1221         } else {
1222                 smart_goto("_BASEROOM_");
1223         }
1224 }