* Removed all of the absolute URL's.
[citadel.git] / webcit / roomops.c
1 /*
2  * $Id$
3  *
4  * Lots of different room-related operations.
5  */
6
7 #include "webcit.h"
8
9 struct folder {
10         int floor;
11         char room[SIZ];
12         char name[SIZ];
13         int hasnewmsgs;
14         int is_mailbox;
15         int selectable;
16         int view;
17 };
18
19 char *viewdefs[] = {
20         "Bulletin Board",
21         "Mail Folder",
22         "Address Book",
23         "Calendar",
24         "Task List",
25         "Notes List"
26 };
27
28 char floorlist[128][SIZ];
29
30 /*
31  * load the list of floors
32  */
33 void load_floorlist(void)
34 {
35         int a;
36         char buf[SIZ];
37
38         for (a = 0; a < 128; ++a)
39                 floorlist[a][0] = 0;
40
41         serv_puts("LFLR");
42         serv_getln(buf, sizeof buf);
43         if (buf[0] != '1') {
44                 strcpy(floorlist[0], "Main Floor");
45                 return;
46         }
47         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
48                 extract_token(floorlist[extract_int(buf, 0)], buf, 1, '|', sizeof floorlist[0]);
49         }
50 }
51
52
53 /*
54  * remove a room from the march list
55  */
56 void remove_march(char *aaa)
57 {
58         struct march *mptr, *mptr2;
59
60         if (WC->march == NULL)
61                 return;
62
63         if (!strcasecmp(WC->march->march_name, aaa)) {
64                 mptr = WC->march->next;
65                 free(WC->march);
66                 WC->march = mptr;
67                 return;
68         }
69         mptr2 = WC->march;
70         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
71                 if (!strcasecmp(mptr->march_name, aaa)) {
72                         mptr2->next = mptr->next;
73                         free(mptr);
74                         mptr = mptr2;
75                 } else {
76                         mptr2 = mptr;
77                 }
78         }
79 }
80
81
82
83
84
85 void room_tree_list(struct roomlisting *rp)
86 {
87         char rmname[64];
88         int f;
89
90         if (rp == NULL) {
91                 return;
92         }
93
94         room_tree_list(rp->lnext);
95
96         strcpy(rmname, rp->rlname);
97         f = rp->rlflags;
98
99         wprintf("<a href=\"dotgoto&room=");
100         urlescputs(rmname);
101         wprintf("\"");
102         wprintf(">");
103         escputs1(rmname, 1, 1);
104         if ((f & QR_DIRECTORY) && (f & QR_NETWORK))
105                 wprintf("}");
106         else if (f & QR_DIRECTORY)
107                 wprintf("]");
108         else if (f & QR_NETWORK)
109                 wprintf(")");
110         else
111                 wprintf("&gt;");
112         wprintf("</A><TT> </TT>\n");
113
114         room_tree_list(rp->rnext);
115         free(rp);
116 }
117
118
119 /* 
120  * Room ordering stuff (compare first by floor, then by order)
121  */
122 int rordercmp(struct roomlisting *r1, struct roomlisting *r2)
123 {
124         if ((r1 == NULL) && (r2 == NULL))
125                 return (0);
126         if (r1 == NULL)
127                 return (-1);
128         if (r2 == NULL)
129                 return (1);
130         if (r1->rlfloor < r2->rlfloor)
131                 return (-1);
132         if (r1->rlfloor > r2->rlfloor)
133                 return (1);
134         if (r1->rlorder < r2->rlorder)
135                 return (-1);
136         if (r1->rlorder > r2->rlorder)
137                 return (1);
138         return (0);
139 }
140
141
142 /*
143  * Common code for all room listings
144  */
145 void listrms(char *variety)
146 {
147         char buf[SIZ];
148         int num_rooms = 0;
149
150         struct roomlisting *rl = NULL;
151         struct roomlisting *rp;
152         struct roomlisting *rs;
153
154
155         /* Ask the server for a room list */
156         serv_puts(variety);
157         serv_getln(buf, sizeof buf);
158         if (buf[0] != '1') {
159                 wprintf("&nbsp;");
160                 return;
161         }
162         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
163                 ++num_rooms;
164                 rp = malloc(sizeof(struct roomlisting));
165                 extract_token(rp->rlname, buf, 0, '|', sizeof rp->rlname);
166                 rp->rlflags = extract_int(buf, 1);
167                 rp->rlfloor = extract_int(buf, 2);
168                 rp->rlorder = extract_int(buf, 3);
169                 rp->lnext = NULL;
170                 rp->rnext = NULL;
171
172                 rs = rl;
173                 if (rl == NULL) {
174                         rl = rp;
175                 } else
176                         while (rp != NULL) {
177                                 if (rordercmp(rp, rs) < 0) {
178                                         if (rs->lnext == NULL) {
179                                                 rs->lnext = rp;
180                                                 rp = NULL;
181                                         } else {
182                                                 rs = rs->lnext;
183                                         }
184                                 } else {
185                                         if (rs->rnext == NULL) {
186                                                 rs->rnext = rp;
187                                                 rp = NULL;
188                                         } else {
189                                                 rs = rs->rnext;
190                                         }
191                                 }
192                         }
193         }
194
195         room_tree_list(rl);
196
197         /* If no rooms were listed, print an nbsp to make the cell
198          * borders show up anyway.
199          */
200         if (num_rooms == 0) wprintf("&nbsp;");
201 }
202
203
204 /*
205  * list all forgotten rooms
206  */
207 void zapped_list(void)
208 {
209         output_headers(1, 1, 0, 0, 0, 0);
210
211         svprintf("BOXTITLE", WCS_STRING, _("Zapped (forgotten) rooms"));
212         do_template("beginbox");
213
214         listrms("LZRM -1");
215
216         wprintf("<br /><br />\n");
217         wprintf(_("Click on any room to un-zap it and goto that room.\n"));
218         do_template("endbox");
219         wDumpContent(1);
220 }
221
222
223 /*
224  * read this room's info file (set v to 1 for verbose mode)
225  */
226 void readinfo(void)
227 {
228         char buf[SIZ];
229
230         serv_puts("RINF");
231         serv_getln(buf, sizeof buf);
232         if (buf[0] == '1') {
233                 fmout("CENTER");
234         }
235 }
236
237
238
239
240 /* Display room banner icon.  The server doesn't actually
241  * need the room name, but we supply it in order to
242  * keep the browser from using a cached icon from 
243  * another room.
244  */
245 void embed_room_graphic(void) {
246         char buf[SIZ];
247
248         serv_puts("OIMG _roompic_");
249         serv_getln(buf, sizeof buf);
250         if (buf[0] == '2') {
251                 wprintf("<IMG HEIGHT=64 src=\"image&name=_roompic_&room=");
252                 urlescputs(WC->wc_roomname);
253                 wprintf("\">");
254                 serv_puts("CLOS");
255                 serv_getln(buf, sizeof buf);
256         }
257         else if (WC->wc_view == VIEW_ADDRESSBOOK) {
258                 wprintf("<img height=48 width=48 src=\""
259                         "static/viewcontacts_48x.gif"
260                         "\">"
261                 );
262         }
263         else if (WC->wc_view == VIEW_CALENDAR) {
264                 wprintf("<img height=48 width=48 src=\""
265                         "static/calarea_48x.gif"
266                         "\">"
267                 );
268         }
269         else if (WC->wc_view == VIEW_TASKS) {
270                 wprintf("<img height=48 width=48 src=\""
271                         "static/taskmanag_48x.gif"
272                         "\">"
273                 );
274         }
275         else if (WC->wc_view == VIEW_NOTES) {
276                 wprintf("<img height=48 width=48 src=\""
277                         "static/storenotes_48x.gif"
278                         "\">"
279                 );
280         }
281         else if (WC->wc_view == VIEW_MAILBOX) {
282                 wprintf("<img height=48 width=48 src=\""
283                         "static/privatemess_48x.gif"
284                         "\">"
285                 );
286         }
287         else {
288                 wprintf("<img height=48 width=48 src=\""
289                         "static/chatrooms_48x.gif"
290                         "\">"
291                 );
292         }
293
294 }
295
296
297
298 /*
299  * Display the current view and offer an option to change it
300  */
301 void embed_view_o_matic(void) {
302         int i;
303
304         wprintf("<form name=\"viewomatic\" action=\"changeview\">\n"
305                 "<span class=\"room_banner_new_messages\">View as: "
306                 "<SELECT NAME=\"newview\" SIZE=\"1\" "
307                 "STYLE=\"font-family: Bitstream Vera Sans,Arial,Helvetica,sans-serif;"
308                 " font-size: 7pt; background: #444455; color: #ddddcc;\" "
309                 "OnChange=\"location.href=viewomatic.newview.options"
310                 "[selectedIndex].value\">\n");
311
312         for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
313                 /*
314                  * Only offer the views that make sense, given the default
315                  * view for the room.  For example, don't offer a Calendar
316                  * view in a non-Calendar room.
317                  */
318                 if (
319                         (i == WC->wc_view)
320                    ||   (i == WC->wc_default_view)
321                    ||   ( (i == 0) && (WC->wc_default_view == 1) )
322                    ||   ( (i == 1) && (WC->wc_default_view == 0) )
323                 ) {
324
325                         wprintf("<OPTION %s VALUE=\"/changeview?view=%d\">",
326                                 ((i == WC->wc_view) ? "SELECTED" : ""),
327                                 i );
328                         escputs(viewdefs[i]);
329                         wprintf("</OPTION>\n");
330                 }
331         }
332         wprintf("</select></span></form>\n");
333 }
334
335
336
337 void embed_room_banner(char *got, int navbar_style) {
338         char fakegot[SIZ];
339
340         /* We need to have the information returned by a GOTO server command.
341          * If it isn't supplied, we fake it by issuing our own GOTO.
342          */
343         if (got == NULL) {
344                 serv_printf("GOTO %s", WC->wc_roomname);
345                 serv_getln(fakegot, sizeof fakegot);
346                 got = fakegot;
347         }
348
349         /* If the user happens to select the "make this my start page" link,
350          * we want it to remember the URL as a "/dotskip" one instead of
351          * a "skip" or "gotonext" or something like that.
352          */
353         snprintf(WC->this_page, sizeof(WC->this_page), "/dotskip&room=%s",
354                 WC->wc_roomname);
355
356         /* Check for new mail. */
357         WC->new_mail = extract_int(&got[4], 9);
358         WC->wc_view = extract_int(&got[4], 11);
359
360         svprintf("ROOMNAME", WCS_STRING, "%s", WC->wc_roomname);
361         svprintf("NEWMSGS", WCS_STRING, "%d", extract_int(&got[4], 1));
362         svprintf("TOTALMSGS", WCS_STRING, "%d", extract_int(&got[4], 2));
363         svcallback("ROOMPIC", embed_room_graphic);
364         svcallback("ROOMINFO", readinfo);
365         svcallback("VIEWOMATIC", embed_view_o_matic);
366         svcallback("START", offer_start_page);
367
368         do_template("roombanner");
369         if (navbar_style != navbar_none) {
370
371                 wprintf("<div style=\"position:absolute; bottom:0px; left:0px\">\n"
372                         "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr>\n");
373
374
375                 if (navbar_style == navbar_default) wprintf(
376                         "<td>"
377                         "<a href=\"ungoto\">"
378                         "<img align=\"middle\" src=\"static/ungoto2_24x.gif\" border=\"0\">"
379                         "<span class=\"navbar_link\">%s</span></A>"
380                         "</td>\n", _("Ungoto")
381                 );
382
383                 if ( (navbar_style == navbar_default) && (WC->wc_view == VIEW_BBS) ) {
384                         wprintf(
385                                 "<td>"
386                                 "<a href=\"readnew\">"
387                                 "<img align=\"middle\" src=\"static/newmess2_24x.gif\" border=\"0\">"
388                                 "<span class=\"navbar_link\">%s</span></A>"
389                                 "</td>\n", _("Read new messages")
390                         );
391                 }
392
393                 if (navbar_style == navbar_default) {
394                         switch(WC->wc_view) {
395                                 case VIEW_ADDRESSBOOK:
396                                         wprintf(
397                                                 "<td>"
398                                                 "<a href=\"readfwd\">"
399                                                 "<img align=\"middle\" src=\"static/viewcontacts_24x.gif\" "
400                                                 "border=\"0\">"
401                                                 "<span class=\"navbar_link\">"
402                                                 "%s"
403                                                 "</span></a></td>\n", _("View contacts")
404                                         );
405                                         break;
406                                 case VIEW_CALENDAR:
407                                         wprintf(
408                                                 "<td>"
409                                                 "<a href=\"readfwd?calview=day\">"
410                                                 "<img align=\"middle\" src=\"static/taskday2_24x.gif\" "
411                                                 "border=\"0\">"
412                                                 "<span class=\"navbar_link\">"
413                                                 "%s"
414                                                 "</span></a></td>\n", _("Day view")
415                                         );
416                                         wprintf(
417                                                 "<td>"
418                                                 "<a href=\"readfwd?calview=month\">"
419                                                 "<img align=\"middle\" src=\"static/monthview2_24x.gif\" "
420                                                 "border=\"0\">"
421                                                 "<span class=\"navbar_link\">"
422                                                 "%s"
423                                                 "</span></a></td>\n", _("Month view")
424                                         );
425                                         break;
426                                 case VIEW_TASKS:
427                                         wprintf(
428                                                 "<td>"
429                                                 "<a href=\"readfwd\">"
430                                                 "<img align=\"middle\" src=\"static/taskmanag_24x.gif\" "
431                                                 "border=\"0\">"
432                                                 "<span class=\"navbar_link\">"
433                                                 "%s"
434                                                 "</span></a></td>\n", _("View tasks")
435                                         );
436                                         break;
437                                 case VIEW_NOTES:
438                                         wprintf(
439                                                 "<td>"
440                                                 "<a href=\"readfwd\">"
441                                                 "<img align=\"middle\" src=\"static/viewnotes_24x.gif\" "
442                                                 "border=\"0\">"
443                                                 "<span class=\"navbar_link\">"
444                                                 "%s"
445                                                 "</span></a></td>\n", _("View notes")
446                                         );
447                                         break;
448                                 case VIEW_MAILBOX:
449                                         wprintf(
450                                                 "<td>"
451                                                 "<a href=\"readfwd\">"
452                                                 "<img align=\"middle\" src=\"static/readallmess3_24x.gif\" "
453                                                 "border=\"0\">"
454                                                 "<span class=\"navbar_link\">"
455                                                 "%s"
456                                                 "</span></a></td>\n", _("View message list")
457                                         );
458                                         break;
459                                 default:
460                                         wprintf(
461                                                 "<td>"
462                                                 "<a href=\"readfwd\">"
463                                                 "<img align=\"middle\" src=\"static/readallmess3_24x.gif\" "
464                                                 "border=\"0\">"
465                                                 "<span class=\"navbar_link\">"
466                                                 "%s"
467                                                 "</span></a></td>\n", _("Read all messages")
468                                         );
469                                         break;
470                         }
471                 }
472
473                 if (navbar_style == navbar_default) {
474                         switch(WC->wc_view) {
475                                 case VIEW_ADDRESSBOOK:
476                                         wprintf(
477                                                 "<td><a href=\"display_enter\">"
478                                                 "<img align=\"middle\" src=\"static/addnewcontact_24x.gif\" "
479                                                 "border=\"0\"><span class=\"navbar_link\">"
480                                                 "%s"
481                                                 "</span></a></td>\n", _("Add new contact")
482                                         );
483                                         break;
484                                 case VIEW_CALENDAR:
485                                         wprintf(
486                                                 "<td><a href=\"display_enter\">"
487                                                 "<img align=\"middle\" src=\"static/addevent_24x.gif\" "
488                                                 "border=\"0\"><span class=\"navbar_link\">"
489                                                 "%s"
490                                                 "</span></a></td>\n", _("Add new event")
491                                         );
492                                         break;
493                                 case VIEW_TASKS:
494                                         wprintf(
495                                                 "<td><a href=\"display_enter\">"
496                                                 "<img align=\"middle\" src=\"static/newmess3_24x.gif\" "
497                                                 "border=\"0\"><span class=\"navbar_link\">"
498                                                 "%s"
499                                                 "</span></a></td>\n", _("Add new task")
500                                         );
501                                         break;
502                                 case VIEW_NOTES:
503                                         wprintf(
504                                                 "<td><a href=\"display_enter\">"
505                                                 "<img align=\"middle\" src=\"static/enternewnote_24x.gif\" "
506                                                 "border=\"0\"><span class=\"navbar_link\">"
507                                                 "%s"
508                                                 "</span></a></td>\n", _("Add new note")
509                                         );
510                                         break;
511                                 default:
512                                         wprintf(
513                                                 "<td><a href=\"display_enter\">"
514                                                 "<img align=\"middle\" src=\"static/newmess3_24x.gif\" "
515                                                 "border=\"0\"><span class=\"navbar_link\">"
516                                                 "%s"
517                                                 "</span></a></td>\n", _("Enter a message")
518                                         );
519                                         break;
520                         }
521                 }
522
523                 if (navbar_style == navbar_default) wprintf(
524                         "<td>"
525                         "<a href=\"skip\" "
526                         "TITLE=\"%s\">"
527                         "<img align=\"middle\" src=\"static/skipthisroom_24x.gif\" border=\"0\">"
528                         "<span class=\"navbar_link\">%s</span></a>"
529                         "</td>\n",
530                         _("Leave all messages marked as unread, go to next room with unread messages"),
531                         _("Skip this room")
532                 );
533
534                 if (navbar_style == navbar_default) wprintf(
535                         "<td>"
536                         "<a href=\"gotonext\" "
537                         "TITLE=\"%s\">"
538                         "<img align=\"middle\" src=\"static/markngo_24x.gif\" border=\"0\">"
539                         "<span class=\"navbar_link\">%s</span></a>"
540                         "</td>\n",
541                         _("Mark all messages as read, go to next room with unread messages"),
542                         _("Goto next room")
543                 );
544
545                 wprintf("</tr></table></div>\n");
546         }
547
548 }
549
550
551
552
553
554 /*
555  * back end routine to take the session to a new room
556  *
557  */
558 int gotoroom(char *gname)
559 {
560         char buf[SIZ];
561         static long ls = (-1L);
562         int err = 0;
563
564         /* store ungoto information */
565         strcpy(WC->ugname, WC->wc_roomname);
566         WC->uglsn = ls;
567
568         /* move to the new room */
569         serv_printf("GOTO %s", gname);
570         serv_getln(buf, sizeof buf);
571         if (buf[0] != '2') {
572                 buf[3] = 0;
573                 err = atoi(buf);
574                 serv_puts("GOTO _BASEROOM_");
575                 serv_getln(buf, sizeof buf);
576         }
577         if (buf[0] != '2') {
578                 buf[3] = 0;
579                 err = atoi(buf);
580                 return err;
581         }
582         extract_token(WC->wc_roomname, &buf[4], 0, '|', sizeof WC->wc_roomname);
583         WC->room_flags = extract_int(&buf[4], 4);
584         /* highest_msg_read = extract_int(&buf[4],6);
585            maxmsgnum = extract_int(&buf[4],5);
586          */
587         WC->is_mailbox = extract_int(&buf[4],7);
588         ls = extract_long(&buf[4], 6);
589         WC->wc_floor = extract_int(&buf[4], 10);
590         WC->wc_view = extract_int(&buf[4], 11);
591         WC->wc_default_view = extract_int(&buf[4], 12);
592
593         if (WC->is_aide)
594                 WC->is_room_aide = WC->is_aide;
595         else
596                 WC->is_room_aide = (char) extract_int(&buf[4], 8);
597
598         remove_march(WC->wc_roomname);
599         if (!strcasecmp(gname, "_BASEROOM_"))
600                 remove_march(gname);
601
602         return err;
603 }
604
605
606 /*
607  * Locate the room on the march list which we most want to go to.  Each room
608  * is measured given a "weight" of preference based on various factors.
609  */
610 char *pop_march(int desired_floor)
611 {
612         static char TheRoom[128];
613         int TheFloor = 0;
614         int TheOrder = 32767;
615         int TheWeight = 0;
616         int weight;
617         struct march *mptr = NULL;
618
619         strcpy(TheRoom, "_BASEROOM_");
620         if (WC->march == NULL)
621                 return (TheRoom);
622
623         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
624                 weight = 0;
625                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
626                         weight = weight + 10000;
627                 if (mptr->march_floor == desired_floor)
628                         weight = weight + 5000;
629
630                 weight = weight + ((128 - (mptr->march_floor)) * 128);
631                 weight = weight + (128 - (mptr->march_order));
632
633                 if (weight > TheWeight) {
634                         TheWeight = weight;
635                         strcpy(TheRoom, mptr->march_name);
636                         TheFloor = mptr->march_floor;
637                         TheOrder = mptr->march_order;
638                 }
639         }
640         return (TheRoom);
641 }
642
643
644
645 /* Goto next room having unread messages.
646  * We want to skip over rooms that the user has already been to, and take the
647  * user back to the lobby when done.  The room we end up in is placed in
648  * newroom - which is set to 0 (the lobby) initially.
649  * We start the search in the current room rather than the beginning to prevent
650  * two or more concurrent users from dragging each other back to the same room.
651  */
652 void gotonext(void)
653 {
654         char buf[SIZ];
655         struct march *mptr, *mptr2;
656         char next_room[128];
657
658         /* First check to see if the march-mode list is already allocated.
659          * If it is, pop the first room off the list and go there.
660          */
661
662         if (WC->march == NULL) {
663                 serv_puts("LKRN");
664                 serv_getln(buf, sizeof buf);
665                 if (buf[0] == '1')
666                         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
667                                 mptr = (struct march *) malloc(sizeof(struct march));
668                                 mptr->next = NULL;
669                                 extract_token(mptr->march_name, buf, 0, '|', sizeof mptr->march_name);
670                                 mptr->march_floor = extract_int(buf, 2);
671                                 mptr->march_order = extract_int(buf, 3);
672                                 if (WC->march == NULL) {
673                                         WC->march = mptr;
674                                 } else {
675                                         mptr2 = WC->march;
676                                         while (mptr2->next != NULL)
677                                                 mptr2 = mptr2->next;
678                                         mptr2->next = mptr;
679                                 }
680                         }
681 /* add _BASEROOM_ to the end of the march list, so the user will end up
682  * in the system base room (usually the Lobby>) at the end of the loop
683  */
684                 mptr = (struct march *) malloc(sizeof(struct march));
685                 mptr->next = NULL;
686                 strcpy(mptr->march_name, "_BASEROOM_");
687                 if (WC->march == NULL) {
688                         WC->march = mptr;
689                 } else {
690                         mptr2 = WC->march;
691                         while (mptr2->next != NULL)
692                                 mptr2 = mptr2->next;
693                         mptr2->next = mptr;
694                 }
695 /*
696  * ...and remove the room we're currently in, so a <G>oto doesn't make us
697  * walk around in circles
698  */
699                 remove_march(WC->wc_roomname);
700         }
701         if (WC->march != NULL) {
702                 strcpy(next_room, pop_march(-1));
703         } else {
704                 strcpy(next_room, "_BASEROOM_");
705         }
706
707
708         smart_goto(next_room);
709 }
710
711
712 void smart_goto(char *next_room) {
713         gotoroom(next_room);
714         readloop("readnew");
715 }
716
717
718
719 /*
720  * mark all messages in current room as having been read
721  */
722 void slrp_highest(void)
723 {
724         char buf[SIZ];
725
726         /* set pointer */
727         serv_puts("SLRP HIGHEST");
728         serv_getln(buf, sizeof buf);
729         if (buf[0] != '2') {
730                 wprintf("<EM>%s</EM><br />\n", &buf[4]);
731                 return;
732         }
733 }
734
735
736 /*
737  * un-goto the previous room
738  */
739 void ungoto(void)
740 {
741         char buf[SIZ];
742
743         if (!strcmp(WC->ugname, "")) {
744                 smart_goto(WC->wc_roomname);
745                 return;
746         }
747         serv_printf("GOTO %s", WC->ugname);
748         serv_getln(buf, sizeof buf);
749         if (buf[0] != '2') {
750                 smart_goto(WC->wc_roomname);
751                 return;
752         }
753         if (WC->uglsn >= 0L) {
754                 serv_printf("SLRP %ld", WC->uglsn);
755                 serv_getln(buf, sizeof buf);
756         }
757         strcpy(buf, WC->ugname);
758         strcpy(WC->ugname, "");
759         smart_goto(buf);
760 }
761
762
763
764
765
766 /*
767  * Set/clear/read the "self-service list subscribe" flag for a room
768  * 
769  * Set 'newval' to 0 to clear, 1 to set, any other value to leave unchanged.
770  * Always returns the new value.
771  */
772
773 int self_service(int newval) {
774         int current_value = 0;
775         char buf[SIZ];
776         
777         char name[SIZ];
778         char password[SIZ];
779         char dirname[SIZ];
780         int flags, floor, order, view, flags2;
781
782         serv_puts("GETR");
783         serv_getln(buf, sizeof buf);
784         if (buf[0] != '2') return(0);
785
786         extract_token(name, &buf[4], 0, '|', sizeof name);
787         extract_token(password, &buf[4], 1, '|', sizeof password);
788         extract_token(dirname, &buf[4], 2, '|', sizeof dirname);
789         flags = extract_int(&buf[4], 3);
790         floor = extract_int(&buf[4], 4);
791         order = extract_int(&buf[4], 5);
792         view = extract_int(&buf[4], 6);
793         flags2 = extract_int(&buf[4], 7);
794
795         if (flags2 & QR2_SELFLIST) {
796                 current_value = 1;
797         }
798         else {
799                 current_value = 0;
800         }
801
802         if (newval == 1) {
803                 flags2 = flags2 | QR2_SELFLIST;
804         }
805         else if (newval == 0) {
806                 flags2 = flags2 & ~QR2_SELFLIST;
807         }
808         else {
809                 return(current_value);
810         }
811
812         if (newval != current_value) {
813                 serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
814                         name, password, dirname, flags,
815                         floor, order, view, flags2);
816                 serv_getln(buf, sizeof buf);
817         }
818
819         return(newval);
820
821 }
822
823
824
825
826
827
828 /*
829  * display the form for editing a room
830  */
831 void display_editroom(void)
832 {
833         char buf[SIZ];
834         char cmd[SIZ];
835         char node[SIZ];
836         char remote_room[SIZ];
837         char recp[SIZ];
838         char er_name[128];
839         char er_password[10];
840         char er_dirname[15];
841         char er_roomaide[26];
842         unsigned er_flags;
843         int er_floor;
844         int i, j;
845         char *tab;
846         char *shared_with;
847         char *not_shared_with;
848         int roompolicy = 0;
849         int roomvalue = 0;
850         int floorpolicy = 0;
851         int floorvalue = 0;
852
853         tab = bstr("tab");
854         if (strlen(tab) == 0) tab = "admin";
855
856         load_floorlist();
857         serv_puts("GETR");
858         serv_getln(buf, sizeof buf);
859
860         if (buf[0] != '2') {
861                 strcpy(WC->ImportantMessage, &buf[4]);
862                 display_main_menu();
863                 return;
864         }
865         extract_token(er_name, &buf[4], 0, '|', sizeof er_name);
866         extract_token(er_password, &buf[4], 1, '|', sizeof er_password);
867         extract_token(er_dirname, &buf[4], 2, '|', sizeof er_dirname);
868         er_flags = extract_int(&buf[4], 3);
869         er_floor = extract_int(&buf[4], 4);
870
871         output_headers(1, 1, 1, 0, 0, 0);
872
873         /* print the tabbed dialog */
874         wprintf("<br />"
875                 "<div id=\"fix_scrollbar_bug\">"
876                 "<TABLE border=0 cellspacing=0 cellpadding=0 width=100%%>"
877                 "<TR ALIGN=CENTER>"
878                 "<TD>&nbsp;</TD>\n");
879
880         if (!strcmp(tab, "admin")) {
881                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
882         }
883         else {
884                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=admin\">");
885         }
886         wprintf(_("Administration"));
887         if (!strcmp(tab, "admin")) {
888                 wprintf("</SPAN></TD>\n");
889         }
890         else {
891                 wprintf("</A></TD>\n");
892         }
893
894         wprintf("<TD>&nbsp;</TD>\n");
895
896         if (!strcmp(tab, "config")) {
897                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
898         }
899         else {
900                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=config\">");
901         }
902         wprintf(_("Configuration"));
903         if (!strcmp(tab, "config")) {
904                 wprintf("</SPAN></TD>\n");
905         }
906         else {
907                 wprintf("</A></TD>\n");
908         }
909
910         wprintf("<TD>&nbsp;</TD>\n");
911
912         if (!strcmp(tab, "expire")) {
913                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
914         }
915         else {
916                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=expire\">");
917         }
918         wprintf(_("Message expire policy"));
919         if (!strcmp(tab, "expire")) {
920                 wprintf("</SPAN></TD>\n");
921         }
922         else {
923                 wprintf("</A></TD>\n");
924         }
925
926         wprintf("<TD>&nbsp;</TD>\n");
927
928         if (!strcmp(tab, "access")) {
929                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
930         }
931         else {
932                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=access\">");
933         }
934         wprintf(_("Access controls"));
935         if (!strcmp(tab, "access")) {
936                 wprintf("</SPAN></TD>\n");
937         }
938         else {
939                 wprintf("</A></TD>\n");
940         }
941
942         wprintf("<TD>&nbsp;</TD>\n");
943
944         if (!strcmp(tab, "sharing")) {
945                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
946         }
947         else {
948                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=sharing\">");
949         }
950         wprintf(_("Sharing"));
951         if (!strcmp(tab, "sharing")) {
952                 wprintf("</SPAN></TD>\n");
953         }
954         else {
955                 wprintf("</A></TD>\n");
956         }
957
958         wprintf("<TD>&nbsp;</TD>\n");
959
960         if (!strcmp(tab, "listserv")) {
961                 wprintf("<TD BGCOLOR=\"#FFFFFF\"><SPAN CLASS=\"tablabel\">");
962         }
963         else {
964                 wprintf("<TD BGCOLOR=\"#CCCCCC\"><a href=\"display_editroom&tab=listserv\">");
965         }
966         wprintf(_("Mailing list service"));
967         if (!strcmp(tab, "listserv")) {
968                 wprintf("</SPAN></TD>\n");
969         }
970         else {
971                 wprintf("</A></TD>\n");
972         }
973
974         wprintf("<TD>&nbsp;</TD>\n");
975
976         wprintf("</TR></TABLE></div>\n");
977         /* end tabbed dialog */ 
978
979         /* begin content of whatever tab is open now */
980         wprintf("<div id=\"fix_scrollbar_bug\">"
981                 "<TABLE border=0 width=100%% bgcolor=\"#FFFFFF\">\n"
982                 "<TR><TD>\n");
983
984         if (!strcmp(tab, "admin")) {
985                 wprintf("<UL>"
986                         "<LI><a href=\"delete_room\" "
987                         "onClick=\"return confirm('");
988                 wprintf(_("Are you sure you want to delete this room?"));
989                 wprintf("');\">\n");
990                 wprintf(_("Delete this room"));
991                 wprintf("</A>\n"
992                         "<LI><a href=\"display_editroompic\">\n");
993                 wprintf(_("Set or change the icon for this room's banner"));
994                 wprintf("</A>\n"
995                         "<LI><a href=\"display_editinfo\">\n");
996                 wprintf(_("Edit this room's Info file"));
997                 wprintf("</A>\n"
998                         "</UL>");
999         }
1000
1001         if (!strcmp(tab, "config")) {
1002                 wprintf("<FORM METHOD=\"POST\" action=\"editroom\">\n");
1003         
1004                 wprintf("<UL><LI>");
1005                 wprintf(_("Name of room: "));
1006                 wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\"%d\">\n",
1007                         er_name,
1008                         (sizeof(er_name)-1)
1009                 );
1010         
1011                 wprintf("<LI>");
1012                 wprintf(_("Resides on floor: "));
1013                 wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
1014                 for (i = 0; i < 128; ++i)
1015                         if (strlen(floorlist[i]) > 0) {
1016                                 wprintf("<OPTION ");
1017                                 if (i == er_floor)
1018                                         wprintf("SELECTED ");
1019                                 wprintf("VALUE=\"%d\">", i);
1020                                 escputs(floorlist[i]);
1021                                 wprintf("</OPTION>\n");
1022                         }
1023                 wprintf("</SELECT>\n");
1024         
1025                 wprintf("<LI>");
1026                 wprintf(_("Type of room:"));
1027                 wprintf("<UL>\n");
1028
1029                 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
1030                 if ((er_flags & QR_PRIVATE) == 0)
1031                 wprintf("CHECKED ");
1032                 wprintf("> ");
1033                 wprintf(_("Public room"));
1034                 wprintf("\n");
1035
1036                 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"hidden\" ");
1037                 if ((er_flags & QR_PRIVATE) &&
1038                     (er_flags & QR_GUESSNAME))
1039                         wprintf("CHECKED ");
1040                 wprintf("> ");
1041                 wprintf(_("Private - guess name"));
1042         
1043                 wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
1044                 if ((er_flags & QR_PRIVATE) &&
1045                     (er_flags & QR_PASSWORDED))
1046                         wprintf("CHECKED ");
1047                 wprintf("> ");
1048                 wprintf(_("Private - require password:"));
1049                 wprintf("\n<INPUT TYPE=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n",
1050                         er_password);
1051         
1052                 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
1053                 if ((er_flags & QR_PRIVATE)
1054                     && ((er_flags & QR_GUESSNAME) == 0)
1055                     && ((er_flags & QR_PASSWORDED) == 0))
1056                         wprintf("CHECKED ");
1057                 wprintf("> ");
1058                 wprintf(_("Private - invitation only"));
1059         
1060                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
1061                 wprintf("> ");
1062                 wprintf(_("If private, cause current users to forget room"));
1063         
1064                 wprintf("\n</UL>\n");
1065         
1066                 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
1067                 if (er_flags & QR_PREFONLY)
1068                         wprintf("CHECKED ");
1069                 wprintf("> ");
1070                 wprintf(_("Preferred users only"));
1071         
1072                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
1073                 if (er_flags & QR_READONLY)
1074                         wprintf("CHECKED ");
1075                 wprintf("> ");
1076                 wprintf(_("Read-only room"));
1077         
1078         /* directory stuff */
1079                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
1080                 if (er_flags & QR_DIRECTORY)
1081                         wprintf("CHECKED ");
1082                 wprintf("> ");
1083                 wprintf(_("File directory room"));
1084
1085                 wprintf("\n<UL><LI>");
1086                 wprintf(_("Directory name: "));
1087                 wprintf("<INPUT TYPE=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n",
1088                         er_dirname);
1089
1090                 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
1091                 if (er_flags & QR_UPLOAD)
1092                         wprintf("CHECKED ");
1093                 wprintf("> ");
1094                 wprintf(_("Uploading allowed"));
1095         
1096                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
1097                 if (er_flags & QR_DOWNLOAD)
1098                         wprintf("CHECKED ");
1099                 wprintf("> ");
1100                 wprintf(_("Downloading allowed"));
1101         
1102                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
1103                 if (er_flags & QR_VISDIR)
1104                         wprintf("CHECKED ");
1105                 wprintf("> ");
1106                 wprintf(_("Visible directory"));
1107                 wprintf("</UL>\n");
1108         
1109         /* end of directory stuff */
1110         
1111                 wprintf("<LI><INPUT TYPE=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
1112                 if (er_flags & QR_NETWORK)
1113                         wprintf("CHECKED ");
1114                 wprintf("> ");
1115                 wprintf(_("Network shared room"));
1116
1117                 wprintf("\n<LI><INPUT TYPE=\"checkbox\" NAME=\"permanent\" VALUE=\"yes\" ");
1118                 if (er_flags & QR_PERMANENT)
1119                         wprintf("CHECKED ");
1120                 wprintf("> ");
1121                 wprintf(_("Permanent (does not auto-purge)"));
1122
1123         /* start of anon options */
1124         
1125                 wprintf("\n<LI>");
1126                 wprintf(_("Anonymous messages"));
1127                 wprintf("<UL>\n");
1128         
1129                 wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
1130                 if (((er_flags & QR_ANONONLY) == 0)
1131                     && ((er_flags & QR_ANONOPT) == 0))
1132                         wprintf("CHECKED ");
1133                 wprintf("> ");
1134                 wprintf(_("No anonymous messages"));
1135         
1136                 wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
1137                 if (er_flags & QR_ANONONLY)
1138                         wprintf("CHECKED ");
1139                 wprintf("> ");
1140                 wprintf(_("All messages are anonymous"));
1141         
1142                 wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
1143                 if (er_flags & QR_ANONOPT)
1144                         wprintf("CHECKED ");
1145                 wprintf("> ");
1146                 wprintf(_("Prompt user when entering messages"));
1147                 wprintf("</UL>\n");
1148         
1149         /* end of anon options */
1150         
1151                 wprintf("<LI>");
1152                 wprintf(_("Room aide: "));
1153                 serv_puts("GETA");
1154                 serv_getln(buf, sizeof buf);
1155                 if (buf[0] != '2') {
1156                         wprintf("<EM>%s</EM>\n", &buf[4]);
1157                 } else {
1158                         extract_token(er_roomaide, &buf[4], 0, '|', sizeof er_roomaide);
1159                         wprintf("<INPUT TYPE=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
1160                 }
1161         
1162                 wprintf("</UL><CENTER>\n");
1163                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"config\">\n"
1164                         "<INPUT TYPE=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">"
1165                         "&nbsp;"
1166                         "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">"
1167                         "</CENTER>\n",
1168                         _("Save changes"),
1169                         _("Cancel")
1170                 );
1171         }
1172
1173
1174         /* Sharing the room with other Citadel nodes... */
1175         if (!strcmp(tab, "sharing")) {
1176
1177                 shared_with = strdup("");
1178                 not_shared_with = strdup("");
1179
1180                 /* Learn the current configuration */
1181                 serv_puts("CONF getsys|application/x-citadel-ignet-config");
1182                 serv_getln(buf, sizeof buf);
1183                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1184                         extract_token(node, buf, 0, '|', sizeof node);
1185                         not_shared_with = realloc(not_shared_with,
1186                                         strlen(not_shared_with) + 32);
1187                         strcat(not_shared_with, node);
1188                         strcat(not_shared_with, "\n");
1189                 }
1190
1191                 serv_puts("GNET");
1192                 serv_getln(buf, sizeof buf);
1193                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1194                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1195                         extract_token(node, buf, 1, '|', sizeof node);
1196                         extract_token(remote_room, buf, 2, '|', sizeof remote_room);
1197                         if (!strcasecmp(cmd, "ignet_push_share")) {
1198                                 shared_with = realloc(shared_with,
1199                                                 strlen(shared_with) + 32);
1200                                 strcat(shared_with, node);
1201                                 if (strlen(remote_room) > 0) {
1202                                         strcat(shared_with, "|");
1203                                         strcat(shared_with, remote_room);
1204                                 }
1205                                 strcat(shared_with, "\n");
1206                         }
1207                 }
1208
1209                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1210                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1211                         extract_token(node, buf, 0, '|', sizeof node);
1212                         for (j=0; j<num_tokens(not_shared_with, '\n'); ++j) {
1213                                 extract_token(cmd, not_shared_with, j, '\n', sizeof cmd);
1214                                 if (!strcasecmp(node, cmd)) {
1215                                         remove_token(not_shared_with, j, '\n');
1216                                 }
1217                         }
1218                 }
1219
1220                 /* Display the stuff */
1221                 wprintf("<CENTER><br />"
1222                         "<TABLE border=1 cellpadding=5><TR>"
1223                         "<TD><B><I>");
1224                 wprintf(_("Shared with"));
1225                 wprintf("</I></B></TD>"
1226                         "<TD><B><I>");
1227                 wprintf(_("Not shared with"));
1228                 wprintf("</I></B></TD></TR>\n"
1229                         "<TR><TD VALIGN=TOP>\n");
1230
1231                 wprintf("<TABLE border=0 cellpadding=5><TR BGCOLOR=\"#CCCCCC\"><TD>");
1232                 wprintf(_("Remote node name"));
1233                 wprintf("</TD><TD>");
1234                 wprintf(_("Remote room name"));
1235                 wprintf("</TD><TD>");
1236                 wprintf(_("Actions"));
1237                 wprintf("</TD></TR>\n");
1238
1239                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1240                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1241                         extract_token(node, buf, 0, '|', sizeof node);
1242                         extract_token(remote_room, buf, 1, '|', sizeof remote_room);
1243                         if (strlen(node) > 0) {
1244                                 wprintf("<FORM METHOD=\"POST\" "
1245                                         "action=\"netedit\">"
1246                                         "<TR><TD>%s</TD>\n", node);
1247
1248                                 wprintf("<TD>");
1249                                 if (strlen(remote_room) > 0) {
1250                                         escputs(remote_room);
1251                                 }
1252                                 wprintf("</TD>");
1253
1254                                 wprintf("<TD>");
1255                 
1256                                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"line\" "
1257                                         "VALUE=\"ignet_push_share|");
1258                                 urlescputs(node);
1259                                 if (strlen(remote_room) > 0) {
1260                                         wprintf("|");
1261                                         urlescputs(remote_room);
1262                                 }
1263                                 wprintf("\">");
1264                                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" "
1265                                         "VALUE=\"sharing\">\n");
1266                                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"cmd\" "
1267                                         "VALUE=\"remove\">\n");
1268                                 wprintf("<INPUT TYPE=\"submit\" "
1269                                         "NAME=\"unshare_button\" VALUE=\"%s\">", _("Unshare"));
1270                                 wprintf("</TD></TR></FORM>\n");
1271                         }
1272                 }
1273
1274                 wprintf("</TABLE>\n");
1275                 wprintf("</TD><TD VALIGN=TOP>\n");
1276                 wprintf("<TABLE border=0 cellpadding=5><TR BGCOLOR=\"#CCCCCC\"><TD>");
1277                 wprintf(_("Remote node name"));
1278                 wprintf("</TD><TD>");
1279                 wprintf(_("Remote room name"));
1280                 wprintf("</TD><TD>");
1281                 wprintf(_("Actions"));
1282                 wprintf("</TD></TR>\n");
1283
1284                 for (i=0; i<num_tokens(not_shared_with, '\n'); ++i) {
1285                         extract_token(node, not_shared_with, i, '\n', sizeof node);
1286                         if (strlen(node) > 0) {
1287                                 wprintf("<FORM METHOD=\"POST\" "
1288                                         "action=\"netedit\">"
1289                                         "<TR><TD>");
1290                                 escputs(node);
1291                                 wprintf("</TD><TD>"
1292                                         "<INPUT TYPE=\"INPUT\" "
1293                                         "NAME=\"suffix\" "
1294                                         "MAXLENGTH=128>"
1295                                         "</TD><TD>");
1296                                 wprintf("<INPUT TYPE=\"hidden\" "
1297                                         "NAME=\"line\" "
1298                                         "VALUE=\"ignet_push_share|");
1299                                 urlescputs(node);
1300                                 wprintf("|\">");
1301                                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" "
1302                                         "VALUE=\"sharing\">\n");
1303                                 wprintf("<INPUT TYPE=\"hidden\" NAME=\"cmd\" "
1304                                         "VALUE=\"add\">\n");
1305                                 wprintf("<INPUT TYPE=\"submit\" "
1306                                         "NAME=\"add_button\" VALUE=\"%s\">", _("Share"));
1307                                 wprintf("</TD></TR></FORM>\n");
1308                         }
1309                 }
1310
1311                 wprintf("</TABLE>\n");
1312                 wprintf("</TD></TR>"
1313                         "</TABLE></CENTER><br />\n"
1314                         "<I><B>%s</B><UL><LI>", _("Notes:"));
1315                 wprintf(_("When sharing a room, "
1316                         "it must be shared from both ends.  Adding a node to "
1317                         "the 'shared' list sends messages out, but in order to"
1318                         " receive messages, the other nodes must be configured"
1319                         " to send messages out to your system as well. "
1320                         "<LI>If the remote room name is blank, it is assumed "
1321                         "that the room name is identical on the remote node."
1322                         "<LI>If the remote room name is different, the remote "
1323                         "node must also configure the name of the room here."
1324                         "</UL></I><br />\n"
1325                 ));
1326
1327         }
1328
1329         /* Mailing list management */
1330         if (!strcmp(tab, "listserv")) {
1331
1332                 wprintf("<br /><center>"
1333                         "<TABLE BORDER=0 WIDTH=100%% CELLPADDING=5>"
1334                         "<TR><TD VALIGN=TOP>");
1335
1336                 wprintf(_("<i>The contents of this room are being "
1337                         "mailed <b>as individual messages</b> "
1338                         "to the following list recipients:"
1339                         "</i><br /><br />\n"));
1340
1341                 serv_puts("GNET");
1342                 serv_getln(buf, sizeof buf);
1343                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1344                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1345                         if (!strcasecmp(cmd, "listrecp")) {
1346                                 extract_token(recp, buf, 1, '|', sizeof recp);
1347                         
1348                                 escputs(recp);
1349                                 wprintf(" <a href=\"netedit&cmd=remove&line="
1350                                         "listrecp|");
1351                                 urlescputs(recp);
1352                                 wprintf("&tab=listserv\">");
1353                                 wprintf(_("(remove)"));
1354                                 wprintf("</A><br />");
1355                         }
1356                 }
1357                 wprintf("<br /><FORM METHOD=\"POST\" action=\"netedit\">\n"
1358                         "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1359                         "<INPUT TYPE=\"hidden\" NAME=\"prefix\" VALUE=\"listrecp|\">\n");
1360                 wprintf("<INPUT TYPE=\"text\" NAME=\"line\">\n");
1361                 wprintf("<INPUT TYPE=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1362                 wprintf("</FORM>\n");
1363
1364                 wprintf("</TD><TD VALIGN=TOP>\n");
1365                 
1366                 wprintf(_("<i>The contents of this room are being "
1367                         "mailed <b>in digest form</b> "
1368                         "to the following list recipients:"
1369                         "</i><br /><br />\n"));
1370
1371                 serv_puts("GNET");
1372                 serv_getln(buf, sizeof buf);
1373                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1374                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1375                         if (!strcasecmp(cmd, "digestrecp")) {
1376                                 extract_token(recp, buf, 1, '|', sizeof recp);
1377                         
1378                                 escputs(recp);
1379                                 wprintf(" <a href=\"netedit&cmd=remove&line="
1380                                         "digestrecp|");
1381                                 urlescputs(recp);
1382                                 wprintf("&tab=listserv\">");
1383                                 wprintf(_("(remove)"));
1384                                 wprintf("</A><br />");
1385                         }
1386                 }
1387                 wprintf("<br /><FORM METHOD=\"POST\" action=\"netedit\">\n"
1388                         "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1389                         "<INPUT TYPE=\"hidden\" NAME=\"prefix\" VALUE=\"digestrecp|\">\n");
1390                 wprintf("<INPUT TYPE=\"text\" NAME=\"line\">\n");
1391                 wprintf("<INPUT TYPE=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1392                 wprintf("</FORM>\n");
1393                 
1394                 wprintf("</TD></TR></TABLE><hr />\n");
1395
1396                 if (self_service(999) == 1) {
1397                         wprintf(_("This room is configured to allow "
1398                                 "self-service subscribe/unsubscribe requests."));
1399                         wprintf("<a href=\"toggle_self_service?newval=0&tab=listserv\">");
1400                         wprintf(_("Click to disable."));
1401                         wprintf("</A><br />\n");
1402                         wprintf(_("The URL for subscribe/unsubscribe is: "));
1403                         wprintf("<TT>%s://%s/listsub</TT><br />\n",
1404                                 (is_https ? "https" : "http"),
1405                                 WC->http_host);
1406                 }
1407                 else {
1408                         wprintf(_("This room is <i>not</i> configured to allow "
1409                                 "self-service subscribe/unsubscribe requests."));
1410                         wprintf(" <a href=\"toggle_self_service?newval=1&"
1411                                 "tab=listserv\">");
1412                         wprintf(_("Click to enable."));
1413                         wprintf("</A><br />\n");
1414                 }
1415
1416
1417                 wprintf("</CENTER>\n");
1418         }
1419
1420
1421         /* Mailing list management */
1422         if (!strcmp(tab, "expire")) {
1423
1424                 serv_puts("GPEX room");
1425                 serv_getln(buf, sizeof buf);
1426                 if (buf[0] == '2') {
1427                         roompolicy = extract_int(&buf[4], 0);
1428                         roomvalue = extract_int(&buf[4], 1);
1429                 }
1430                 
1431                 serv_puts("GPEX floor");
1432                 serv_getln(buf, sizeof buf);
1433                 if (buf[0] == '2') {
1434                         floorpolicy = extract_int(&buf[4], 0);
1435                         floorvalue = extract_int(&buf[4], 1);
1436                 }
1437                 
1438                 wprintf("<br /><FORM METHOD=\"POST\" action=\"set_room_policy\">\n");
1439                 wprintf("<TABLE border=0 cellspacing=5>\n");
1440                 wprintf("<TR><TD>");
1441                 wprintf(_("Message expire policy for this room"));
1442                 wprintf("<br />(");
1443                 escputs(WC->wc_roomname);
1444                 wprintf(")</TD><TD>");
1445                 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"0\" %s>",
1446                         ((roompolicy == 0) ? "CHECKED" : "") );
1447                 wprintf(_("Use the default policy for this floor"));
1448                 wprintf("<br />\n");
1449                 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"1\" %s>",
1450                         ((roompolicy == 1) ? "CHECKED" : "") );
1451                 wprintf(_("Never automatically expire messages"));
1452                 wprintf("<br />\n");
1453                 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"2\" %s>",
1454                         ((roompolicy == 2) ? "CHECKED" : "") );
1455                 wprintf("Expire by message count<br />\n");
1456                 wprintf("<INPUT TYPE=\"radio\" NAME=\"roompolicy\" VALUE=\"3\" %s>",
1457                         ((roompolicy == 3) ? "CHECKED" : "") );
1458                 wprintf(_("Expire by message age"));
1459                 wprintf("<br />");
1460                 wprintf(_("Number of messages or days: "));
1461                 wprintf("<INPUT TYPE=\"text\" NAME=\"roomvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">", roomvalue);
1462                 wprintf("</TD></TR>\n");
1463
1464                 if (WC->axlevel >= 6) {
1465                         wprintf("<TR><TD COLSPAN=2><hr /></TD></TR>\n");
1466                         wprintf("<TR><TD>");
1467                         wprintf(_("Message expire policy for this floor"));
1468                         wprintf("<br />(");
1469                         escputs(floorlist[WC->wc_floor]);
1470                         wprintf(")</TD><TD>");
1471                         wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"0\" %s>",
1472                                 ((floorpolicy == 0) ? "CHECKED" : "") );
1473                         wprintf(_("Use the system default"));
1474                         wprintf("<br />\n");
1475                         wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"1\" %s>",
1476                                 ((floorpolicy == 1) ? "CHECKED" : "") );
1477                         wprintf(_("Never automatically expire messages"));
1478                         wprintf("<br />\n");
1479                         wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"2\" %s>",
1480                                 ((floorpolicy == 2) ? "CHECKED" : "") );
1481                         wprintf(_("Expire by message count"));
1482                         wprintf("<br />\n");
1483                         wprintf("<INPUT TYPE=\"radio\" NAME=\"floorpolicy\" VALUE=\"3\" %s>",
1484                                 ((floorpolicy == 3) ? "CHECKED" : "") );
1485                         wprintf(_("Expire by message age"));
1486                         wprintf("<br />");
1487                         wprintf(_("Number of messages or days: "));
1488                         wprintf("<INPUT TYPE=\"text\" NAME=\"floorvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">",
1489                                 floorvalue);
1490                 }
1491
1492                 wprintf("<CENTER>\n");
1493                 wprintf("<TR><TD COLSPAN=2><hr /><CENTER>\n");
1494                 wprintf("<INPUT TYPE=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Save changes"));
1495                 wprintf("&nbsp;");
1496                 wprintf("<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
1497                 wprintf("</CENTER></TD><TR>\n");
1498
1499                 wprintf("</TABLE>\n"
1500                         "<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"expire\">\n"
1501                         "</FORM>\n"
1502                 );
1503
1504         }
1505
1506         /* Mailing list management */
1507         if (!strcmp(tab, "access")) {
1508                 display_whok();
1509         }
1510
1511         /* end content of whatever tab is open now */
1512         wprintf("</TD></TR></TABLE></div>\n");
1513
1514         wDumpContent(1);
1515 }
1516
1517
1518 /* 
1519  * Toggle self-service list subscription
1520  */
1521 void toggle_self_service(void) {
1522         int newval = 0;
1523
1524         newval = atoi(bstr("newval"));
1525         self_service(newval);
1526         display_editroom();
1527 }
1528
1529
1530
1531 /*
1532  * save new parameters for a room
1533  */
1534 void editroom(void)
1535 {
1536         char buf[SIZ];
1537         char er_name[128];
1538         char er_password[10];
1539         char er_dirname[15];
1540         char er_roomaide[26];
1541         int er_floor;
1542         unsigned er_flags;
1543         int bump;
1544
1545
1546         if (strlen(bstr("ok_button")) == 0) {
1547                 strcpy(WC->ImportantMessage,
1548                         _("Cancelled.  Changes were not saved."));
1549                 display_editroom();
1550                 return;
1551         }
1552         serv_puts("GETR");
1553         serv_getln(buf, sizeof buf);
1554
1555         if (buf[0] != '2') {
1556                 strcpy(WC->ImportantMessage, &buf[4]);
1557                 display_editroom();
1558                 return;
1559         }
1560         extract_token(er_name, &buf[4], 0, '|', sizeof er_name);
1561         extract_token(er_password, &buf[4], 1, '|', sizeof er_password);
1562         extract_token(er_dirname, &buf[4], 2, '|', sizeof er_dirname);
1563         er_flags = extract_int(&buf[4], 3);
1564
1565         strcpy(er_roomaide, bstr("er_roomaide"));
1566         if (strlen(er_roomaide) == 0) {
1567                 serv_puts("GETA");
1568                 serv_getln(buf, sizeof buf);
1569                 if (buf[0] != '2') {
1570                         strcpy(er_roomaide, "");
1571                 } else {
1572                         extract_token(er_roomaide, &buf[4], 0, '|', sizeof er_roomaide);
1573                 }
1574         }
1575         strcpy(buf, bstr("er_name"));
1576         buf[128] = 0;
1577         if (strlen(buf) > 0) {
1578                 strcpy(er_name, buf);
1579         }
1580
1581         strcpy(buf, bstr("er_password"));
1582         buf[10] = 0;
1583         if (strlen(buf) > 0)
1584                 strcpy(er_password, buf);
1585
1586         strcpy(buf, bstr("er_dirname"));
1587         buf[15] = 0;
1588         if (strlen(buf) > 0)
1589                 strcpy(er_dirname, buf);
1590
1591         strcpy(buf, bstr("type"));
1592         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
1593
1594         if (!strcmp(buf, "invonly")) {
1595                 er_flags |= (QR_PRIVATE);
1596         }
1597         if (!strcmp(buf, "hidden")) {
1598                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
1599         }
1600         if (!strcmp(buf, "passworded")) {
1601                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
1602         }
1603         if (!strcmp(bstr("prefonly"), "yes")) {
1604                 er_flags |= QR_PREFONLY;
1605         } else {
1606                 er_flags &= ~QR_PREFONLY;
1607         }
1608
1609         if (!strcmp(bstr("readonly"), "yes")) {
1610                 er_flags |= QR_READONLY;
1611         } else {
1612                 er_flags &= ~QR_READONLY;
1613         }
1614
1615         if (!strcmp(bstr("permanent"), "yes")) {
1616                 er_flags |= QR_PERMANENT;
1617         } else {
1618                 er_flags &= ~QR_PERMANENT;
1619         }
1620
1621         if (!strcmp(bstr("network"), "yes")) {
1622                 er_flags |= QR_NETWORK;
1623         } else {
1624                 er_flags &= ~QR_NETWORK;
1625         }
1626
1627         if (!strcmp(bstr("directory"), "yes")) {
1628                 er_flags |= QR_DIRECTORY;
1629         } else {
1630                 er_flags &= ~QR_DIRECTORY;
1631         }
1632
1633         if (!strcmp(bstr("ulallowed"), "yes")) {
1634                 er_flags |= QR_UPLOAD;
1635         } else {
1636                 er_flags &= ~QR_UPLOAD;
1637         }
1638
1639         if (!strcmp(bstr("dlallowed"), "yes")) {
1640                 er_flags |= QR_DOWNLOAD;
1641         } else {
1642                 er_flags &= ~QR_DOWNLOAD;
1643         }
1644
1645         if (!strcmp(bstr("visdir"), "yes")) {
1646                 er_flags |= QR_VISDIR;
1647         } else {
1648                 er_flags &= ~QR_VISDIR;
1649         }
1650
1651         strcpy(buf, bstr("anon"));
1652
1653         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
1654         if (!strcmp(buf, "anononly"))
1655                 er_flags |= QR_ANONONLY;
1656         if (!strcmp(buf, "anon2"))
1657                 er_flags |= QR_ANONOPT;
1658
1659         bump = 0;
1660         if (!strcmp(bstr("bump"), "yes"))
1661                 bump = 1;
1662
1663         er_floor = atoi(bstr("er_floor"));
1664
1665         sprintf(buf, "SETR %s|%s|%s|%u|%d|%d",
1666              er_name, er_password, er_dirname, er_flags, bump, er_floor);
1667         serv_puts(buf);
1668         serv_getln(buf, sizeof buf);
1669         if (buf[0] != '2') {
1670                 strcpy(WC->ImportantMessage, &buf[4]);
1671                 display_editroom();
1672                 return;
1673         }
1674         gotoroom(er_name);
1675
1676         if (strlen(er_roomaide) > 0) {
1677                 sprintf(buf, "SETA %s", er_roomaide);
1678                 serv_puts(buf);
1679                 serv_getln(buf, sizeof buf);
1680                 if (buf[0] != '2') {
1681                         strcpy(WC->ImportantMessage, &buf[4]);
1682                         display_main_menu();
1683                         return;
1684                 }
1685         }
1686         gotoroom(er_name);
1687         strcpy(WC->ImportantMessage, _("Your changes have been saved."));
1688         display_editroom();
1689         return;
1690 }
1691
1692
1693 /*
1694  * Display form for Invite, Kick, and show Who Knows a room
1695  */
1696 void do_invt_kick(void) {
1697         char buf[SIZ], room[SIZ], username[SIZ];
1698
1699         serv_puts("GETR");
1700         serv_getln(buf, sizeof buf);
1701
1702         if (buf[0] != '2') {
1703                 escputs(&buf[4]);
1704                 return;
1705         }
1706         extract_token(room, &buf[4], 0, '|', sizeof room);
1707
1708         strcpy(username, bstr("username"));
1709
1710         if (strlen(bstr("kick_button")) > 0) {
1711                 sprintf(buf, "KICK %s", username);
1712                 serv_puts(buf);
1713                 serv_getln(buf, sizeof buf);
1714
1715                 if (buf[0] != '2') {
1716                         strcpy(WC->ImportantMessage, &buf[4]);
1717                 } else {
1718                         sprintf(WC->ImportantMessage,
1719                                 _("<B><I>User %s kicked out of room %s.</I></B>\n"), 
1720                                 username, room);
1721                 }
1722         }
1723
1724         if (strlen(bstr("invite_button")) > 0) {
1725                 sprintf(buf, "INVT %s", username);
1726                 serv_puts(buf);
1727                 serv_getln(buf, sizeof buf);
1728
1729                 if (buf[0] != '2') {
1730                         strcpy(WC->ImportantMessage, &buf[4]);
1731                 } else {
1732                         sprintf(WC->ImportantMessage,
1733                                 _("<B><I>User %s invited to room %s.</I></B>\n"), 
1734                                 username, room);
1735                 }
1736         }
1737
1738         display_editroom();
1739 }
1740
1741
1742
1743 /*
1744  * Display form for Invite, Kick, and show Who Knows a room
1745  */
1746 void display_whok(void)
1747 {
1748         char buf[SIZ], room[SIZ], username[SIZ];
1749
1750         serv_puts("GETR");
1751         serv_getln(buf, sizeof buf);
1752
1753         if (buf[0] != '2') {
1754                 escputs(&buf[4]);
1755                 return;
1756         }
1757         extract_token(room, &buf[4], 0, '|', sizeof room);
1758
1759         
1760         wprintf("<TABLE border=0 CELLSPACING=10><TR VALIGN=TOP><TD>");
1761         wprintf(_("The users listed below have access to this room.  "
1762                 "To remove a user from the access list, select the user "
1763                 "name from the list and click 'Kick'."));
1764         wprintf("<br /><br />");
1765         
1766         wprintf("<CENTER><FORM METHOD=\"POST\" action=\"do_invt_kick\">\n");
1767         wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
1768         wprintf("<SELECT NAME=\"username\" SIZE=\"10\" style=\"width:100%%\">\n");
1769         serv_puts("WHOK");
1770         serv_getln(buf, sizeof buf);
1771         if (buf[0] == '1') {
1772                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1773                         extract_token(username, buf, 0, '|', sizeof username);
1774                         wprintf("<OPTION>");
1775                         escputs(username);
1776                         wprintf("\n");
1777                 }
1778         }
1779         wprintf("</SELECT><br />\n");
1780
1781         wprintf("<input type=\"submit\" name=\"kick_button\" value=\"%s\">", _("Kick"));
1782         wprintf("</FORM></CENTER>\n");
1783
1784         wprintf("</TD><TD>");
1785         wprintf(_("To grant another user access to this room, enter the "
1786                 "user name in the box below and click 'Invite'."));
1787         wprintf("<br /><br />");
1788
1789         wprintf("<CENTER><FORM METHOD=\"POST\" action=\"do_invt_kick\">\n");
1790         wprintf("<INPUT TYPE=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
1791         wprintf("Invite: ");
1792         wprintf("<input type=\"text\" name=\"username\" style=\"width:100%%\"><br />\n"
1793                 "<input type=\"hidden\" name=\"invite_button\" value=\"Invite\">"
1794                 "<input type=\"submit\" value=\"%s\">"
1795                 "</FORM></CENTER>\n", _("Invite"));
1796
1797         wprintf("</TD></TR></TABLE>\n");
1798         wDumpContent(1);
1799 }
1800
1801
1802
1803 /*
1804  * display the form for entering a new room
1805  */
1806 void display_entroom(void)
1807 {
1808         int i;
1809         char buf[SIZ];
1810
1811         serv_puts("CRE8 0");
1812         serv_getln(buf, sizeof buf);
1813
1814         if (buf[0] != '2') {
1815                 strcpy(WC->ImportantMessage, &buf[4]);
1816                 display_main_menu();
1817                 return;
1818         }
1819
1820         output_headers(1, 1, 2, 0, 0, 0);
1821         wprintf("<div id=\"banner\">\n"
1822                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
1823                 "<SPAN CLASS=\"titlebar\">");
1824         wprintf(_("Create a new room"));
1825         wprintf("</SPAN>"
1826                 "</TD></TR></TABLE>\n"
1827                 "</div>\n<div id=\"content\">\n"
1828         );
1829
1830         wprintf("<div id=\"fix_scrollbar_bug\">"
1831                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
1832
1833         wprintf("<form name=\"create_room_form\" method=\"POST\" action=\"entroom\">\n");
1834
1835         wprintf("<UL><LI>");
1836         wprintf(_("Name of room: "));
1837         wprintf("<INPUT TYPE=\"text\" NAME=\"er_name\" MAXLENGTH=\"127\">\n");
1838
1839         wprintf("<LI>");
1840         wprintf(_("Resides on floor: "));
1841         load_floorlist(); 
1842         wprintf("<SELECT NAME=\"er_floor\" SIZE=\"1\">\n");
1843         for (i = 0; i < 128; ++i)
1844                 if (strlen(floorlist[i]) > 0) {
1845                         wprintf("<OPTION ");
1846                         wprintf("VALUE=\"%d\">", i);
1847                         escputs(floorlist[i]);
1848                         wprintf("</OPTION>\n");
1849                 }
1850         wprintf("</SELECT>\n");
1851
1852         /* Our clever little snippet of JavaScript automatically selects
1853          * a public room if the view is set to Bulletin Board, and it
1854          * selects a mailbox room otherwise.  The user can override this,
1855          * of course.
1856          */
1857         wprintf("<LI>");
1858         wprintf(_("Default view for room: "));
1859         wprintf("<SELECT NAME=\"er_view\" SIZE=\"1\" OnChange=\""
1860                 "       if (this.form.er_view.value == 0) {     "       
1861                 "               this.form.type[0].checked=true;         "
1862                 "               this.form.er_floor.disabled = false;    "
1863                 "       }                                               "
1864                 "       else {                                          "
1865                 "               this.form.type[4].checked=true;         "
1866                 "               this.form.er_floor.disabled = true;     "
1867                 "       }                                               "
1868                 "\">\n");
1869         for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
1870                 wprintf("<OPTION %s VALUE=\"%d\">",
1871                         ((i == 0) ? "SELECTED" : ""), i );
1872                 escputs(viewdefs[i]);
1873                 wprintf("</OPTION>\n");
1874         }
1875         wprintf("</SELECT>\n");
1876
1877         wprintf("<LI>");
1878         wprintf(_("Type of room:"));
1879         wprintf("<UL>\n");
1880
1881         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"public\" ");
1882         wprintf("CHECKED OnChange=\""
1883                 "       if (this.form.type[0].checked == true) {        "
1884                 "               this.form.er_floor.disabled = false;    "
1885                 "       }                                               "
1886                 "\"> ");
1887         wprintf(_("Public (automatically appears to everyone)"));
1888
1889         wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"hidden\" OnChange=\""
1890                 "       if (this.form.type[1].checked == true) {        "
1891                 "               this.form.er_floor.disabled = false;    "
1892                 "       }                                               "
1893                 "\"> ");
1894         wprintf(_("Private - hidden (accessible to anyone who knows its name)"));
1895
1896         wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"passworded\" OnChange=\""
1897                 "       if (this.form.type[2].checked == true) {        "
1898                 "               this.form.er_floor.disabled = false;    "
1899                 "       }                                               "
1900                 "\"> ");
1901         wprintf(_("Private - require password: "));
1902         wprintf("<INPUT TYPE=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
1903
1904         wprintf("<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"invonly\" OnChange=\""
1905                 "       if (this.form.type[3].checked == true) {        "
1906                 "               this.form.er_floor.disabled = false;    "
1907                 "       }                                               "
1908                 "\"> ");
1909         wprintf(_("Private - invitation only"));
1910
1911         wprintf("\n<LI><INPUT TYPE=\"radio\" NAME=\"type\" VALUE=\"personal\" "
1912                 "OnChange=\""
1913                 "       if (this.form.type[4].checked == true) {        "
1914                 "               this.form.er_floor.disabled = true;     "
1915                 "       }                                               "
1916                 "\"> ");
1917         wprintf(_("Personal (mailbox for you only)"));
1918
1919         wprintf("\n</UL>\n");
1920
1921         wprintf("<CENTER>\n");
1922         wprintf("<INPUT TYPE=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Create new room"));
1923         wprintf("&nbsp;");
1924         wprintf("<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
1925         wprintf("</CENTER>\n");
1926         wprintf("</FORM>\n<hr />");
1927         serv_printf("MESG roomaccess");
1928         serv_getln(buf, sizeof buf);
1929         if (buf[0] == '1') {
1930                 fmout("CENTER");
1931         }
1932         wprintf("</td></tr></table></div>\n");
1933         wDumpContent(1);
1934 }
1935
1936
1937
1938
1939 /*
1940  * support function for entroom() -- sets the default view 
1941  */
1942 void er_set_default_view(int newview) {
1943
1944         char buf[SIZ];
1945
1946         char rm_name[SIZ];
1947         char rm_pass[SIZ];
1948         char rm_dir[SIZ];
1949         int rm_bits1;
1950         int rm_floor;
1951         int rm_listorder;
1952         int rm_bits2;
1953
1954         serv_puts("GETR");
1955         serv_getln(buf, sizeof buf);
1956         if (buf[0] != '2') return;
1957
1958         extract_token(rm_name, &buf[4], 0, '|', sizeof rm_name);
1959         extract_token(rm_pass, &buf[4], 1, '|', sizeof rm_pass);
1960         extract_token(rm_dir, &buf[4], 2, '|', sizeof rm_dir);
1961         rm_bits1 = extract_int(&buf[4], 3);
1962         rm_floor = extract_int(&buf[4], 4);
1963         rm_listorder = extract_int(&buf[4], 5);
1964         rm_bits2 = extract_int(&buf[4], 7);
1965
1966         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1967                 rm_name, rm_pass, rm_dir, rm_bits1, rm_floor,
1968                 rm_listorder, newview, rm_bits2
1969         );
1970         serv_getln(buf, sizeof buf);
1971 }
1972
1973
1974
1975 /*
1976  * enter a new room
1977  */
1978 void entroom(void)
1979 {
1980         char buf[SIZ];
1981         char er_name[SIZ];
1982         char er_type[SIZ];
1983         char er_password[SIZ];
1984         int er_floor;
1985         int er_num_type;
1986         int er_view;
1987
1988         if (strlen(bstr("ok_button")) == 0) {
1989                 strcpy(WC->ImportantMessage,
1990                         _("Cancelled.  No new room was created."));
1991                 display_main_menu();
1992                 return;
1993         }
1994         strcpy(er_name, bstr("er_name"));
1995         strcpy(er_type, bstr("type"));
1996         strcpy(er_password, bstr("er_password"));
1997         er_floor = atoi(bstr("er_floor"));
1998         er_view = atoi(bstr("er_view"));
1999
2000         er_num_type = 0;
2001         if (!strcmp(er_type, "hidden"))
2002                 er_num_type = 1;
2003         if (!strcmp(er_type, "passworded"))
2004                 er_num_type = 2;
2005         if (!strcmp(er_type, "invonly"))
2006                 er_num_type = 3;
2007         if (!strcmp(er_type, "personal"))
2008                 er_num_type = 4;
2009
2010         sprintf(buf, "CRE8 1|%s|%d|%s|%d|%d|%d", 
2011                 er_name, er_num_type, er_password, er_floor, 0, er_view);
2012         serv_puts(buf);
2013         serv_getln(buf, sizeof buf);
2014         if (buf[0] != '2') {
2015                 strcpy(WC->ImportantMessage, &buf[4]);
2016                 display_main_menu();
2017                 return;
2018         }
2019         gotoroom(er_name);
2020         do_change_view(er_view);                /* Now go there */
2021 }
2022
2023
2024 /*
2025  * display the screen to enter a private room
2026  */
2027 void display_private(char *rname, int req_pass)
2028 {
2029         output_headers(1, 1, 2, 0, 0, 0);
2030         wprintf("<div id=\"banner\">\n"
2031                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
2032                 "<SPAN CLASS=\"titlebar\">");
2033         wprintf(_("Go to a hidden room"));
2034         wprintf("</SPAN>"
2035                 "</TD></TR></TABLE>\n"
2036                 "</div>\n<div id=\"content\">\n"
2037         );
2038
2039         wprintf("<div id=\"fix_scrollbar_bug\">"
2040                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
2041
2042         wprintf("<CENTER>\n");
2043         wprintf("<br />");
2044         wprintf(_("If you know the name of a hidden (guess-name) or "
2045                 "passworded room, you can enter that room by typing "
2046                 "its name below.  Once you gain access to a private "
2047                 "room, it will appear in your regular room listings "
2048                 "so you don't have to keep returning here."));
2049         wprintf("\n<br /><br />");
2050
2051         wprintf("<FORM METHOD=\"POST\" action=\"goto_private\">\n");
2052
2053         wprintf("<table border=\"0\" cellspacing=\"5\" "
2054                 "cellpadding=\"5\" BGCOLOR=\"#EEEEEE\">\n"
2055                 "<TR><TD>");
2056         wprintf(_("Enter room name:"));
2057         wprintf("</TD><TD>"
2058                 "<INPUT TYPE=\"text\" NAME=\"gr_name\" "
2059                 "VALUE=\"%s\" MAXLENGTH=\"128\">\n", rname);
2060
2061         if (req_pass) {
2062                 wprintf("</TD></TR><TR><TD>");
2063                 wprintf(_("Enter room password:"));
2064                 wprintf("</TD><TD>");
2065                 wprintf("<INPUT TYPE=\"password\" NAME=\"gr_pass\" MAXLENGTH=\"9\">\n");
2066         }
2067         wprintf("</TD></TR></TABLE><br />\n");
2068
2069         wprintf("<INPUT TYPE=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">"
2070                 "&nbsp;"
2071                 "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">",
2072                 _("Go there"),
2073                 _("Cancel")
2074         );
2075         wprintf("</FORM>\n");
2076         wprintf("</td></tr></table></div>\n");
2077         wDumpContent(1);
2078 }
2079
2080 /* 
2081  * goto a private room
2082  */
2083 void goto_private(void)
2084 {
2085         char hold_rm[SIZ];
2086         char buf[SIZ];
2087
2088         if (strlen(bstr("ok_button")) == 0) {
2089                 display_main_menu();
2090                 return;
2091         }
2092         strcpy(hold_rm, WC->wc_roomname);
2093         strcpy(buf, "GOTO ");
2094         strcat(buf, bstr("gr_name"));
2095         strcat(buf, "|");
2096         strcat(buf, bstr("gr_pass"));
2097         serv_puts(buf);
2098         serv_getln(buf, sizeof buf);
2099
2100         if (buf[0] == '2') {
2101                 smart_goto(bstr("gr_name"));
2102                 return;
2103         }
2104         if (!strncmp(buf, "540", 3)) {
2105                 display_private(bstr("gr_name"), 1);
2106                 return;
2107         }
2108         output_headers(1, 1, 1, 0, 0, 0);
2109         wprintf("%s\n", &buf[4]);
2110         wDumpContent(1);
2111         return;
2112 }
2113
2114
2115 /*
2116  * display the screen to zap a room
2117  */
2118 void display_zap(void)
2119 {
2120         output_headers(1, 1, 2, 0, 0, 0);
2121
2122         wprintf("<div id=\"banner\">\n");
2123         wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#770000\"><TR><TD>");
2124         wprintf("<SPAN CLASS=\"titlebar\">");
2125         wprintf(_("Zap (forget/unsubscribe) the current room"));
2126         wprintf("</SPAN>\n");
2127         wprintf("</TD></TR></TABLE>\n");
2128         wprintf("</div>\n<div id=\"content\">\n");
2129
2130         wprintf(_("If you select this option, <em>%s</em> will "
2131                 "disappear from your room list.  Is this what you wish "
2132                 "to do?<br />\n"), WC->wc_roomname);
2133
2134         wprintf("<FORM METHOD=\"POST\" action=\"zap\">\n");
2135         wprintf("<INPUT TYPE=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Zap this room"));
2136         wprintf("&nbsp;");
2137         wprintf("<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
2138         wprintf("</FORM>\n");
2139         wDumpContent(1);
2140 }
2141
2142
2143 /* 
2144  * zap a room
2145  */
2146 void zap(void)
2147 {
2148         char buf[SIZ];
2149         char final_destination[SIZ];
2150
2151         /* If the forget-room routine fails for any reason, we fall back
2152          * to the current room; otherwise, we go to the Lobby
2153          */
2154         strcpy(final_destination, WC->wc_roomname);
2155
2156         if (strlen(bstr("ok_button")) > 0) {
2157                 serv_printf("GOTO %s", WC->wc_roomname);
2158                 serv_getln(buf, sizeof buf);
2159                 if (buf[0] == '2') {
2160                         serv_puts("FORG");
2161                         serv_getln(buf, sizeof buf);
2162                         if (buf[0] == '2') {
2163                                 strcpy(final_destination, "_BASEROOM_");
2164                         }
2165                 }
2166         }
2167         smart_goto(final_destination);
2168 }
2169
2170
2171
2172 /*
2173  * Delete the current room
2174  */
2175 void delete_room(void)
2176 {
2177         char buf[SIZ];
2178
2179         serv_puts("KILL 1");
2180         serv_getln(buf, sizeof buf);
2181         if (buf[0] != '2') {
2182                 strcpy(WC->ImportantMessage, &buf[4]);
2183                 display_main_menu();
2184                 return;
2185         } else {
2186                 smart_goto("_BASEROOM_");
2187         }
2188 }
2189
2190
2191
2192 /*
2193  * Perform changes to a room's network configuration
2194  */
2195 void netedit(void) {
2196         FILE *fp;
2197         char buf[SIZ];
2198         char line[SIZ];
2199         char cmpa0[SIZ];
2200         char cmpa1[SIZ];
2201         char cmpb0[SIZ];
2202         char cmpb1[SIZ];
2203
2204         if (strlen(bstr("line"))==0) {
2205                 display_editroom();
2206                 return;
2207         }
2208
2209         strcpy(line, bstr("prefix"));
2210         strcat(line, bstr("line"));
2211         strcat(line, bstr("suffix"));
2212
2213         fp = tmpfile();
2214         if (fp == NULL) {
2215                 display_editroom();
2216                 return;
2217         }
2218
2219         serv_puts("GNET");
2220         serv_getln(buf, sizeof buf);
2221         if (buf[0] != '1') {
2222                 fclose(fp);
2223                 display_editroom();
2224                 return;
2225         }
2226
2227         /* This loop works for add *or* remove.  Spiffy, eh? */
2228         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2229                 extract_token(cmpa0, buf, 0, '|', sizeof cmpa0);
2230                 extract_token(cmpa1, buf, 1, '|', sizeof cmpa1);
2231                 extract_token(cmpb0, line, 0, '|', sizeof cmpb0);
2232                 extract_token(cmpb1, line, 1, '|', sizeof cmpb1);
2233                 if ( (strcasecmp(cmpa0, cmpb0)) 
2234                    || (strcasecmp(cmpa1, cmpb1)) ) {
2235                         fprintf(fp, "%s\n", buf);
2236                 }
2237         }
2238
2239         rewind(fp);
2240         serv_puts("SNET");
2241         serv_getln(buf, sizeof buf);
2242         if (buf[0] != '4') {
2243                 fclose(fp);
2244                 display_editroom();
2245                 return;
2246         }
2247
2248         while (fgets(buf, sizeof buf, fp) != NULL) {
2249                 buf[strlen(buf)-1] = 0;
2250                 serv_puts(buf);
2251         }
2252
2253         if (strlen(bstr("add_button")) > 0) {
2254                 serv_puts(line);
2255         }
2256
2257         serv_puts("000");
2258         fclose(fp);
2259         display_editroom();
2260 }
2261
2262
2263
2264 /*
2265  * Convert a room name to a folder-ish-looking name.
2266  */
2267 void room_to_folder(char *folder, char *room, int floor, int is_mailbox)
2268 {
2269         int i;
2270
2271         /*
2272          * For mailboxes, just do it straight...
2273          */
2274         if (is_mailbox) {
2275                 sprintf(folder, "My folders|%s", room);
2276         }
2277
2278         /*
2279          * Otherwise, prefix the floor name as a "public folders" moniker
2280          */
2281         else {
2282                 sprintf(folder, "%s|%s", floorlist[floor], room);
2283         }
2284
2285         /*
2286          * Replace "\" characters with "|" for pseudo-folder-delimiting
2287          */
2288         for (i=0; i<strlen(folder); ++i) {
2289                 if (folder[i] == '\\') folder[i] = '|';
2290         }
2291 }
2292
2293
2294
2295
2296 /*
2297  * Back end for change_view()
2298  */
2299 void do_change_view(int newview) {
2300         char buf[SIZ];
2301
2302         serv_printf("VIEW %d", newview);
2303         serv_getln(buf, sizeof buf);
2304         WC->wc_view = newview;
2305         smart_goto(WC->wc_roomname);
2306 }
2307
2308
2309
2310 /*
2311  * Change the view for this room
2312  */
2313 void change_view(void) {
2314         int view;
2315
2316         view = atol(bstr("view"));
2317         do_change_view(view);
2318 }
2319
2320
2321 /*
2322  * One big expanded tree list view --- like a folder list
2323  */
2324 void do_folder_view(struct folder *fold, int max_folders, int num_floors) {
2325         char buf[SIZ];
2326         int levels;
2327         int i;
2328         int has_subfolders = 0;
2329         int *parents;
2330
2331         parents = malloc(max_folders * sizeof(int));
2332
2333         /* BEGIN TREE MENU */
2334         wprintf("<div id=\"roomlist_div\">Loading folder list...</div>\n");
2335
2336         /* include NanoTree */
2337         wprintf("<script type=\"text/javascript\" src=\"static/nanotree.js\"></script>\n");
2338
2339         /* initialize NanoTree */
2340         wprintf("<script type=\"text/javascript\">                      \n"
2341                 "       showRootNode = false;                           \n"
2342                 "       sortNodes = false;                              \n"
2343                 "       dragable = false;                               \n"
2344                 "                                                       \n"
2345                 "       function standardClick(treeNode) {              \n"
2346                 "       }                                               \n"
2347                 "                                                       \n"
2348                 "       var closedGif = 'static/folder_closed.gif';     \n"
2349                 "       var openGif = 'static/folder_open.gif';         \n"
2350                 "                                                       \n"
2351                 "       rootNode = new TreeNode(1, 'root node - hide'); \n"
2352         );
2353
2354         levels = 0;
2355         for (i=0; i<max_folders; ++i) {
2356
2357                 has_subfolders = 0;
2358                 if ((i+1) < max_folders) {
2359                         if ( (!strncasecmp(fold[i].name, fold[i+1].name, strlen(fold[i].name)))
2360                            && (fold[i+1].name[strlen(fold[i].name)] == '|') ) {
2361                                 has_subfolders = 1;
2362                         }
2363                 }
2364
2365                 levels = num_tokens(fold[i].name, '|');
2366                 parents[levels] = i;
2367
2368                 wprintf("var node%d = new TreeNode(%d, '", i, i);
2369
2370                 if (fold[i].selectable) {
2371                         wprintf("<a href=\"dotgoto?room=");
2372                         urlescputs(fold[i].room);
2373                         wprintf("\">");
2374                 }
2375
2376                 if (levels == 1) {
2377                         wprintf("<SPAN CLASS=\"roomlist_floor\">");
2378                 }
2379                 else if (fold[i].hasnewmsgs) {
2380                         wprintf("<SPAN CLASS=\"roomlist_new\">");
2381                 }
2382                 else {
2383                         wprintf("<SPAN CLASS=\"roomlist_old\">");
2384                 }
2385                 extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
2386                 escputs(buf);
2387                 wprintf("</SPAN>");
2388
2389                 wprintf("</a>', ");
2390                 if (has_subfolders) {
2391                         wprintf("new Array(closedGif, openGif)");
2392                 }
2393                 else if (fold[i].view == VIEW_ADDRESSBOOK) {
2394                         wprintf("'static/viewcontacts_16x.gif'");
2395                 }
2396                 else if (fold[i].view == VIEW_CALENDAR) {
2397                         wprintf("'static/calarea_16x.gif'");
2398                 }
2399                 else if (fold[i].view == VIEW_TASKS) {
2400                         wprintf("'static/taskmanag_16x.gif'");
2401                 }
2402                 else if (fold[i].view == VIEW_NOTES) {
2403                         wprintf("'static/storenotes_16x.gif'");
2404                 }
2405                 else if (fold[i].view == VIEW_MAILBOX) {
2406                         wprintf("'static/privatemess_16x.gif'");
2407                 }
2408                 else {
2409                         wprintf("'static/chatrooms_16x.gif'");
2410                 }
2411                 wprintf(", '");
2412                 urlescputs(fold[i].name);
2413                 wprintf("');\n");
2414
2415                 if (levels < 2) {
2416                         wprintf("rootNode.addChild(node%d);\n", i);
2417                 }
2418                 else {
2419                         wprintf("node%d.addChild(node%d);\n", parents[levels-1], i);
2420                 }
2421         }
2422
2423         wprintf("container = document.getElementById('roomlist_div');   \n"
2424                 "showTree('');  \n"
2425                 "</script>\n"
2426         );
2427
2428         free(parents);
2429         /* END TREE MENU */
2430 }
2431
2432 /*
2433  * Boxes and rooms and lists ... oh my!
2434  */
2435 void do_rooms_view(struct folder *fold, int max_folders, int num_floors) {
2436         char buf[256];
2437         char floor_name[256];
2438         char old_floor_name[256];
2439         char boxtitle[256];
2440         int levels, oldlevels;
2441         int i, t;
2442         int num_boxes = 0;
2443         static int columns = 3;
2444         int boxes_per_column = 0;
2445         int current_column = 0;
2446         int nf;
2447
2448         strcpy(floor_name, "");
2449         strcpy(old_floor_name, "");
2450
2451         nf = num_floors;
2452         while (nf % columns != 0) ++nf;
2453         boxes_per_column = (nf / columns);
2454         if (boxes_per_column < 1) boxes_per_column = 1;
2455
2456         /* Outer table (for columnization) */
2457         wprintf("<TABLE BORDER=0 WIDTH=96%% CELLPADDING=5>"
2458                 "<tr><td valign=top>");
2459
2460         levels = 0;
2461         oldlevels = 0;
2462         for (i=0; i<max_folders; ++i) {
2463
2464                 levels = num_tokens(fold[i].name, '|');
2465                 extract_token(floor_name, fold[i].name, 0,
2466                         '|', sizeof floor_name);
2467
2468                 if ( (strcasecmp(floor_name, old_floor_name))
2469                    && (strlen(old_floor_name) > 0) ) {
2470                         /* End inner box */
2471                         do_template("endbox");
2472
2473                         ++num_boxes;
2474                         if ((num_boxes % boxes_per_column) == 0) {
2475                                 ++current_column;
2476                                 if (current_column < columns) {
2477                                         wprintf("</td><td valign=top>\n");
2478                                 }
2479                         }
2480                 }
2481                 strcpy(old_floor_name, floor_name);
2482
2483                 if (levels == 1) {
2484                         /* Begin inner box */
2485                         stresc(boxtitle, floor_name, 1, 0);
2486                         svprintf("BOXTITLE", WCS_STRING, boxtitle);
2487                         do_template("beginbox");
2488                 }
2489
2490                 oldlevels = levels;
2491
2492                 if (levels > 1) {
2493                         wprintf("&nbsp;");
2494                         if (levels>2) for (t=0; t<(levels-2); ++t) wprintf("&nbsp;&nbsp;&nbsp;");
2495                         if (fold[i].selectable) {
2496                                 wprintf("<a href=\"dotgoto?room=");
2497                                 urlescputs(fold[i].room);
2498                                 wprintf("\">");
2499                         }
2500                         else {
2501                                 wprintf("<i>");
2502                         }
2503                         if (fold[i].hasnewmsgs) {
2504                                 wprintf("<SPAN CLASS=\"roomlist_new\">");
2505                         }
2506                         else {
2507                                 wprintf("<SPAN CLASS=\"roomlist_old\">");
2508                         }
2509                         extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
2510                         escputs(buf);
2511                         wprintf("</SPAN>");
2512                         if (fold[i].selectable) {
2513                                 wprintf("</A>");
2514                         }
2515                         else {
2516                                 wprintf("</i>");
2517                         }
2518                         if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
2519                                 wprintf(" (INBOX)");
2520                         }
2521                         wprintf("<br />\n");
2522                 }
2523         }
2524         /* End the final inner box */
2525         do_template("endbox");
2526
2527         wprintf("</TD></TR></TABLE>\n");
2528 }
2529
2530
2531 /*
2532  * Show the room list.  (only should get called by
2533  * knrooms() because that's where output_headers() is called from)
2534  */
2535
2536 void list_all_rooms_by_floor(char *viewpref) {
2537         char buf[SIZ];
2538         int swap = 0;
2539         struct folder *fold = NULL;
2540         struct folder ftmp;
2541         int max_folders = 0;
2542         int alloc_folders = 0;
2543         int i, j;
2544         int ra_flags = 0;
2545         int flags = 0;
2546         int num_floors = 1;     /* add an extra one for private folders */
2547
2548         /* Start with the mailboxes */
2549         max_folders = 1;
2550         alloc_folders = 1;
2551         fold = malloc(sizeof(struct folder));
2552         memset(fold, 0, sizeof(struct folder));
2553         strcpy(fold[0].name, "My folders");
2554         fold[0].is_mailbox = 1;
2555
2556         /* Then add floors */
2557         serv_puts("LFLR");
2558         serv_getln(buf, sizeof buf);
2559         if (buf[0]=='1') while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2560                 if (max_folders >= alloc_folders) {
2561                         alloc_folders = max_folders + 100;
2562                         fold = realloc(fold,
2563                                 alloc_folders * sizeof(struct folder));
2564                 }
2565                 memset(&fold[max_folders], 0, sizeof(struct folder));
2566                 extract_token(fold[max_folders].name, buf, 1, '|', sizeof fold[max_folders].name);
2567                 ++max_folders;
2568                 ++num_floors;
2569         }
2570
2571         /* Now add rooms */
2572         serv_puts("LKRA");
2573         serv_getln(buf, sizeof buf);
2574         if (buf[0]=='1') while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2575                 if (max_folders >= alloc_folders) {
2576                         alloc_folders = max_folders + 100;
2577                         fold = realloc(fold,
2578                                 alloc_folders * sizeof(struct folder));
2579                 }
2580                 memset(&fold[max_folders], 0, sizeof(struct folder));
2581                 extract_token(fold[max_folders].room, buf, 0, '|', sizeof fold[max_folders].room);
2582                 ra_flags = extract_int(buf, 5);
2583                 flags = extract_int(buf, 1);
2584                 fold[max_folders].floor = extract_int(buf, 2);
2585                 fold[max_folders].hasnewmsgs =
2586                         ((ra_flags & UA_HASNEWMSGS) ? 1 : 0 );
2587                 if (flags & QR_MAILBOX) {
2588                         fold[max_folders].is_mailbox = 1;
2589                 }
2590                 fold[max_folders].view = extract_int(buf, 6);
2591                 room_to_folder(fold[max_folders].name,
2592                                 fold[max_folders].room,
2593                                 fold[max_folders].floor,
2594                                 fold[max_folders].is_mailbox);
2595                 fold[max_folders].selectable = 1;
2596                 ++max_folders;
2597         }
2598
2599         /* Bubble-sort the folder list */
2600         for (i=0; i<max_folders; ++i) {
2601                 for (j=0; j<(max_folders-1)-i; ++j) {
2602                         if (fold[j].is_mailbox == fold[j+1].is_mailbox) {
2603                                 swap = strcasecmp(fold[j].name, fold[j+1].name);
2604                         }
2605                         else {
2606                                 if ( (fold[j+1].is_mailbox)
2607                                    && (!fold[j].is_mailbox)) {
2608                                         swap = 1;
2609                                 }
2610                                 else {
2611                                         swap = 0;
2612                                 }
2613                         }
2614                         if (swap > 0) {
2615                                 memcpy(&ftmp, &fold[j], sizeof(struct folder));
2616                                 memcpy(&fold[j], &fold[j+1],
2617                                                         sizeof(struct folder));
2618                                 memcpy(&fold[j+1], &ftmp,
2619                                                         sizeof(struct folder));
2620                         }
2621                 }
2622         }
2623
2624 /* test only hackish view 
2625         wprintf("<table><TR><TD>A Table</TD></TR></table>\n");
2626         for (i=0; i<max_folders; ++i) {
2627                 escputs(fold[i].name);
2628                 wprintf("<br />\n");
2629         }
2630  */
2631
2632         if (!strcasecmp(viewpref, "folders")) {
2633                 do_folder_view(fold, max_folders, num_floors);
2634         }
2635         else {
2636                 do_rooms_view(fold, max_folders, num_floors);
2637         }
2638
2639         free(fold);
2640         wDumpContent(1);
2641 }
2642
2643
2644 /* Do either a known rooms list or a folders list, depending on the
2645  * user's preference
2646  */
2647 void knrooms() {
2648         char listviewpref[SIZ];
2649
2650         output_headers(1, 1, 2, 0, 0, 0);
2651         load_floorlist();
2652
2653         /* Determine whether the user is trying to change views */
2654         if (bstr("view") != NULL) {
2655                 if (strlen(bstr("view")) > 0) {
2656                         set_preference("roomlistview", bstr("view"), 1);
2657                 }
2658         }
2659
2660         get_preference("roomlistview", listviewpref, sizeof listviewpref);
2661
2662         if ( (strcasecmp(listviewpref, "folders"))
2663            && (strcasecmp(listviewpref, "table")) ) {
2664                 strcpy(listviewpref, "rooms");
2665         }
2666
2667         /* title bar */
2668         wprintf("<div id=\"banner\">\n"
2669                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
2670                 "<SPAN CLASS=\"titlebar\">"
2671         );
2672         if (!strcasecmp(listviewpref, "rooms")) {
2673                 wprintf("Room list");
2674         }
2675         if (!strcasecmp(listviewpref, "folders")) {
2676                 wprintf("Folder list");
2677         }
2678         if (!strcasecmp(listviewpref, "table")) {
2679                 wprintf("Room list");
2680         }
2681         wprintf("</SPAN></TD>\n");
2682
2683         /* offer the ability to switch views */
2684         wprintf("<TD ALIGN=RIGHT><FORM NAME=\"roomlistomatic\">\n"
2685                 "<SELECT NAME=\"newview\" SIZE=\"1\" "
2686                 "OnChange=\"location.href=roomlistomatic.newview.options"
2687                 "[selectedIndex].value\">\n");
2688
2689         wprintf("<OPTION %s VALUE=\"/knrooms&view=rooms\">"
2690                 "View as room list"
2691                 "</OPTION>\n",
2692                 ( !strcasecmp(listviewpref, "rooms") ? "SELECTED" : "" )
2693         );
2694
2695         wprintf("<OPTION %s VALUE=\"/knrooms&view=folders\">"
2696                 "View as folder list"
2697                 "</OPTION>\n",
2698                 ( !strcasecmp(listviewpref, "folders") ? "SELECTED" : "" )
2699         );
2700
2701         wprintf("</SELECT><br />");
2702         offer_start_page();
2703         wprintf("</FORM></TD></TR></TABLE>\n");
2704         wprintf("</div>\n"
2705                 "</div>\n"
2706                 "<div id=\"content\">\n");
2707
2708         /* Display the room list in the user's preferred format */
2709         list_all_rooms_by_floor(listviewpref);
2710 }
2711
2712
2713
2714 /* 
2715  * Set the message expire policy for this room and/or floor
2716  */
2717 void set_room_policy(void) {
2718         char buf[SIZ];
2719
2720         if (strlen(bstr("ok_button")) == 0) {
2721                 strcpy(WC->ImportantMessage,
2722                         _("Cancelled.  Changes were not saved."));
2723                 display_editroom();
2724                 return;
2725         }
2726
2727         serv_printf("SPEX room|%d|%d", atoi(bstr("roompolicy")), atoi(bstr("roomvalue")));
2728         serv_getln(buf, sizeof buf);
2729         strcpy(WC->ImportantMessage, &buf[4]);
2730
2731         if (WC->axlevel >= 6) {
2732                 strcat(WC->ImportantMessage, "<br />\n");
2733                 serv_printf("SPEX floor|%d|%d", atoi(bstr("floorpolicy")), atoi(bstr("floorvalue")));
2734                 serv_getln(buf, sizeof buf);
2735                 strcat(WC->ImportantMessage, &buf[4]);
2736         }
2737
2738         display_editroom();
2739 }