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