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