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