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