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