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