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