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