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