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