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