51dd72788700bf90f8851159d4596eb6af44754a
[citadel.git] / webcit / roomops.c
1 /*
2  * $Id$
3  * Lots of different room-related operations.
4  */
5
6 #include "webcit.h"
7 #include "webserver.h"
8 #define MAX_FLOORS 128
9 char floorlist[MAX_FLOORS][SIZ]; /**< list of our floor names */
10
11 char *viewdefs[9]; /**< the different kinds of available views */
12
13 void display_whok(void);
14
15 /*
16  * 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         viewdefs[7] = _("Calendar List");
27         viewdefs[8] = _("Journal");
28 }
29
30 /*
31  * Determine which views are allowed as the default for creating a new room.
32  */
33 int is_view_allowed_as_default(int which_view)
34 {
35         switch(which_view) {
36                 case VIEW_BBS:          return(1);
37                 case VIEW_MAILBOX:      return(1);
38                 case VIEW_ADDRESSBOOK:  return(1);
39                 case VIEW_CALENDAR:     return(1);
40                 case VIEW_TASKS:        return(1);
41                 case VIEW_NOTES:        return(1);
42
43 #ifdef TECH_PREVIEW
44                 case VIEW_WIKI:         return(1);
45 #else /* TECH_PREVIEW */
46                 case VIEW_WIKI:         return(0);      /* because it isn't finished yet */
47 #endif /* TECH_PREVIEW */
48
49                 case VIEW_CALBRIEF:     return(0);
50                 case VIEW_JOURNAL:      return(0);
51                 default:                return(0);      /* should never get here */
52         }
53 }
54
55
56 /*
57  * load the list of floors
58  */
59 void load_floorlist(void)
60 {
61         int a;
62         char buf[SIZ];
63
64         for (a = 0; a < MAX_FLOORS; ++a)
65                 floorlist[a][0] = 0;
66
67         serv_puts("LFLR");
68         serv_getln(buf, sizeof buf);
69         if (buf[0] != '1') {
70                 strcpy(floorlist[0], "Main Floor");
71                 return;
72         }
73         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
74                 extract_token(floorlist[extract_int(buf, 0)], buf, 1, '|', sizeof floorlist[0]);
75         }
76 }
77
78
79 /*
80  * Free a session's march list
81  */
82 void free_march_list(struct wcsession *wcf)
83 {
84         struct march *mptr;
85
86         while (wcf->march != NULL) {
87                 mptr = wcf->march->next;
88                 free(wcf->march);
89                 wcf->march = mptr;
90         }
91
92 }
93
94
95
96 /*
97  * remove a room from the march list
98  */
99 void remove_march(char *aaa)
100 {
101         struct march *mptr, *mptr2;
102
103         if (WC->march == NULL)
104                 return;
105
106         if (!strcasecmp(WC->march->march_name, aaa)) {
107                 mptr = WC->march->next;
108                 free(WC->march);
109                 WC->march = mptr;
110                 return;
111         }
112         mptr2 = WC->march;
113         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
114                 if (!strcasecmp(mptr->march_name, aaa)) {
115                         mptr2->next = mptr->next;
116                         free(mptr);
117                         mptr = mptr2;
118                 } else {
119                         mptr2 = mptr;
120                 }
121         }
122 }
123
124
125
126
127 /*
128  * display rooms in tree structure
129  */
130 void room_tree_list(struct roomlisting *rp)
131 {
132         char rmname[64];
133         int f;
134
135         if (rp == NULL) {
136                 return;
137         }
138
139         room_tree_list(rp->lnext);
140
141         strcpy(rmname, rp->rlname);
142         f = rp->rlflags;
143
144         wprintf("<a href=\"dotgoto&room=");
145         urlescputs(rmname);
146         wprintf("\"");
147         wprintf(">");
148         escputs1(rmname, 1, 1);
149         if ((f & QR_DIRECTORY) && (f & QR_NETWORK))
150                 wprintf("}");
151         else if (f & QR_DIRECTORY)
152                 wprintf("]");
153         else if (f & QR_NETWORK)
154                 wprintf(")");
155         else
156                 wprintf("&gt;");
157         wprintf("</a><tt> </tt>\n");
158
159         room_tree_list(rp->rnext);
160         free(rp);
161 }
162
163
164 /** 
165  * \brief Room ordering stuff (compare first by floor, then by order)
166  * \param r1 first roomlist to compare
167  * \param r2 second roomlist co compare
168  * \return are they the same???
169  */
170 int rordercmp(struct roomlisting *r1, struct roomlisting *r2)
171 {
172         if ((r1 == NULL) && (r2 == NULL))
173                 return (0);
174         if (r1 == NULL)
175                 return (-1);
176         if (r2 == NULL)
177                 return (1);
178         if (r1->rlfloor < r2->rlfloor)
179                 return (-1);
180         if (r1->rlfloor > r2->rlfloor)
181                 return (1);
182         if (r1->rlorder < r2->rlorder)
183                 return (-1);
184         if (r1->rlorder > r2->rlorder)
185                 return (1);
186         return (0);
187 }
188
189
190 /**
191  * \brief Common code for all room listings
192  * \param variety what???
193  */
194 void listrms(char *variety)
195 {
196         char buf[SIZ];
197         int num_rooms = 0;
198
199         struct roomlisting *rl = NULL;
200         struct roomlisting *rp;
201         struct roomlisting *rs;
202
203         /** Ask the server for a room list */
204         serv_puts(variety);
205         serv_getln(buf, sizeof buf);
206         if (buf[0] != '1') {
207                 wprintf("&nbsp;");
208                 return;
209         }
210
211         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
212                 ++num_rooms;
213                 rp = malloc(sizeof(struct roomlisting));
214                 extract_token(rp->rlname, buf, 0, '|', sizeof rp->rlname);
215                 rp->rlflags = extract_int(buf, 1);
216                 rp->rlfloor = extract_int(buf, 2);
217                 rp->rlorder = extract_int(buf, 3);
218                 rp->lnext = NULL;
219                 rp->rnext = NULL;
220
221                 rs = rl;
222                 if (rl == NULL) {
223                         rl = rp;
224                 } else
225                         while (rp != NULL) {
226                                 if (rordercmp(rp, rs) < 0) {
227                                         if (rs->lnext == NULL) {
228                                                 rs->lnext = rp;
229                                                 rp = NULL;
230                                         } else {
231                                                 rs = rs->lnext;
232                                         }
233                                 } else {
234                                         if (rs->rnext == NULL) {
235                                                 rs->rnext = rp;
236                                                 rp = NULL;
237                                         } else {
238                                                 rs = rs->rnext;
239                                         }
240                                 }
241                         }
242         }
243
244         room_tree_list(rl);
245
246         /**
247          * If no rooms were listed, print an nbsp to make the cell
248          * borders show up anyway.
249          */
250         if (num_rooms == 0) wprintf("&nbsp;");
251 }
252
253
254 /**
255  * \brief list all forgotten rooms
256  */
257 void zapped_list(void)
258 {
259         StrBuf *Buf;
260         output_headers(1, 1, 1, 0, 0, 0);
261
262         Buf = NewStrBufPlain(_("Zapped (forgotten) rooms"), -1);
263         DoTemplate(HKEY("beginbox"), NULL, Buf, CTX_STRBUF);
264
265         FreeStrBuf(&Buf);
266
267         listrms("LZRM -1");
268
269         wprintf("<br /><br />\n");
270         wprintf(_("Click on any room to un-zap it and goto that room.\n"));
271         do_template("endbox", NULL);
272         wDumpContent(1);
273 }
274
275
276 /**
277  * \brief read this room's info file (set v to 1 for verbose mode)
278  */
279 void readinfo(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
280 {
281         char buf[256];
282         char briefinfo[128];
283         char fullinfo[8192];
284         int fullinfo_len = 0;
285
286         serv_puts("RINF");
287         serv_getln(buf, sizeof buf);
288         if (buf[0] == '1') {
289
290                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
291                         if (fullinfo_len < (sizeof fullinfo - sizeof buf)) {
292                                 strcpy(&fullinfo[fullinfo_len], buf);
293                                 fullinfo_len += strlen(buf);
294                         }
295                 }
296
297                 safestrncpy(briefinfo, fullinfo, sizeof briefinfo);
298                 strcpy(&briefinfo[50], "...");
299
300                 wprintf("<div class=\"infos\" "
301                 "onclick=\"javascript:Effect.Appear('room_infos', { duration: 0.5 });\" "
302                 ">");
303                 escputs(briefinfo);
304                 wprintf("</div><div id=\"room_infos\" style=\"display:none;\">");
305                 wprintf("<img class=\"close_infos\" "
306                         "onclick=\"javascript:Effect.Fade('room_infos', { duration: 0.5 });\" "
307                         "src=\"static/closewindow.gif\" alt=\"%s\">",
308                         _("Close window")
309                 );
310                 escputs(fullinfo);
311                 wprintf("</div>");
312         }
313         else {
314                 wprintf("&nbsp;");
315         }
316 }
317
318
319
320
321 /**
322  * \brief Display room banner icon.  
323  * The server doesn't actually
324  * need the room name, but we supply it in order to
325  * keep the browser from using a cached icon from 
326  * another room.
327  */
328 void embed_room_graphic(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) {
329         char buf[SIZ];
330
331         serv_puts("OIMG _roompic_");
332         serv_getln(buf, sizeof buf);
333         if (buf[0] == '2') {
334                 wprintf("<img height=\"64px\" src=\"image&name=_roompic_&room=");
335                 urlescputs(WC->wc_roomname);
336                 wprintf("\">");
337                 serv_puts("CLOS");
338                 serv_getln(buf, sizeof buf);
339         }
340         else if (WC->wc_view == VIEW_ADDRESSBOOK) {
341                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
342                         "static/viewcontacts_48x.gif"
343                         "\">"
344                 );
345         }
346         else if ( (WC->wc_view == VIEW_CALENDAR) || (WC->wc_view == VIEW_CALBRIEF) ) {
347                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
348                         "static/calarea_48x.gif"
349                         "\">"
350                 );
351         }
352         else if (WC->wc_view == VIEW_TASKS) {
353                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
354                         "static/taskmanag_48x.gif"
355                         "\">"
356                 );
357         }
358         else if (WC->wc_view == VIEW_NOTES) {
359                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
360                         "static/storenotes_48x.gif"
361                         "\">"
362                 );
363         }
364         else if (WC->wc_view == VIEW_MAILBOX) {
365                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
366                         "static/privatemess_48x.gif"
367                         "\">"
368                 );
369         }
370         else {
371                 wprintf("<img class=\"roompic\" alt=\"\" src=\""
372                         "static/chatrooms_48x.gif"
373                         "\">"
374                 );
375         }
376
377 }
378
379
380
381 /**
382  * \brief Display the current view and offer an option to change it
383  */
384 void embed_view_o_matic(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) {
385         int i;
386
387         wprintf("<form name=\"viewomatic\" action=\"changeview\">\n");
388         wprintf("\t<div style=\"display: inline;\">\n\t<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
389         wprintf("<label for=\"view_name\">");
390         wprintf(_("View as:"));
391         wprintf("</label> "
392                 "<select name=\"newview\" size=\"1\" "
393                 "id=\"view_name\" class=\"selectbox\" "
394                 "OnChange=\"location.href=viewomatic.newview.options"
395                 "[selectedIndex].value\">\n");
396
397         for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
398                 /**
399                  * Only offer the views that make sense, given the default
400                  * view for the room.  For example, don't offer a Calendar
401                  * view in a non-Calendar room.
402                  */
403                 if (
404                         (i == WC->wc_view)
405                         ||      (i == WC->wc_default_view)                      /**< default */
406                         ||      ( (i == 0) && (WC->wc_default_view == 1) )      /**< mail or bulletin */
407                         ||      ( (i == 1) && (WC->wc_default_view == 0) )      /**< mail or bulletin */
408                         /** ||  ( (i == 7) && (WC->wc_default_view == 3) )      (calendar list temporarily disabled) */
409                 ) {
410
411                         wprintf("<option %s value=\"changeview?view=%d\">",
412                                 ((i == WC->wc_view) ? "selected" : ""),
413                                 i );
414                         escputs(viewdefs[i]);
415                         wprintf("</option>\n");
416                 }
417         }
418         wprintf("</select></div></form>\n");
419 }
420
421
422 /**
423  * \brief Display a search box
424  */
425 void embed_search_o_matic(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) {
426         wprintf("<form name=\"searchomatic\" action=\"do_search\">\n");
427         wprintf("<div style=\"display: inline;\"><input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
428         wprintf("<label for=\"search_name\">");
429         wprintf(_("Search: "));
430         wprintf("</label><input ");
431         wprintf("%s", serv_info.serv_fulltext_enabled ? "" : "disabled ");
432         wprintf("type=\"text\" name=\"query\" size=\"15\" maxlength=\"128\" "
433                 "id=\"search_name\" class=\"inputbox\">\n"
434         );
435         wprintf("</div></form>\n");
436 }
437
438
439 /**
440  * \brief               Embed the room banner
441  *
442  * \param got           The information returned from a GOTO server command
443  * \param navbar_style  Determines which navigation buttons to display
444  *
445  */
446
447 void embed_room_banner(char *got, int navbar_style) {
448         char buf[256];
449         char buf2[1024];
450         char with_files[256];
451         int file_count=0;
452         
453         /**
454          * We need to have the information returned by a GOTO server command.
455          * If it isn't supplied, we fake it by issuing our own GOTO.
456          */
457         if (got == NULL) {
458                 memset(buf, 20, '0');
459                 buf[20] = '\0';
460                 serv_printf("GOTO %s", WC->wc_roomname);
461                 serv_getln(buf, sizeof buf);
462                 got = buf;
463         }
464
465         /** The browser needs some information for its own use */
466         wprintf("<script type=\"text/javascript\">      \n"
467                 "       room_is_trash = %d;             \n"
468                 "</script>\n",
469                 WC->wc_is_trash
470         );
471
472         /**
473          * If the user happens to select the "make this my start page" link,
474          * we want it to remember the URL as a "/dotskip" one instead of
475          * a "skip" or "gotonext" or something like that.
476          */
477         snprintf(WC->this_page, sizeof(WC->this_page), "dotskip&room=%s",
478                 WC->wc_roomname);
479
480         /** Check for new mail. */
481         WC->new_mail = extract_int(&got[4], 9);
482         WC->wc_view = extract_int(&got[4], 11);
483
484         /* Is this a directory room and does it contain files and how many? */
485         if ((WC->room_flags & QR_DIRECTORY) && (WC->room_flags & QR_VISDIR))
486         {
487                 serv_puts("RDIR");
488                 serv_getln(buf2, sizeof buf2);
489                 if (buf2[0] == '1') while (serv_getln(buf2, sizeof buf2), strcmp(buf2, "000"))
490                         file_count++;
491                 snprintf (with_files, sizeof with_files, 
492                           "; <a href=\"display_room_directory\"> %d %s </a>", 
493                           file_count, 
494                           ((file_count>1) || (file_count == 0)  ? _("files") : _("file")));
495         }
496         else
497                 strcpy (with_files, "");
498         
499         svprintf(HKEY("NUMMSGS"), WCS_STRING,
500                 _("%d new of %d messages%s"),
501                 extract_int(&got[4], 1),
502                 extract_int(&got[4], 2),
503                 with_files
504         );
505         svcallback("ROOMPIC", embed_room_graphic);
506         svcallback("ROOMINFO", readinfo);
507         svcallback("VIEWOMATIC", embed_view_o_matic); 
508         svcallback("SEARCHOMATIC", embed_search_o_matic);
509         svcallback("START", offer_start_page); 
510  
511         do_template("roombanner", NULL);
512         // roombanner contains this for mobile
513         if (navbar_style != navbar_none && !WC->is_mobile) { 
514
515                 wprintf("<div id=\"navbar\"><ul>");
516
517                 if (navbar_style == navbar_default) wprintf(
518                         "<li class=\"ungoto\">"
519                         "<a href=\"ungoto\">"
520                         "<img src=\"static/ungoto2_24x.gif\" alt=\"\">"
521                         "<span class=\"navbar_link\">%s</span></A>"
522                         "</li>\n", _("Ungoto")
523                 );
524
525                 if ( (navbar_style == navbar_default) && (WC->wc_view == VIEW_BBS) ) {
526                         wprintf(
527                                 "<li class=\"newmess\">"
528                                 "<a href=\"readnew\">"
529                                 "<img src=\"static/newmess2_24x.gif\" alt=\"\">"
530                                 "<span class=\"navbar_link\">%s</span></A>"
531                                 "</li>\n", _("Read new messages")
532                         );
533                 }
534
535                 if (navbar_style == navbar_default) {
536                         switch(WC->wc_view) {
537                                 case VIEW_ADDRESSBOOK:
538                                         wprintf(
539                                                 "<li class=\"viewcontacts\">"
540                                                 "<a href=\"readfwd\">"
541                                                 "<img src=\"static/viewcontacts_24x.gif\" "
542                                                 "alt=\"\">"
543                                                 "<span class=\"navbar_link\">"
544                                                 "%s"
545                                                 "</span></a></li>\n", _("View contacts")
546                                         );
547                                         break;
548                                 case VIEW_CALENDAR:
549                                         wprintf(
550                                                 "<li class=\"staskday\">"
551                                                 "<a href=\"readfwd?calview=day\">"
552                                                 "<img src=\"static/taskday2_24x.gif\" "
553                                                 "alt=\"\">"
554                                                 "<span class=\"navbar_link\">"
555                                                 "%s"
556                                                 "</span></a></li>\n", _("Day view")
557                                         );
558                                         wprintf(
559                                                 "<li class=\"monthview\">"
560                                                 "<a href=\"readfwd?calview=month\">"
561                                                 "<img src=\"static/monthview2_24x.gif\" "
562                                                 "alt=\"\">"
563                                                 "<span class=\"navbar_link\">"
564                                                 "%s"
565                                                 "</span></a></li>\n", _("Month view")
566                                         );
567                                         break;
568                                 case VIEW_CALBRIEF:
569                                         wprintf(
570                                                 "<li class=\"monthview\">"
571                                                 "<a href=\"readfwd?calview=month\">"
572                                                 "<img src=\"static/monthview2_24x.gif\" "
573                                                 "alt=\"\">"
574                                                 "<span class=\"navbar_link\">"
575                                                 "%s"
576                                                 "</span></a></li>\n", _("Calendar list")
577                                         );
578                                         break;
579                                 case VIEW_TASKS:
580                                         wprintf(
581                                                 "<li class=\"taskmanag\">"
582                                                 "<a href=\"readfwd\">"
583                                                 "<img src=\"static/taskmanag_24x.gif\" "
584                                                 "alt=\"\">"
585                                                 "<span class=\"navbar_link\">"
586                                                 "%s"
587                                                 "</span></a></li>\n", _("View tasks")
588                                         );
589                                         break;
590                                 case VIEW_NOTES:
591                                         wprintf(
592                                                 "<li class=\"viewnotes\">"
593                                                 "<a href=\"readfwd\">"
594                                                 "<img src=\"static/viewnotes_24x.gif\" "
595                                                 "alt=\"\">"
596                                                 "<span class=\"navbar_link\">"
597                                                 "%s"
598                                                 "</span></a></li>\n", _("View notes")
599                                         );
600                                         break;
601                                 case VIEW_MAILBOX:
602                                         wprintf(
603                                                 "<li class=\"readallmess\">"
604                                                 "<a href=\"readfwd\">"
605                                                 "<img src=\"static/readallmess3_24x.gif\" "
606                                                 "alt=\"\">"
607                                                 "<span class=\"navbar_link\">"
608                                                 "%s"
609                                                 "</span></a></li>\n", _("View message list")
610                                         );
611                                         break;
612                                 case VIEW_WIKI:
613                                         wprintf(
614                                                 "<li class=\"readallmess\">"
615                                                 "<a href=\"readfwd\">"
616                                                 "<img src=\"static/readallmess3_24x.gif\" "
617                                                 "alt=\"\">"
618                                                 "<span class=\"navbar_link\">"
619                                                 "%s"
620                                                 "</span></a></li>\n", _("Wiki home")
621                                         );
622                                         break;
623                                 default:
624                                         wprintf(
625                                                 "<li class=\"readallmess\">"
626                                                 "<a href=\"readfwd\">"
627                                                 "<img src=\"static/readallmess3_24x.gif\" "
628                                                 "alt=\"\">"
629                                                 "<span class=\"navbar_link\">"
630                                                 "%s"
631                                                 "</span></a></li>\n", _("Read all messages")
632                                         );
633                                         break;
634                         }
635                 }
636
637                 if (navbar_style == navbar_default) {
638                         switch(WC->wc_view) {
639                                 case VIEW_ADDRESSBOOK:
640                                         wprintf(
641                                                 "<li class=\"addnewcontact\">"
642                                                 "<a href=\"display_enter\">"
643                                                 "<img src=\"static/addnewcontact_24x.gif\" "
644                                                 "alt=\"\"><span class=\"navbar_link\">"
645                                                 "%s"
646                                                 "</span></a></li>\n", _("Add new contact")
647                                         );
648                                         break;
649                                 case VIEW_CALENDAR:
650                                 case VIEW_CALBRIEF:
651                                         wprintf("<li class=\"addevent\"><a href=\"display_enter");
652                                         if (havebstr("year" )) wprintf("?year=%s", bstr("year"));
653                                         if (havebstr("month")) wprintf("?month=%s", bstr("month"));
654                                         if (havebstr("day"  )) wprintf("?day=%s", bstr("day"));
655                                         wprintf("\">"
656                                                 "<img  src=\"static/addevent_24x.gif\" "
657                                                 "alt=\"\"><span class=\"navbar_link\">"
658                                                 "%s"
659                                                 "</span></a></li>\n", _("Add new event")
660                                         );
661                                         break;
662                                 case VIEW_TASKS:
663                                         wprintf(
664                                                 "<li class=\"newmess\">"
665                                                 "<a href=\"display_enter\">"
666                                                 "<img  src=\"static/newmess3_24x.gif\" "
667                                                 "alt=\"\"><span class=\"navbar_link\">"
668                                                 "%s"
669                                                 "</span></a></li>\n", _("Add new task")
670                                         );
671                                         break;
672                                 case VIEW_NOTES:
673                                         wprintf(
674                                                 "<li class=\"enternewnote\">"
675                                                 "<a href=\"add_new_note\">"
676                                                 "<img  src=\"static/enternewnote_24x.gif\" "
677                                                 "alt=\"\"><span class=\"navbar_link\">"
678                                                 "%s"
679                                                 "</span></a></li>\n", _("Add new note")
680                                         );
681                                         break;
682                                 case VIEW_WIKI:
683                                         safestrncpy(buf, bstr("page"), sizeof buf);
684                                         str_wiki_index(buf);
685                                         wprintf(
686                                                 "<li class=\"newmess\">"
687                                                 "<a href=\"display_enter?wikipage=%s\">"
688                                                 "<img  src=\"static/newmess3_24x.gif\" "
689                                                 "alt=\"\"><span class=\"navbar_link\">"
690                                                 "%s"
691                                                 "</span></a></li>\n", buf, _("Edit this page")
692                                         );
693                                         break;
694                                 case VIEW_MAILBOX:
695                                         wprintf(
696                                                 "<li class=\"newmess\">"
697                                                 "<a href=\"display_enter\">"
698                                                 "<img  src=\"static/newmess3_24x.gif\" "
699                                                 "alt=\"\"><span class=\"navbar_link\">"
700                                                 "%s"
701                                                 "</span></a></li>\n", _("Write mail")
702                                         );
703                                         break;
704                                 default:
705                                         wprintf(
706                                                 "<li class=\"newmess\">"
707                                                 "<a href=\"display_enter\">"
708                                                 "<img  src=\"static/newmess3_24x.gif\" "
709                                                 "alt=\"\"><span class=\"navbar_link\">"
710                                                 "%s"
711                                                 "</span></a></li>\n", _("Enter a message")
712                                         );
713                                         break;
714                         }
715                 }
716
717                 if (navbar_style == navbar_default) wprintf(
718                         "<li class=\"skipthisroom\">"
719                         "<a href=\"skip\" "
720                         "title=\"%s\">"
721                         "<img  src=\"static/skipthisroom_24x.gif\" alt=\"\">"
722                         "<span class=\"navbar_link\">%s</span></a>"
723                         "</li>\n",
724                         _("Leave all messages marked as unread, go to next room with unread messages"),
725                         _("Skip this room")
726                 );
727
728                 if (navbar_style == navbar_default) wprintf(
729                         "<li class=\"markngo\">"
730                         "<a href=\"gotonext\" "
731                         "title=\"%s\">"
732                         "<img  src=\"static/markngo_24x.gif\" alt=\"\">"
733                         "<span class=\"navbar_link\">%s</span></a>"
734                         "</li>\n",
735                         _("Mark all messages as read, go to next room with unread messages"),
736                         _("Goto next room")
737                 );
738
739                 wprintf("</ul></div>\n");
740         }
741
742 }
743
744
745 /*
746  * back end routine to take the session to a new room
747  */
748 int gotoroom(char *gname)
749 {
750         char buf[SIZ];
751         static long ls = (-1L);
752         int err = 0;
753
754         /* store ungoto information */
755         strcpy(WC->ugname, WC->wc_roomname);
756         WC->uglsn = ls;
757
758         /** move to the new room */
759         serv_printf("GOTO %s", gname);
760         serv_getln(buf, sizeof buf);
761         if (buf[0] != '2') {
762                 buf[3] = 0;
763                 err = atoi(buf);
764                 serv_puts("GOTO _BASEROOM_");
765                 serv_getln(buf, sizeof buf);
766         }
767         if (buf[0] != '2') {
768                 buf[3] = 0;
769                 err = atoi(buf);
770                 return err;
771         }
772         extract_token(WC->wc_roomname, &buf[4], 0, '|', sizeof WC->wc_roomname);
773         WC->room_flags = extract_int(&buf[4], 4);
774         /* highest_msg_read = extract_int(&buf[4],6);
775            maxmsgnum = extract_int(&buf[4],5);
776          */
777         WC->is_mailbox = extract_int(&buf[4],7);
778         ls = extract_long(&buf[4], 6);
779         WC->wc_floor = extract_int(&buf[4], 10);
780         WC->wc_view = extract_int(&buf[4], 11);
781         WC->wc_default_view = extract_int(&buf[4], 12);
782         WC->wc_is_trash = extract_int(&buf[4], 13);
783         WC->room_flags2 = extract_int(&buf[4], 14);
784
785         if (WC->is_aide)
786                 WC->is_room_aide = WC->is_aide;
787         else
788                 WC->is_room_aide = (char) extract_int(&buf[4], 8);
789
790         remove_march(WC->wc_roomname);
791         if (!strcasecmp(gname, "_BASEROOM_"))
792                 remove_march(gname);
793
794         return err;
795 }
796
797
798 /**
799  * \brief Locate the room on the march list which we most want to go to.  
800  * Each room
801  * is measured given a "weight" of preference based on various factors.
802  * \param desired_floor the room number on the citadel server
803  * \return the roomname
804  */
805 char *pop_march(int desired_floor)
806 {
807         static char TheRoom[128];
808         int TheFloor = 0;
809         int TheOrder = 32767;
810         int TheWeight = 0;
811         int weight;
812         struct march *mptr = NULL;
813
814         strcpy(TheRoom, "_BASEROOM_");
815         if (WC->march == NULL)
816                 return (TheRoom);
817
818         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
819                 weight = 0;
820                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
821                         weight = weight + 10000;
822                 if (mptr->march_floor == desired_floor)
823                         weight = weight + 5000;
824
825                 weight = weight + ((128 - (mptr->march_floor)) * 128);
826                 weight = weight + (128 - (mptr->march_order));
827
828                 if (weight > TheWeight) {
829                         TheWeight = weight;
830                         strcpy(TheRoom, mptr->march_name);
831                         TheFloor = mptr->march_floor;
832                         TheOrder = mptr->march_order;
833                 }
834         }
835         return (TheRoom);
836 }
837
838
839
840 /*
841  * Goto next room having unread messages.
842  *
843  * We want to skip over rooms that the user has already been to, and take the
844  * user back to the lobby when done.  The room we end up in is placed in
845  * newroom - which is set to 0 (the lobby) initially.
846  * We start the search in the current room rather than the beginning to prevent
847  * two or more concurrent users from dragging each other back to the same room.
848  */
849 void gotonext(void)
850 {
851         char buf[256];
852         struct march *mptr = NULL;
853         struct march *mptr2 = NULL;
854         char room_name[128];
855         char next_room[128];
856         int ELoop = 0;
857
858         /*
859          * First check to see if the march-mode list is already allocated.
860          * If it is, pop the first room off the list and go there.
861          */
862
863         if (WC->march == NULL) {
864                 serv_puts("LKRN");
865                 serv_getln(buf, sizeof buf);
866                 if (buf[0] == '1')
867                         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
868                                 if (IsEmptyStr(buf)) {
869                                         if (ELoop > 10000)
870                                                 return;
871                                         if (ELoop % 100 == 0)
872                                                 sleeeeeeeeeep(1);
873                                         ELoop ++;
874                                         continue;                                       
875                                 }
876                                 extract_token(room_name, buf, 0, '|', sizeof room_name);
877                                 if (strcasecmp(room_name, WC->wc_roomname)) {
878                                         mptr = (struct march *) malloc(sizeof(struct march));
879                                         mptr->next = NULL;
880                                         safestrncpy(mptr->march_name, room_name, sizeof mptr->march_name);
881                                         mptr->march_floor = extract_int(buf, 2);
882                                         mptr->march_order = extract_int(buf, 3);
883                                         if (WC->march == NULL) 
884                                                 WC->march = mptr;
885                                         else 
886                                                 mptr2->next = mptr;
887                                         mptr2 = mptr;
888                                 }
889                                 buf[0] = '\0';
890                         }
891                 /*
892                  * add _BASEROOM_ to the end of the march list, so the user will end up
893                  * in the system base room (usually the Lobby>) at the end of the loop
894                  */
895                 mptr = (struct march *) malloc(sizeof(struct march));
896                 mptr->next = NULL;
897                 mptr->march_order = 0;
898                 mptr->march_floor = 0;
899                 strcpy(mptr->march_name, "_BASEROOM_");
900                 if (WC->march == NULL) {
901                         WC->march = mptr;
902                 } else {
903                         mptr2 = WC->march;
904                         while (mptr2->next != NULL)
905                                 mptr2 = mptr2->next;
906                         mptr2->next = mptr;
907                 }
908                 /*
909                  * ...and remove the room we're currently in, so a <G>oto doesn't make us
910                  * walk around in circles
911                  */
912                 remove_march(WC->wc_roomname);
913         }
914         if (WC->march != NULL) {
915                 strcpy(next_room, pop_march(-1));
916         } else {
917                 strcpy(next_room, "_BASEROOM_");
918         }
919
920
921         smart_goto(next_room);
922 }
923
924
925 /*
926  * goto next room
927  */
928 void smart_goto(char *next_room) {
929         gotoroom(next_room);
930         readloop(readnew);
931 }
932
933
934
935 /*
936  * mark all messages in current room as having been read
937  */
938 void slrp_highest(void)
939 {
940         char buf[256];
941
942         serv_puts("SLRP HIGHEST");
943         serv_getln(buf, sizeof buf);
944 }
945
946
947 /*
948  * un-goto the previous room
949  */
950 void ungoto(void)
951 {
952         char buf[SIZ];
953
954         if (!strcmp(WC->ugname, "")) {
955                 smart_goto(WC->wc_roomname);
956                 return;
957         }
958         serv_printf("GOTO %s", WC->ugname);
959         serv_getln(buf, sizeof buf);
960         if (buf[0] != '2') {
961                 smart_goto(WC->wc_roomname);
962                 return;
963         }
964         if (WC->uglsn >= 0L) {
965                 serv_printf("SLRP %ld", WC->uglsn);
966                 serv_getln(buf, sizeof buf);
967         }
968         strcpy(buf, WC->ugname);
969         strcpy(WC->ugname, "");
970         smart_goto(buf);
971 }
972
973 typedef struct __room_states {
974         char password[SIZ];
975         char dirname[SIZ];
976         char name[SIZ];
977         int flags;
978         int floor;
979         int order;
980         int view;
981         int flags2;
982 } room_states;
983
984
985
986
987 /*
988  * Set/clear/read the "self-service list subscribe" flag for a room
989  * 
990  * set newval to 0 to clear, 1 to set, any other value to leave unchanged.
991  * returns the new value.
992  */
993
994 int self_service(int newval) {
995         int current_value = 0;
996         char buf[SIZ];
997         
998         char name[SIZ];
999         char password[SIZ];
1000         char dirname[SIZ];
1001         int flags, floor, order, view, flags2;
1002
1003         serv_puts("GETR");
1004         serv_getln(buf, sizeof buf);
1005         if (buf[0] != '2') return(0);
1006
1007         extract_token(name, &buf[4], 0, '|', sizeof name);
1008         extract_token(password, &buf[4], 1, '|', sizeof password);
1009         extract_token(dirname, &buf[4], 2, '|', sizeof dirname);
1010         flags = extract_int(&buf[4], 3);
1011         floor = extract_int(&buf[4], 4);
1012         order = extract_int(&buf[4], 5);
1013         view = extract_int(&buf[4], 6);
1014         flags2 = extract_int(&buf[4], 7);
1015
1016         if (flags2 & QR2_SELFLIST) {
1017                 current_value = 1;
1018         }
1019         else {
1020                 current_value = 0;
1021         }
1022
1023         if (newval == 1) {
1024                 flags2 = flags2 | QR2_SELFLIST;
1025         }
1026         else if (newval == 0) {
1027                 flags2 = flags2 & ~QR2_SELFLIST;
1028         }
1029         else {
1030                 return(current_value);
1031         }
1032
1033         if (newval != current_value) {
1034                 serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1035                         name, password, dirname, flags,
1036                         floor, order, view, flags2);
1037                 serv_getln(buf, sizeof buf);
1038         }
1039
1040         return(newval);
1041
1042 }
1043
1044 int is_selflist(room_states *RoomFlags)
1045 {
1046         return ((RoomFlags->flags2 & QR2_SELFLIST) != 0);
1047 }
1048
1049 int is_publiclist(room_states *RoomFlags)
1050 {
1051         return ((RoomFlags->flags2 & QR2_SMTP_PUBLIC) != 0);
1052 }
1053
1054 int is_moderatedlist(room_states *RoomFlags)
1055 {
1056         return ((RoomFlags->flags2 & QR2_MODERATED) != 0);
1057 }
1058
1059 /*
1060  * Set/clear/read the "self-service list subscribe" flag for a room
1061  * 
1062  * set newval to 0 to clear, 1 to set, any other value to leave unchanged.
1063  * returns the new value.
1064  */
1065
1066 int get_roomflags(room_states *RoomOps) 
1067 {
1068         char buf[SIZ];
1069         
1070         serv_puts("GETR");
1071         serv_getln(buf, sizeof buf);
1072         if (buf[0] != '2') return(0);
1073
1074         extract_token(RoomOps->name, &buf[4], 0, '|', sizeof RoomOps->name);
1075         extract_token(RoomOps->password, &buf[4], 1, '|', sizeof RoomOps->password);
1076         extract_token(RoomOps->dirname, &buf[4], 2, '|', sizeof RoomOps->dirname);
1077         RoomOps->flags = extract_int(&buf[4], 3);
1078         RoomOps->floor = extract_int(&buf[4], 4);
1079         RoomOps->order = extract_int(&buf[4], 5);
1080         RoomOps->view = extract_int(&buf[4], 6);
1081         RoomOps->flags2 = extract_int(&buf[4], 7);
1082         return (1);
1083 }
1084
1085 int set_roomflags(room_states *RoomOps)
1086 {
1087         char buf[SIZ];
1088
1089         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1090                     RoomOps->name, 
1091                     RoomOps->password, 
1092                     RoomOps->dirname, 
1093                     RoomOps->flags,
1094                     RoomOps->floor, 
1095                     RoomOps->order, 
1096                     RoomOps->view, 
1097                     RoomOps->flags2);
1098         serv_getln(buf, sizeof buf);
1099         return (1);
1100 }
1101
1102
1103
1104
1105
1106
1107 /*
1108  * display the form for editing a room
1109  */
1110 void display_editroom(void)
1111 {
1112         char buf[SIZ];
1113         char cmd[1024];
1114         char node[256];
1115         char remote_room[128];
1116         char recp[1024];
1117         char er_name[128];
1118         char er_password[10];
1119         char er_dirname[15];
1120         char er_roomaide[26];
1121         unsigned er_flags;
1122         unsigned er_flags2;
1123         int er_floor;
1124         int i, j;
1125         char *tab;
1126         char *shared_with;
1127         char *not_shared_with;
1128         int roompolicy = 0;
1129         int roomvalue = 0;
1130         int floorpolicy = 0;
1131         int floorvalue = 0;
1132         char pop3_host[128];
1133         char pop3_user[32];
1134         int bg = 0;
1135
1136         tab = bstr("tab");
1137         if (IsEmptyStr(tab)) tab = "admin";
1138
1139         load_floorlist();
1140         output_headers(1, 1, 1, 0, 0, 0);
1141
1142         wprintf("<div class=\"fix_scrollbar_bug\">");
1143
1144         wprintf("<br />\n");
1145
1146         /* print the tabbed dialog */
1147         wprintf("<div align=\"center\">");
1148         wprintf("<table id=\"AdminTabs\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\""
1149                 "<tr align=\"center\" style=\"cursor:pointer\"><td>&nbsp;</td>"
1150                 );
1151
1152         wprintf("<td class=\"");
1153         if (!strcmp(tab, "admin")) {
1154                 wprintf(" tab_cell_label\">");
1155                 wprintf(_("Administration"));
1156         }
1157         else {
1158                 wprintf("< tab_cell_edit\"><a href=\"display_editroom&tab=admin\">");
1159                 wprintf(_("Administration"));
1160                 wprintf("</a>");
1161         }
1162         wprintf("</td>\n");
1163         wprintf("<td>&nbsp;</td>\n");
1164
1165         if ( (WC->axlevel >= 6) || (WC->is_room_aide) ) {
1166
1167                 wprintf("<td class=\"");
1168                 if (!strcmp(tab, "config")) {
1169                         wprintf(" tab_cell_label\">");
1170                         wprintf(_("Configuration"));
1171                 }
1172                 else {
1173                         wprintf(" tab_cell_edit\"><a href=\"display_editroom&tab=config\">");
1174                         wprintf(_("Configuration"));
1175                         wprintf("</a>");
1176                 }
1177                 wprintf("</td>\n");
1178                 wprintf("<td>&nbsp;</td>\n");
1179
1180                 wprintf("<td class=\"");
1181                 if (!strcmp(tab, "expire")) {
1182                         wprintf(" tab_cell_label\">");
1183                         wprintf(_("Message expire policy"));
1184                 }
1185                 else {
1186                         wprintf(" tab_cell_edit\"><a href=\"display_editroom&tab=expire\">");
1187                         wprintf(_("Message expire policy"));
1188                         wprintf("</a>");
1189                 }
1190                 wprintf("</td>\n");
1191                 wprintf("<td>&nbsp;</td>\n");
1192         
1193                 wprintf("<td class=\"");
1194                 if (!strcmp(tab, "access")) {
1195                         wprintf(" tab_cell_label\">");
1196                         wprintf(_("Access controls"));
1197                 }
1198                 else {
1199                         wprintf(" tab_cell_edit\"><a href=\"display_editroom&tab=access\">");
1200                         wprintf(_("Access controls"));
1201                         wprintf("</a>");
1202                 }
1203                 wprintf("</td>\n");
1204                 wprintf("<td>&nbsp;</td>\n");
1205
1206                 wprintf("<td class=\"");
1207                 if (!strcmp(tab, "sharing")) {
1208                         wprintf(" tab_cell_label\">");
1209                         wprintf(_("Sharing"));
1210                 }
1211                 else {
1212                         wprintf(" tab_cell_edit\"><a href=\"display_editroom&tab=sharing\">");
1213                         wprintf(_("Sharing"));
1214                         wprintf("</a>");
1215                 }
1216                 wprintf("</td>\n");
1217                 wprintf("<td>&nbsp;</td>\n");
1218
1219                 wprintf("<td class=\"");
1220                 if (!strcmp(tab, "listserv")) {
1221                         wprintf(" tab_cell_label\">");
1222                         wprintf(_("Mailing list service"));
1223                 }
1224                 else {
1225                         wprintf("< tab_cell_edit\"><a href=\"display_editroom&tab=listserv\">");
1226                         wprintf(_("Mailing list service"));
1227                         wprintf("</a>");
1228                 }
1229                 wprintf("</td>\n");
1230                 wprintf("<td>&nbsp;</td>\n");
1231
1232         }
1233
1234         wprintf("<td class=\"");
1235         if (!strcmp(tab, "feeds")) {
1236                 wprintf(" tab_cell_label\">");
1237                 wprintf(_("Remote retrieval"));
1238         }
1239         else {
1240                 wprintf("< tab_cell_edit\"><a href=\"display_editroom&tab=feeds\">");
1241                 wprintf(_("Remote retrieval"));
1242                 wprintf("</a>");
1243         }
1244         wprintf("</td>\n");
1245         wprintf("<td>&nbsp;</td>\n");
1246
1247         wprintf("</tr></table>\n");
1248         wprintf("</div>\n");
1249         /* end tabbed dialog */ 
1250
1251         wprintf("<script type=\"text/javascript\">"
1252                 " Nifty(\"table#AdminTabs td\", \"small transparent top\");"
1253                 "</script>"
1254         );
1255
1256         /* begin content of whatever tab is open now */
1257
1258         if (!strcmp(tab, "admin")) {
1259                 wprintf("<div class=\"tabcontent\">");
1260                 wprintf("<ul>"
1261                         "<li><a href=\"delete_room\" "
1262                         "onClick=\"return confirm('");
1263                 wprintf(_("Are you sure you want to delete this room?"));
1264                 wprintf("');\">\n");
1265                 wprintf(_("Delete this room"));
1266                 wprintf("</a>\n"
1267                         "<li><a href=\"display_editroompic\">\n");
1268                 wprintf(_("Set or change the icon for this room's banner"));
1269                 wprintf("</a>\n"
1270                         "<li><a href=\"display_editinfo\">\n");
1271                 wprintf(_("Edit this room's Info file"));
1272                 wprintf("</a>\n"
1273                         "</ul>");
1274                 wprintf("</div>");
1275         }
1276
1277         if (!strcmp(tab, "config")) {
1278                 wprintf("<div class=\"tabcontent\">");
1279                 serv_puts("GETR");
1280                 serv_getln(buf, sizeof buf);
1281
1282                 if (!strncmp(buf, "550", 3)) {
1283                         wprintf("<br><br><div align=center>%s</div><br><br>\n",
1284                                 _("Higher access is required to access this function.")
1285                         );
1286                 }
1287                 else if (buf[0] != '2') {
1288                         wprintf("<br><br><div align=center>%s</div><br><br>\n", &buf[4]);
1289                 }
1290                 else {
1291                         extract_token(er_name, &buf[4], 0, '|', sizeof er_name);
1292                         extract_token(er_password, &buf[4], 1, '|', sizeof er_password);
1293                         extract_token(er_dirname, &buf[4], 2, '|', sizeof er_dirname);
1294                         er_flags = extract_int(&buf[4], 3);
1295                         er_floor = extract_int(&buf[4], 4);
1296                         er_flags2 = extract_int(&buf[4], 7);
1297         
1298                         wprintf("<form method=\"POST\" action=\"editroom\">\n");
1299                         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1300                 
1301                         wprintf("<ul><li>");
1302                         wprintf(_("Name of room: "));
1303                         wprintf("<input type=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\"%d\">\n",
1304                                 er_name,
1305                                 (sizeof(er_name)-1)
1306                         );
1307                 
1308                         wprintf("<li>");
1309                         wprintf(_("Resides on floor: "));
1310                         wprintf("<select NAME=\"er_floor\" SIZE=\"1\"");
1311                         if (er_flags & QR_MAILBOX)
1312                                 wprintf("disabled >\n");
1313                         for (i = 0; i < 128; ++i)
1314                                 if (!IsEmptyStr(floorlist[i])) {
1315                                         wprintf("<OPTION ");
1316                                         if (i == er_floor )
1317                                                 wprintf("SELECTED ");
1318                                         wprintf("VALUE=\"%d\">", i);
1319                                         escputs(floorlist[i]);
1320                                         wprintf("</OPTION>\n");
1321                                 }
1322                         wprintf("</select>\n");
1323
1324                         wprintf("<li>");
1325                         wprintf(_("Type of room:"));
1326                         wprintf("<ul>\n");
1327         
1328                         wprintf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"public\" ");
1329                         if ((er_flags & (QR_PRIVATE + QR_MAILBOX)) == 0)
1330                                 wprintf("CHECKED ");
1331                         wprintf("OnChange=\""
1332                                 "       if (this.form.type[0].checked == true) {        "
1333                                 "               this.form.er_floor.disabled = false;    "
1334                                 "       }                                               "
1335                                 "\"> ");
1336                         wprintf(_("Public (automatically appears to everyone)"));
1337                         wprintf("\n");
1338         
1339                         wprintf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"hidden\" ");
1340                         if ((er_flags & QR_PRIVATE) &&
1341                         (er_flags & QR_GUESSNAME))
1342                                 wprintf("CHECKED ");
1343                         wprintf(" OnChange=\""
1344                                 "       if (this.form.type[1].checked == true) {        "
1345                                 "               this.form.er_floor.disabled = false;    "
1346                                 "       }                                               "
1347                                 "\"> ");
1348                         wprintf(_("Private - hidden (accessible to anyone who knows its name)"));
1349                 
1350                         wprintf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
1351                         if ((er_flags & QR_PRIVATE) &&
1352                         (er_flags & QR_PASSWORDED))
1353                                 wprintf("CHECKED ");
1354                         wprintf(" OnChange=\""
1355                                 "       if (this.form.type[2].checked == true) {        "
1356                                 "               this.form.er_floor.disabled = false;    "
1357                                 "       }                                               "
1358                                 "\"> ");
1359                         wprintf(_("Private - require password: "));
1360                         wprintf("\n<input type=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n",
1361                                 er_password);
1362                 
1363                         wprintf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
1364                         if ((er_flags & QR_PRIVATE)
1365                         && ((er_flags & QR_GUESSNAME) == 0)
1366                         && ((er_flags & QR_PASSWORDED) == 0))
1367                                 wprintf("CHECKED ");
1368                         wprintf(" OnChange=\""
1369                                 "       if (this.form.type[3].checked == true) {        "
1370                                 "               this.form.er_floor.disabled = false;    "
1371                                 "       }                                               "
1372                                 "\"> ");
1373                         wprintf(_("Private - invitation only"));
1374                 
1375                         wprintf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"personal\" ");
1376                         if (er_flags & QR_MAILBOX)
1377                                 wprintf("CHECKED ");
1378                         wprintf (" OnChange=\""
1379                                 "       if (this.form.type[4].checked == true) {        "
1380                                 "               this.form.er_floor.disabled = true;     "
1381                                 "       }                                               "
1382                                 "\"> ");
1383                         wprintf(_("Personal (mailbox for you only)"));
1384                         
1385                         wprintf("\n<li><input type=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
1386                         wprintf("> ");
1387                         wprintf(_("If private, cause current users to forget room"));
1388                 
1389                         wprintf("\n</ul>\n");
1390                 
1391                         wprintf("<li><input type=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
1392                         if (er_flags & QR_PREFONLY)
1393                                 wprintf("CHECKED ");
1394                         wprintf("> ");
1395                         wprintf(_("Preferred users only"));
1396                 
1397                         wprintf("\n<li><input type=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
1398                         if (er_flags & QR_READONLY)
1399                                 wprintf("CHECKED ");
1400                         wprintf("> ");
1401                         wprintf(_("Read-only room"));
1402                 
1403                         wprintf("\n<li><input type=\"checkbox\" NAME=\"collabdel\" VALUE=\"yes\" ");
1404                         if (er_flags2 & QR2_COLLABDEL)
1405                                 wprintf("CHECKED ");
1406                         wprintf("> ");
1407                         wprintf(_("All users allowed to post may also delete messages"));
1408                 
1409                         /** directory stuff */
1410                         wprintf("\n<li><input type=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
1411                         if (er_flags & QR_DIRECTORY)
1412                                 wprintf("CHECKED ");
1413                         wprintf("> ");
1414                         wprintf(_("File directory room"));
1415         
1416                         wprintf("\n<ul><li>");
1417                         wprintf(_("Directory name: "));
1418                         wprintf("<input type=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n",
1419                                 er_dirname);
1420         
1421                         wprintf("<li><input type=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
1422                         if (er_flags & QR_UPLOAD)
1423                         wprintf("CHECKED ");
1424                         wprintf("> ");
1425                         wprintf(_("Uploading allowed"));
1426                 
1427                         wprintf("\n<li><input type=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
1428                         if (er_flags & QR_DOWNLOAD)
1429                                 wprintf("CHECKED ");
1430                         wprintf("> ");
1431                         wprintf(_("Downloading allowed"));
1432                 
1433                         wprintf("\n<li><input type=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
1434                         if (er_flags & QR_VISDIR)
1435                                 wprintf("CHECKED ");
1436                         wprintf("> ");
1437                         wprintf(_("Visible directory"));
1438                         wprintf("</ul>\n");
1439                 
1440                         /** end of directory stuff */
1441         
1442                         wprintf("<li><input type=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
1443                         if (er_flags & QR_NETWORK)
1444                                 wprintf("CHECKED ");
1445                         wprintf("> ");
1446                         wprintf(_("Network shared room"));
1447         
1448                         wprintf("\n<li><input type=\"checkbox\" NAME=\"permanent\" VALUE=\"yes\" ");
1449                         if (er_flags & QR_PERMANENT)
1450                                 wprintf("CHECKED ");
1451                         wprintf("> ");
1452                         wprintf(_("Permanent (does not auto-purge)"));
1453         
1454                         wprintf("\n<li><input type=\"checkbox\" NAME=\"subjectreq\" VALUE=\"yes\" ");
1455                         if (er_flags2 & QR2_SUBJECTREQ)
1456                                 wprintf("CHECKED ");
1457                         wprintf("> ");
1458                         wprintf(_("Subject Required (Force users to specify a message subject)"));
1459         
1460                         /** start of anon options */
1461                 
1462                         wprintf("\n<li>");
1463                         wprintf(_("Anonymous messages"));
1464                         wprintf("<ul>\n");
1465                 
1466                         wprintf("<li><input type=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
1467                         if (((er_flags & QR_ANONONLY) == 0)
1468                         && ((er_flags & QR_ANONOPT) == 0))
1469                                 wprintf("CHECKED ");
1470                         wprintf("> ");
1471                         wprintf(_("No anonymous messages"));
1472         
1473                         wprintf("\n<li><input type=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
1474                         if (er_flags & QR_ANONONLY)
1475                                 wprintf("CHECKED ");
1476                         wprintf("> ");
1477                         wprintf(_("All messages are anonymous"));
1478                 
1479                         wprintf("\n<li><input type=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
1480                         if (er_flags & QR_ANONOPT)
1481                                 wprintf("CHECKED ");
1482                         wprintf("> ");
1483                         wprintf(_("Prompt user when entering messages"));
1484                         wprintf("</ul>\n");
1485                 
1486                 /* end of anon options */
1487                 
1488                         wprintf("<li>");
1489                         wprintf(_("Room aide: "));
1490                         serv_puts("GETA");
1491                         serv_getln(buf, sizeof buf);
1492                         if (buf[0] != '2') {
1493                                 wprintf("<em>%s</em>\n", &buf[4]);
1494                         } else {
1495                                 extract_token(er_roomaide, &buf[4], 0, '|', sizeof er_roomaide);
1496                                 wprintf("<input type=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
1497                         }
1498                 
1499                         wprintf("</ul><CENTER>\n");
1500                         wprintf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"config\">\n"
1501                                 "<input type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">"
1502                                 "&nbsp;"
1503                                 "<input type=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">"
1504                                 "</CENTER>\n",
1505                                 _("Save changes"),
1506                                 _("Cancel")
1507                         );
1508                 }
1509                 wprintf("</div>");
1510         }
1511
1512
1513         /* Sharing the room with other Citadel nodes... */
1514         if (!strcmp(tab, "sharing")) {
1515                 wprintf("<div class=\"tabcontent\">");
1516
1517                 shared_with = strdup("");
1518                 not_shared_with = strdup("");
1519
1520                 /** Learn the current configuration */
1521                 serv_puts("CONF getsys|application/x-citadel-ignet-config");
1522                 serv_getln(buf, sizeof buf);
1523                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1524                         extract_token(node, buf, 0, '|', sizeof node);
1525                         not_shared_with = realloc(not_shared_with,
1526                                         strlen(not_shared_with) + 32);
1527                         strcat(not_shared_with, node);
1528                         strcat(not_shared_with, "\n");
1529                 }
1530
1531                 serv_puts("GNET");
1532                 serv_getln(buf, sizeof buf);
1533                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1534                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1535                         extract_token(node, buf, 1, '|', sizeof node);
1536                         extract_token(remote_room, buf, 2, '|', sizeof remote_room);
1537                         if (!strcasecmp(cmd, "ignet_push_share")) {
1538                                 shared_with = realloc(shared_with,
1539                                                 strlen(shared_with) + 32);
1540                                 strcat(shared_with, node);
1541                                 if (!IsEmptyStr(remote_room)) {
1542                                         strcat(shared_with, "|");
1543                                         strcat(shared_with, remote_room);
1544                                 }
1545                                 strcat(shared_with, "\n");
1546                         }
1547                 }
1548
1549                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1550                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1551                         extract_token(node, buf, 0, '|', sizeof node);
1552                         for (j=0; j<num_tokens(not_shared_with, '\n'); ++j) {
1553                                 extract_token(cmd, not_shared_with, j, '\n', sizeof cmd);
1554                                 if (!strcasecmp(node, cmd)) {
1555                                         remove_token(not_shared_with, j, '\n');
1556                                 }
1557                         }
1558                 }
1559
1560                 /* Display the stuff */
1561                 wprintf("<CENTER><br />"
1562                         "<table border=1 cellpadding=5><tr>"
1563                         "<td><B><I>");
1564                 wprintf(_("Shared with"));
1565                 wprintf("</I></B></td>"
1566                         "<td><B><I>");
1567                 wprintf(_("Not shared with"));
1568                 wprintf("</I></B></td></tr>\n"
1569                         "<tr><td VALIGN=TOP>\n");
1570
1571                 wprintf("<table border=0 cellpadding=5><tr class=\"tab_cell\"><td>");
1572                 wprintf(_("Remote node name"));
1573                 wprintf("</td><td>");
1574                 wprintf(_("Remote room name"));
1575                 wprintf("</td><td>");
1576                 wprintf(_("Actions"));
1577                 wprintf("</td></tr>\n");
1578
1579                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1580                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1581                         extract_token(node, buf, 0, '|', sizeof node);
1582                         extract_token(remote_room, buf, 1, '|', sizeof remote_room);
1583                         if (!IsEmptyStr(node)) {
1584                                 wprintf("<form method=\"POST\" action=\"netedit\">");
1585                                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1586                                 wprintf("<tr><td>%s</td>\n", node);
1587
1588                                 wprintf("<td>");
1589                                 if (!IsEmptyStr(remote_room)) {
1590                                         escputs(remote_room);
1591                                 }
1592                                 wprintf("</td>");
1593
1594                                 wprintf("<td>");
1595                 
1596                                 wprintf("<input type=\"hidden\" NAME=\"line\" "
1597                                         "VALUE=\"ignet_push_share|");
1598                                 urlescputs(node);
1599                                 if (!IsEmptyStr(remote_room)) {
1600                                         wprintf("|");
1601                                         urlescputs(remote_room);
1602                                 }
1603                                 wprintf("\">");
1604                                 wprintf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"sharing\">\n");
1605                                 wprintf("<input type=\"hidden\" NAME=\"cmd\" VALUE=\"remove\">\n");
1606                                 wprintf("<input type=\"submit\" "
1607                                         "NAME=\"unshare_button\" VALUE=\"%s\">", _("Unshare"));
1608                                 wprintf("</td></tr></form>\n");
1609                         }
1610                 }
1611
1612                 wprintf("</table>\n");
1613                 wprintf("</td><td VALIGN=TOP>\n");
1614                 wprintf("<table border=0 cellpadding=5><tr class=\"tab_cell\"><td>");
1615                 wprintf(_("Remote node name"));
1616                 wprintf("</td><td>");
1617                 wprintf(_("Remote room name"));
1618                 wprintf("</td><td>");
1619                 wprintf(_("Actions"));
1620                 wprintf("</td></tr>\n");
1621
1622                 for (i=0; i<num_tokens(not_shared_with, '\n'); ++i) {
1623                         extract_token(node, not_shared_with, i, '\n', sizeof node);
1624                         if (!IsEmptyStr(node)) {
1625                                 wprintf("<form method=\"POST\" action=\"netedit\">");
1626                                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1627                                 wprintf("<tr><td>");
1628                                 escputs(node);
1629                                 wprintf("</td><td>"
1630                                         "<input type=\"INPUT\" "
1631                                         "NAME=\"suffix\" "
1632                                         "MAXLENGTH=128>"
1633                                         "</td><td>");
1634                                 wprintf("<input type=\"hidden\" "
1635                                         "NAME=\"line\" "
1636                                         "VALUE=\"ignet_push_share|");
1637                                 urlescputs(node);
1638                                 wprintf("|\">");
1639                                 wprintf("<input type=\"hidden\" NAME=\"tab\" "
1640                                         "VALUE=\"sharing\">\n");
1641                                 wprintf("<input type=\"hidden\" NAME=\"cmd\" "
1642                                         "VALUE=\"add\">\n");
1643                                 wprintf("<input type=\"submit\" "
1644                                         "NAME=\"add_button\" VALUE=\"%s\">", _("Share"));
1645                                 wprintf("</td></tr></form>\n");
1646                         }
1647                 }
1648
1649                 wprintf("</table>\n");
1650                 wprintf("</td></tr>"
1651                         "</table></CENTER><br />\n"
1652                         "<I><B>%s</B><ul><li>", _("Notes:"));
1653                 wprintf(_("When sharing a room, "
1654                         "it must be shared from both ends.  Adding a node to "
1655                         "the 'shared' list sends messages out, but in order to"
1656                         " receive messages, the other nodes must be configured"
1657                         " to send messages out to your system as well. "
1658                         "<li>If the remote room name is blank, it is assumed "
1659                         "that the room name is identical on the remote node."
1660                         "<li>If the remote room name is different, the remote "
1661                         "node must also configure the name of the room here."
1662                         "</ul></I><br />\n"
1663                 ));
1664
1665                 wprintf("</div>");
1666         }
1667
1668         /* Mailing list management */
1669         if (!strcmp(tab, "listserv")) {
1670                 room_states RoomFlags;
1671                 wprintf("<div class=\"tabcontent\">");
1672
1673                 wprintf("<br /><center>"
1674                         "<table BORDER=0 WIDTH=100%% CELLPADDING=5>"
1675                         "<tr><td VALIGN=TOP>");
1676
1677                 wprintf(_("<i>The contents of this room are being "
1678                         "mailed <b>as individual messages</b> "
1679                         "to the following list recipients:"
1680                         "</i><br /><br />\n"));
1681
1682                 serv_puts("GNET");
1683                 serv_getln(buf, sizeof buf);
1684                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1685                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1686                         if (!strcasecmp(cmd, "listrecp")) {
1687                                 extract_token(recp, buf, 1, '|', sizeof recp);
1688                         
1689                                 escputs(recp);
1690                                 wprintf(" <a href=\"netedit&cmd=remove&tab=listserv&line=listrecp|");
1691                                 urlescputs(recp);
1692                                 wprintf("\">");
1693                                 wprintf(_("(remove)"));
1694                                 wprintf("</A><br />");
1695                         }
1696                 }
1697                 wprintf("<br /><form method=\"POST\" action=\"netedit\">\n"
1698                         "<input type=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1699                         "<input type=\"hidden\" NAME=\"prefix\" VALUE=\"listrecp|\">\n");
1700                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1701                 wprintf("<input type=\"text\" id=\"add_as_listrecp\" NAME=\"line\">\n");
1702                 wprintf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1703                 wprintf("</form>\n");
1704
1705                 wprintf("</td><td VALIGN=TOP>\n");
1706                 
1707                 wprintf(_("<i>The contents of this room are being "
1708                         "mailed <b>in digest form</b> "
1709                         "to the following list recipients:"
1710                         "</i><br /><br />\n"));
1711
1712                 serv_puts("GNET");
1713                 serv_getln(buf, sizeof buf);
1714                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1715                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1716                         if (!strcasecmp(cmd, "digestrecp")) {
1717                                 extract_token(recp, buf, 1, '|', sizeof recp);
1718                         
1719                                 escputs(recp);
1720                                 wprintf(" <a href=\"netedit&cmd=remove&tab=listserv&line="
1721                                         "digestrecp|");
1722                                 urlescputs(recp);
1723                                 wprintf("\">");
1724                                 wprintf(_("(remove)"));
1725                                 wprintf("</A><br />");
1726                         }
1727                 }
1728                 wprintf("<br /><form method=\"POST\" action=\"netedit\">\n"
1729                         "<input type=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1730                         "<input type=\"hidden\" NAME=\"prefix\" VALUE=\"digestrecp|\">\n");
1731                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1732                 wprintf("<input type=\"text\" id=\"add_as_digestrecp\" NAME=\"line\">\n");
1733                 wprintf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1734                 wprintf("</form>\n");
1735                 
1736                 wprintf("</td></tr></table>\n");
1737
1738                 /** Pop open an address book -- begin **/
1739                 wprintf("<div align=right>"
1740                         "<a href=\"javascript:PopOpenAddressBook('add_as_listrecp|%s|add_as_digestrecp|%s');\" "
1741                         "title=\"%s\">"
1742                         "<img align=middle border=0 width=24 height=24 src=\"static/viewcontacts_24x.gif\">"
1743                         "&nbsp;%s</a>"
1744                         "</div>",
1745                         _("List"),
1746                         _("Digest"),
1747                         _("Add recipients from Contacts or other address books"),
1748                         _("Add recipients from Contacts or other address books")
1749                 );
1750                 /* Pop open an address book -- end **/
1751
1752                 wprintf("<br />\n<form method=\"GET\" action=\"toggle_self_service\">\n");
1753
1754                 get_roomflags (&RoomFlags);
1755                 
1756                 /* Self Service subscription? */
1757                 wprintf("<table><tr><td>\n");
1758                 wprintf(_("Allow self-service subscribe/unsubscribe requests."));
1759                 wprintf("</td><td><input type=\"checkbox\" name=\"QR2_SelfList\" value=\"yes\" %s></td></tr>\n"
1760                         " <tr><td colspan=\"2\">\n",
1761                         (is_selflist(&RoomFlags))?"checked":"");
1762                 wprintf(_("The URL for subscribe/unsubscribe is: "));
1763                 wprintf("<TT>%s://%s/listsub</TT></td></tr>\n",
1764                         (is_https ? "https" : "http"),
1765                         WC->http_host);
1766                 /* Public posting? */
1767                 wprintf("<tr><td>");
1768                 wprintf(_("Allow non-subscribers to mail to this room."));
1769                 wprintf("</td><td><input type=\"checkbox\" name=\"QR2_SubsOnly\" value=\"yes\" %s></td></tr>\n",
1770                         (is_publiclist(&RoomFlags))?"checked":"");
1771                 
1772                 /* Moderated List? */
1773                 wprintf("<tr><td>");
1774                 wprintf(_("Room post publication needs Aide permission."));
1775                 wprintf("</td><td><input type=\"checkbox\" name=\"QR2_Moderated\" value=\"yes\" %s></td></tr>\n",
1776                         (is_moderatedlist(&RoomFlags))?"checked":"");
1777
1778
1779                 wprintf("<tr><td colspan=\"2\" align=\"center\">"
1780                         "<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\"></td></tr>", _("Save changes"));
1781                 wprintf("</table></form>");
1782                         
1783
1784                 wprintf("</CENTER>\n");
1785                 wprintf("</div>");
1786         }
1787
1788
1789         /* Configuration of The Dreaded Auto-Purger */
1790         if (!strcmp(tab, "expire")) {
1791                 wprintf("<div class=\"tabcontent\">");
1792
1793                 serv_puts("GPEX room");
1794                 serv_getln(buf, sizeof buf);
1795                 if (!strncmp(buf, "550", 3)) {
1796                         wprintf("<br><br><div align=center>%s</div><br><br>\n",
1797                                 _("Higher access is required to access this function.")
1798                         );
1799                 }
1800                 else if (buf[0] != '2') {
1801                         wprintf("<br><br><div align=center>%s</div><br><br>\n", &buf[4]);
1802                 }
1803                 else {
1804                         roompolicy = extract_int(&buf[4], 0);
1805                         roomvalue = extract_int(&buf[4], 1);
1806                 
1807                         serv_puts("GPEX floor");
1808                         serv_getln(buf, sizeof buf);
1809                         if (buf[0] == '2') {
1810                                 floorpolicy = extract_int(&buf[4], 0);
1811                                 floorvalue = extract_int(&buf[4], 1);
1812                         }
1813                         
1814                         wprintf("<br /><form method=\"POST\" action=\"set_room_policy\">\n");
1815                         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1816                         wprintf("<table border=0 cellspacing=5>\n");
1817                         wprintf("<tr><td>");
1818                         wprintf(_("Message expire policy for this room"));
1819                         wprintf("<br />(");
1820                         escputs(WC->wc_roomname);
1821                         wprintf(")</td><td>");
1822                         wprintf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"0\" %s>",
1823                                 ((roompolicy == 0) ? "CHECKED" : "") );
1824                         wprintf(_("Use the default policy for this floor"));
1825                         wprintf("<br />\n");
1826                         wprintf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"1\" %s>",
1827                                 ((roompolicy == 1) ? "CHECKED" : "") );
1828                         wprintf(_("Never automatically expire messages"));
1829                         wprintf("<br />\n");
1830                         wprintf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"2\" %s>",
1831                                 ((roompolicy == 2) ? "CHECKED" : "") );
1832                         wprintf(_("Expire by message count"));
1833                         wprintf("<br />\n");
1834                         wprintf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"3\" %s>",
1835                                 ((roompolicy == 3) ? "CHECKED" : "") );
1836                         wprintf(_("Expire by message age"));
1837                         wprintf("<br />");
1838                         wprintf(_("Number of messages or days: "));
1839                         wprintf("<input type=\"text\" NAME=\"roomvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">", roomvalue);
1840                         wprintf("</td></tr>\n");
1841         
1842                         if (WC->axlevel >= 6) {
1843                                 wprintf("<tr><td COLSPAN=2><hr /></td></tr>\n");
1844                                 wprintf("<tr><td>");
1845                                 wprintf(_("Message expire policy for this floor"));
1846                                 wprintf("<br />(");
1847                                 escputs(floorlist[WC->wc_floor]);
1848                                 wprintf(")</td><td>");
1849                                 wprintf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"0\" %s>",
1850                                         ((floorpolicy == 0) ? "CHECKED" : "") );
1851                                 wprintf(_("Use the system default"));
1852                                 wprintf("<br />\n");
1853                                 wprintf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"1\" %s>",
1854                                         ((floorpolicy == 1) ? "CHECKED" : "") );
1855                                 wprintf(_("Never automatically expire messages"));
1856                                 wprintf("<br />\n");
1857                                 wprintf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"2\" %s>",
1858                                         ((floorpolicy == 2) ? "CHECKED" : "") );
1859                                 wprintf(_("Expire by message count"));
1860                                 wprintf("<br />\n");
1861                                 wprintf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"3\" %s>",
1862                                         ((floorpolicy == 3) ? "CHECKED" : "") );
1863                                 wprintf(_("Expire by message age"));
1864                                 wprintf("<br />");
1865                                 wprintf(_("Number of messages or days: "));
1866                                 wprintf("<input type=\"text\" NAME=\"floorvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">",
1867                                         floorvalue);
1868                         }
1869         
1870                         wprintf("<CENTER>\n");
1871                         wprintf("<tr><td COLSPAN=2><hr /><CENTER>\n");
1872                         wprintf("<input type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Save changes"));
1873                         wprintf("&nbsp;");
1874                         wprintf("<input type=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
1875                         wprintf("</CENTER></td><tr>\n");
1876         
1877                         wprintf("</table>\n"
1878                                 "<input type=\"hidden\" NAME=\"tab\" VALUE=\"expire\">\n"
1879                                 "</form>\n"
1880                         );
1881                 }
1882
1883                 wprintf("</div>");
1884         }
1885
1886         /* Access controls */
1887         if (!strcmp(tab, "access")) {
1888                 wprintf("<div class=\"tabcontent\">");
1889                 display_whok();
1890                 wprintf("</div>");
1891         }
1892
1893         /* Fetch messages from remote locations */
1894         if (!strcmp(tab, "feeds")) {
1895                 wprintf("<div class=\"tabcontent\">");
1896
1897                 wprintf("<i>");
1898                 wprintf(_("Retrieve messages from these remote POP3 accounts and store them in this room:"));
1899                 wprintf("</i><br />\n");
1900
1901                 wprintf("<table class=\"altern\" border=0 cellpadding=5>"
1902                         "<tr class=\"even\"><th>");
1903                 wprintf(_("Remote host"));
1904                 wprintf("</th><th>");
1905                 wprintf(_("User name"));
1906                 wprintf("</th><th>");
1907                 wprintf(_("Password"));
1908                 wprintf("</th><th>");
1909                 wprintf(_("Keep messages on server?"));
1910                 wprintf("</th><th>");
1911                 wprintf(_("Interval"));
1912                 wprintf("</th><th> </th></tr>");
1913
1914                 serv_puts("GNET");
1915                 serv_getln(buf, sizeof buf);
1916                 bg = 1;
1917                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1918                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1919                         if (!strcasecmp(cmd, "pop3client")) {
1920                                 safestrncpy(recp, &buf[11], sizeof recp);
1921
1922                                 bg = 1 - bg;
1923                                 wprintf("<tr class=\"%s\">",
1924                                         (bg ? "even" : "odd")
1925                                 );
1926
1927                                 wprintf("<td>");
1928                                 extract_token(pop3_host, buf, 1, '|', sizeof pop3_host);
1929                                 escputs(pop3_host);
1930                                 wprintf("</td>");
1931
1932                                 wprintf("<td>");
1933                                 extract_token(pop3_user, buf, 2, '|', sizeof pop3_user);
1934                                 escputs(pop3_user);
1935                                 wprintf("</td>");
1936
1937                                 wprintf("<td>*****</td>");              /* Don't show the password */
1938
1939                                 wprintf("<td>%s</td>", extract_int(buf, 4) ? _("Yes") : _("No"));
1940
1941                                 wprintf("<td>%ld</td>", extract_long(buf, 5));  // Fetching interval
1942                         
1943                                 wprintf("<td class=\"button_link\">");
1944                                 wprintf(" <a href=\"netedit&cmd=remove&tab=feeds&line=pop3client|");
1945                                 urlescputs(recp);
1946                                 wprintf("\">");
1947                                 wprintf(_("(remove)"));
1948                                 wprintf("</a></td>");
1949                         
1950                                 wprintf("</tr>");
1951                         }
1952                 }
1953
1954                 wprintf("<form method=\"POST\" action=\"netedit\">\n"
1955                         "<tr>"
1956                         "<input type=\"hidden\" name=\"tab\" value=\"feeds\">"
1957                         "<input type=\"hidden\" name=\"prefix\" value=\"pop3client|\">\n");
1958                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1959                 wprintf("<td>");
1960                 wprintf("<input type=\"text\" id=\"add_as_pop3host\" NAME=\"line_pop3host\">\n");
1961                 wprintf("</td>");
1962                 wprintf("<td>");
1963                 wprintf("<input type=\"text\" id=\"add_as_pop3user\" NAME=\"line_pop3user\">\n");
1964                 wprintf("</td>");
1965                 wprintf("<td>");
1966                 wprintf("<input type=\"password\" id=\"add_as_pop3pass\" NAME=\"line_pop3pass\">\n");
1967                 wprintf("</td>");
1968                 wprintf("<td>");
1969                 wprintf("<input type=\"checkbox\" id=\"add_as_pop3keep\" NAME=\"line_pop3keep\" VALUE=\"1\">");
1970                 wprintf("</td>");
1971                 wprintf("<td>");
1972                 wprintf("<input type=\"text\" id=\"add_as_pop3int\" NAME=\"line_pop3int\" MAXLENGTH=\"5\">");
1973                 wprintf("</td>");
1974                 wprintf("<td>");
1975                 wprintf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1976                 wprintf("</td></tr>");
1977                 wprintf("</form></table>\n");
1978
1979                 wprintf("<hr>\n");
1980
1981                 wprintf("<i>");
1982                 wprintf(_("Fetch the following RSS feeds and store them in this room:"));
1983                 wprintf("</i><br />\n");
1984
1985                 wprintf("<table class=\"altern\" border=0 cellpadding=5>"
1986                         "<tr class=\"even\"><th>");
1987                 wprintf("<img src=\"static/rss_16x.png\" width=\"16\" height=\"16\" alt=\" \"> ");
1988                 wprintf(_("Feed URL"));
1989                 wprintf("</th><th>");
1990                 wprintf("</th></tr>");
1991
1992                 serv_puts("GNET");
1993                 serv_getln(buf, sizeof buf);
1994                 bg = 1;
1995                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1996                         extract_token(cmd, buf, 0, '|', sizeof cmd);
1997                         if (!strcasecmp(cmd, "rssclient")) {
1998                                 safestrncpy(recp, &buf[10], sizeof recp);
1999
2000                                 bg = 1 - bg;
2001                                 wprintf("<tr class=\"%s\">",
2002                                         (bg ? "even" : "odd")
2003                                 );
2004
2005                                 wprintf("<td>");
2006                                 extract_token(pop3_host, buf, 1, '|', sizeof pop3_host);
2007                                 escputs(pop3_host);
2008                                 wprintf("</td>");
2009
2010                                 wprintf("<td class=\"button_link\">");
2011                                 wprintf(" <a href=\"netedit&cmd=remove&tab=feeds&line=rssclient|");
2012                                 urlescputs(recp);
2013                                 wprintf("\">");
2014                                 wprintf(_("(remove)"));
2015                                 wprintf("</a></td>");
2016                         
2017                                 wprintf("</tr>");
2018                         }
2019                 }
2020
2021                 wprintf("<form method=\"POST\" action=\"netedit\">\n"
2022                         "<tr>"
2023                         "<input type=\"hidden\" name=\"tab\" value=\"feeds\">"
2024                         "<input type=\"hidden\" name=\"prefix\" value=\"rssclient|\">\n");
2025                 wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2026                 wprintf("<td>");
2027                 wprintf("<input type=\"text\" id=\"add_as_pop3host\" size=\"72\" "
2028                         "maxlength=\"256\" name=\"line_pop3host\">\n");
2029                 wprintf("</td>");
2030                 wprintf("<td>");
2031                 wprintf("<input type=\"submit\" name=\"add_button\" value=\"%s\">", _("Add"));
2032                 wprintf("</td></tr>");
2033                 wprintf("</form></table>\n");
2034
2035                 wprintf("</div>");
2036         }
2037
2038
2039         /* end content of whatever tab is open now */
2040         wprintf("</div>\n");
2041
2042         address_book_popup();
2043         wDumpContent(1);
2044 }
2045
2046
2047 /* 
2048  * Toggle self-service list subscription
2049  */
2050 void toggle_self_service(void) {
2051         room_states RoomFlags;
2052
2053         get_roomflags (&RoomFlags);
2054
2055         if (yesbstr("QR2_SelfList")) 
2056                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SELFLIST;
2057         else 
2058                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SELFLIST;
2059
2060         if (yesbstr("QR2_SMTP_PUBLIC")) 
2061                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SMTP_PUBLIC;
2062         else
2063                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SMTP_PUBLIC;
2064
2065         if (yesbstr("QR2_Moderated")) 
2066                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_MODERATED;
2067         else
2068                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_MODERATED;
2069         if (yesbstr("QR2_SubsOnly")) 
2070                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SMTP_PUBLIC;
2071         else
2072                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SMTP_PUBLIC;
2073
2074         set_roomflags (&RoomFlags);
2075         
2076         display_editroom();
2077 }
2078
2079
2080
2081 /*
2082  * save new parameters for a room
2083  */
2084 void editroom(void)
2085 {
2086         char buf[SIZ];
2087         char er_name[128];
2088         char er_password[10];
2089         char er_dirname[15];
2090         char er_roomaide[26];
2091         int er_floor;
2092         unsigned er_flags;
2093         int er_listingorder;
2094         int er_defaultview;
2095         unsigned er_flags2;
2096         int bump;
2097
2098
2099         if (!havebstr("ok_button")) {
2100                 strcpy(WC->ImportantMessage,
2101                         _("Cancelled.  Changes were not saved."));
2102                 display_editroom();
2103                 return;
2104         }
2105         serv_puts("GETR");
2106         serv_getln(buf, sizeof buf);
2107
2108         if (buf[0] != '2') {
2109                 strcpy(WC->ImportantMessage, &buf[4]);
2110                 display_editroom();
2111                 return;
2112         }
2113         extract_token(er_name, &buf[4], 0, '|', sizeof er_name);
2114         extract_token(er_password, &buf[4], 1, '|', sizeof er_password);
2115         extract_token(er_dirname, &buf[4], 2, '|', sizeof er_dirname);
2116         er_flags = extract_int(&buf[4], 3);
2117         er_listingorder = extract_int(&buf[4], 5);
2118         er_defaultview = extract_int(&buf[4], 6);
2119         er_flags2 = extract_int(&buf[4], 7);
2120
2121         strcpy(er_roomaide, bstr("er_roomaide"));
2122         if (IsEmptyStr(er_roomaide)) {
2123                 serv_puts("GETA");
2124                 serv_getln(buf, sizeof buf);
2125                 if (buf[0] != '2') {
2126                         strcpy(er_roomaide, "");
2127                 } else {
2128                         extract_token(er_roomaide, &buf[4], 0, '|', sizeof er_roomaide);
2129                 }
2130         }
2131         strcpy(buf, bstr("er_name"));
2132         buf[128] = 0;
2133         if (!IsEmptyStr(buf)) {
2134                 strcpy(er_name, buf);
2135         }
2136
2137         strcpy(buf, bstr("er_password"));
2138         buf[10] = 0;
2139         if (!IsEmptyStr(buf))
2140                 strcpy(er_password, buf);
2141
2142         strcpy(buf, bstr("er_dirname"));
2143         buf[15] = 0;
2144         if (!IsEmptyStr(buf))
2145                 strcpy(er_dirname, buf);
2146
2147         strcpy(buf, bstr("type"));
2148         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
2149
2150         if (!strcmp(buf, "invonly")) {
2151                 er_flags |= (QR_PRIVATE);
2152         }
2153         if (!strcmp(buf, "hidden")) {
2154                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
2155         }
2156         if (!strcmp(buf, "passworded")) {
2157                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
2158         }
2159         if (!strcmp(buf, "personal")) {
2160                 er_flags |= QR_MAILBOX;
2161         } else {
2162                 er_flags &= ~QR_MAILBOX;
2163         }
2164         
2165         if (yesbstr("prefonly")) {
2166                 er_flags |= QR_PREFONLY;
2167         } else {
2168                 er_flags &= ~QR_PREFONLY;
2169         }
2170
2171         if (yesbstr("readonly")) {
2172                 er_flags |= QR_READONLY;
2173         } else {
2174                 er_flags &= ~QR_READONLY;
2175         }
2176
2177         
2178         if (yesbstr("collabdel")) {
2179                 er_flags2 |= QR2_COLLABDEL;
2180         } else {
2181                 er_flags2 &= ~QR2_COLLABDEL;
2182         }
2183
2184         if (yesbstr("permanent")) {
2185                 er_flags |= QR_PERMANENT;
2186         } else {
2187                 er_flags &= ~QR_PERMANENT;
2188         }
2189
2190         if (yesbstr("subjectreq")) {
2191                 er_flags2 |= QR2_SUBJECTREQ;
2192         } else {
2193                 er_flags2 &= ~QR2_SUBJECTREQ;
2194         }
2195
2196         if (yesbstr("network")) {
2197                 er_flags |= QR_NETWORK;
2198         } else {
2199                 er_flags &= ~QR_NETWORK;
2200         }
2201
2202         if (yesbstr("directory")) {
2203                 er_flags |= QR_DIRECTORY;
2204         } else {
2205                 er_flags &= ~QR_DIRECTORY;
2206         }
2207
2208         if (yesbstr("ulallowed")) {
2209                 er_flags |= QR_UPLOAD;
2210         } else {
2211                 er_flags &= ~QR_UPLOAD;
2212         }
2213
2214         if (yesbstr("dlallowed")) {
2215                 er_flags |= QR_DOWNLOAD;
2216         } else {
2217                 er_flags &= ~QR_DOWNLOAD;
2218         }
2219
2220         if (yesbstr("visdir")) {
2221                 er_flags |= QR_VISDIR;
2222         } else {
2223                 er_flags &= ~QR_VISDIR;
2224         }
2225
2226         strcpy(buf, bstr("anon"));
2227
2228         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
2229         if (!strcmp(buf, "anononly"))
2230                 er_flags |= QR_ANONONLY;
2231         if (!strcmp(buf, "anon2"))
2232                 er_flags |= QR_ANONOPT;
2233
2234         bump = 0;
2235         if (!strcmp(bstr("bump"), "yes"))
2236                 bump = 1;
2237
2238         er_floor = ibstr("er_floor");
2239
2240         sprintf(buf, "SETR %s|%s|%s|%u|%d|%d|%d|%d|%u",
2241                 er_name, er_password, er_dirname, er_flags, bump, er_floor,
2242                 er_listingorder, er_defaultview, er_flags2);
2243         serv_puts(buf);
2244         serv_getln(buf, sizeof buf);
2245         if (buf[0] != '2') {
2246                 strcpy(WC->ImportantMessage, &buf[4]);
2247                 display_editroom();
2248                 return;
2249         }
2250         gotoroom(er_name);
2251
2252         if (!IsEmptyStr(er_roomaide)) {
2253                 sprintf(buf, "SETA %s", er_roomaide);
2254                 serv_puts(buf);
2255                 serv_getln(buf, sizeof buf);
2256                 if (buf[0] != '2') {
2257                         strcpy(WC->ImportantMessage, &buf[4]);
2258                         display_main_menu();
2259                         return;
2260                 }
2261         }
2262         gotoroom(er_name);
2263         strcpy(WC->ImportantMessage, _("Your changes have been saved."));
2264         display_editroom();
2265         return;
2266 }
2267
2268
2269 /*
2270  * Display form for Invite, Kick, and show Who Knows a room
2271  */
2272 void do_invt_kick(void) {
2273         char buf[SIZ], room[SIZ], username[SIZ];
2274
2275         serv_puts("GETR");
2276         serv_getln(buf, sizeof buf);
2277
2278         if (buf[0] != '2') {
2279                 escputs(&buf[4]);
2280                 return;
2281         }
2282         extract_token(room, &buf[4], 0, '|', sizeof room);
2283
2284         strcpy(username, bstr("username"));
2285
2286         if (havebstr("kick_button")) {
2287                 sprintf(buf, "KICK %s", username);
2288                 serv_puts(buf);
2289                 serv_getln(buf, sizeof buf);
2290
2291                 if (buf[0] != '2') {
2292                         strcpy(WC->ImportantMessage, &buf[4]);
2293                 } else {
2294                         sprintf(WC->ImportantMessage,
2295                                 _("<B><I>User %s kicked out of room %s.</I></B>\n"), 
2296                                 username, room);
2297                 }
2298         }
2299
2300         if (havebstr("invite_button")) {
2301                 sprintf(buf, "INVT %s", username);
2302                 serv_puts(buf);
2303                 serv_getln(buf, sizeof buf);
2304
2305                 if (buf[0] != '2') {
2306                         strcpy(WC->ImportantMessage, &buf[4]);
2307                 } else {
2308                         sprintf(WC->ImportantMessage,
2309                                 _("<B><I>User %s invited to room %s.</I></B>\n"), 
2310                                 username, room);
2311                 }
2312         }
2313
2314         display_editroom();
2315 }
2316
2317
2318
2319 /*
2320  * Display form for Invite, Kick, and show Who Knows a room
2321  */
2322 void display_whok(void)
2323 {
2324         char buf[SIZ], room[SIZ], username[SIZ];
2325
2326         serv_puts("GETR");
2327         serv_getln(buf, sizeof buf);
2328
2329         if (buf[0] != '2') {
2330                 escputs(&buf[4]);
2331                 return;
2332         }
2333         extract_token(room, &buf[4], 0, '|', sizeof room);
2334
2335         
2336         wprintf("<table border=0 CELLSPACING=10><tr VALIGN=TOP><td>");
2337         wprintf(_("The users listed below have access to this room.  "
2338                 "To remove a user from the access list, select the user "
2339                 "name from the list and click 'Kick'."));
2340         wprintf("<br /><br />");
2341         
2342         wprintf("<CENTER><form method=\"POST\" action=\"do_invt_kick\">\n");
2343         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2344         wprintf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
2345         wprintf("<select NAME=\"username\" SIZE=\"10\" style=\"width:100%%\">\n");
2346         serv_puts("WHOK");
2347         serv_getln(buf, sizeof buf);
2348         if (buf[0] == '1') {
2349                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2350                         extract_token(username, buf, 0, '|', sizeof username);
2351                         wprintf("<OPTION>");
2352                         escputs(username);
2353                         wprintf("\n");
2354                 }
2355         }
2356         wprintf("</select><br />\n");
2357
2358         wprintf("<input type=\"submit\" name=\"kick_button\" value=\"%s\">", _("Kick"));
2359         wprintf("</form></CENTER>\n");
2360
2361         wprintf("</td><td>");
2362         wprintf(_("To grant another user access to this room, enter the "
2363                 "user name in the box below and click 'Invite'."));
2364         wprintf("<br /><br />");
2365
2366         wprintf("<CENTER><form method=\"POST\" action=\"do_invt_kick\">\n");
2367         wprintf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
2368         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2369         wprintf(_("Invite:"));
2370         wprintf(" ");
2371         wprintf("<input type=\"text\" name=\"username\" id=\"username_id\" style=\"width:100%%\"><br />\n"
2372                 "<input type=\"hidden\" name=\"invite_button\" value=\"Invite\">"
2373                 "<input type=\"submit\" value=\"%s\">"
2374                 "</form></CENTER>\n", _("Invite"));
2375                 /* Pop open an address book -- begin **/
2376                 wprintf(
2377                         "<a href=\"javascript:PopOpenAddressBook('username_id|%s');\" "
2378                         "title=\"%s\">"
2379                         "<img align=middle border=0 width=24 height=24 src=\"static/viewcontacts_24x.gif\">"
2380                         "&nbsp;%s</a>",
2381                         _("User"), 
2382                         _("Users"), _("Users")
2383                 );
2384                 /* Pop open an address book -- end **/
2385
2386         wprintf("</td></tr></table>\n");
2387         address_book_popup();
2388         wDumpContent(1);
2389 }
2390
2391
2392
2393 /*
2394  * display the form for entering a new room
2395  */
2396 void display_entroom(void)
2397 {
2398         int i;
2399         char buf[SIZ];
2400
2401         serv_puts("CRE8 0");
2402         serv_getln(buf, sizeof buf);
2403
2404         if (buf[0] != '2') {
2405                 strcpy(WC->ImportantMessage, &buf[4]);
2406                 display_main_menu();
2407                 return;
2408         }
2409
2410         output_headers(1, 1, 1, 0, 0, 0);
2411
2412         svprintf(HKEY("BOXTITLE"), WCS_STRING, _("Create a new room"));
2413         do_template("beginbox", NULL);
2414
2415         wprintf("<form name=\"create_room_form\" method=\"POST\" action=\"entroom\">\n");
2416         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2417
2418         wprintf("<table class=\"altern\"> ");
2419
2420         wprintf("<tr class=\"even\"><td>");
2421         wprintf(_("Name of room: "));
2422         wprintf("</td><td>");
2423         wprintf("<input type=\"text\" NAME=\"er_name\" MAXLENGTH=\"127\">\n");
2424         wprintf("</td></tr>");
2425
2426         wprintf("<tr class=\"odd\"><td>");
2427         wprintf(_("Resides on floor: "));
2428         wprintf("</td><td>");
2429         load_floorlist(); 
2430         wprintf("<select name=\"er_floor\" size=\"1\">\n");
2431         for (i = 0; i < 128; ++i)
2432                 if (!IsEmptyStr(floorlist[i])) {
2433                         wprintf("<option ");
2434                         wprintf("value=\"%d\">", i);
2435                         escputs(floorlist[i]);
2436                         wprintf("</option>\n");
2437                 }
2438         wprintf("</select>\n");
2439         wprintf("</td></tr>");
2440
2441                 /*
2442                  * Our clever little snippet of JavaScript automatically selects
2443                  * a public room if the view is set to Bulletin Board or wiki, and
2444                  * it selects a mailbox room otherwise.  The user can override this,
2445                  * of course.  We also disable the floor selector for mailboxes.
2446                  */
2447         wprintf("<tr class=\"even\"><td>");
2448         wprintf(_("Default view for room: "));
2449         wprintf("</td><td>");
2450         wprintf("<select name=\"er_view\" size=\"1\" OnChange=\""
2451                 "       if ( (this.form.er_view.value == 0)             "
2452                 "          || (this.form.er_view.value == 6) ) {        "
2453                 "               this.form.type[0].checked=true;         "
2454                 "               this.form.er_floor.disabled = false;    "
2455                 "       }                                               "
2456                 "       else {                                          "
2457                 "               this.form.type[4].checked=true;         "
2458                 "               this.form.er_floor.disabled = true;     "
2459                 "       }                                               "
2460                 "\">\n");
2461         for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
2462                 if (is_view_allowed_as_default(i)) {
2463                         wprintf("<option %s value=\"%d\">",
2464                                 ((i == 0) ? "selected" : ""), i );
2465                         escputs(viewdefs[i]);
2466                         wprintf("</option>\n");
2467                 }
2468         }
2469         wprintf("</select>\n");
2470         wprintf("</td></tr>");
2471
2472         wprintf("<tr class=\"even\"><td>");
2473         wprintf(_("Type of room:"));
2474         wprintf("</td><td>");
2475         wprintf("<ul class=\"adminlist\">\n");
2476
2477         wprintf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"public\" ");
2478         wprintf("CHECKED OnChange=\""
2479                 "       if (this.form.type[0].checked == true) {        "
2480                 "               this.form.er_floor.disabled = false;    "
2481                 "       }                                               "
2482                 "\"> ");
2483         wprintf(_("Public (automatically appears to everyone)"));
2484         wprintf("</li>");
2485
2486         wprintf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"hidden\" OnChange=\""
2487                 "       if (this.form.type[1].checked == true) {        "
2488                 "               this.form.er_floor.disabled = false;    "
2489                 "       }                                               "
2490                 "\"> ");
2491         wprintf(_("Private - hidden (accessible to anyone who knows its name)"));
2492         wprintf("</li>");
2493
2494         wprintf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"passworded\" OnChange=\""
2495                 "       if (this.form.type[2].checked == true) {        "
2496                 "               this.form.er_floor.disabled = false;    "
2497                 "       }                                               "
2498                 "\"> ");
2499         wprintf(_("Private - require password: "));
2500         wprintf("<input type=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
2501         wprintf("</li>");
2502
2503         wprintf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"invonly\" OnChange=\""
2504                 "       if (this.form.type[3].checked == true) {        "
2505                 "               this.form.er_floor.disabled = false;    "
2506                 "       }                                               "
2507                 "\"> ");
2508         wprintf(_("Private - invitation only"));
2509         wprintf("</li>");
2510
2511         wprintf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"personal\" "
2512                 "OnChange=\""
2513                 "       if (this.form.type[4].checked == true) {        "
2514                 "               this.form.er_floor.disabled = true;     "
2515                 "       }                                               "
2516                 "\"> ");
2517         wprintf(_("Personal (mailbox for you only)"));
2518         wprintf("</li>");
2519
2520         wprintf("\n</ul>\n");
2521         wprintf("</td></tr></table>\n");
2522
2523         wprintf("<div class=\"buttons\">\n");
2524         wprintf("<input type=\"submit\" name=\"ok_button\" value=\"%s\">", _("Create new room"));
2525         wprintf("&nbsp;");
2526         wprintf("<input type=\"submit\" name=\"cancel_button\" value=\"%s\">", _("Cancel"));
2527         wprintf("</div>\n");
2528         wprintf("</form>\n<hr />");
2529         serv_printf("MESG roomaccess");
2530         serv_getln(buf, sizeof buf);
2531         if (buf[0] == '1') {
2532                 fmout("LEFT");
2533         }
2534
2535         do_template("endbox", NULL);
2536
2537         wDumpContent(1);
2538 }
2539
2540
2541
2542
2543 /*
2544  * support function for entroom() -- sets the default view 
2545  */
2546 void er_set_default_view(int newview) {
2547
2548         char buf[SIZ];
2549
2550         char rm_name[SIZ];
2551         char rm_pass[SIZ];
2552         char rm_dir[SIZ];
2553         int rm_bits1;
2554         int rm_floor;
2555         int rm_listorder;
2556         int rm_bits2;
2557
2558         serv_puts("GETR");
2559         serv_getln(buf, sizeof buf);
2560         if (buf[0] != '2') return;
2561
2562         extract_token(rm_name, &buf[4], 0, '|', sizeof rm_name);
2563         extract_token(rm_pass, &buf[4], 1, '|', sizeof rm_pass);
2564         extract_token(rm_dir, &buf[4], 2, '|', sizeof rm_dir);
2565         rm_bits1 = extract_int(&buf[4], 3);
2566         rm_floor = extract_int(&buf[4], 4);
2567         rm_listorder = extract_int(&buf[4], 5);
2568         rm_bits2 = extract_int(&buf[4], 7);
2569
2570         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
2571                 rm_name, rm_pass, rm_dir, rm_bits1, rm_floor,
2572                 rm_listorder, newview, rm_bits2
2573         );
2574         serv_getln(buf, sizeof buf);
2575 }
2576
2577
2578
2579 /*
2580  * Create a new room
2581  */
2582 void entroom(void)
2583 {
2584         char buf[SIZ];
2585         char er_name[SIZ];
2586         char er_type[SIZ];
2587         char er_password[SIZ];
2588         int er_floor;
2589         int er_num_type;
2590         int er_view;
2591
2592         if (!havebstr("ok_button")) {
2593                 strcpy(WC->ImportantMessage,
2594                         _("Cancelled.  No new room was created."));
2595                 display_main_menu();
2596                 return;
2597         }
2598         strcpy(er_name, bstr("er_name"));
2599         strcpy(er_type, bstr("type"));
2600         strcpy(er_password, bstr("er_password"));
2601         er_floor = ibstr("er_floor");
2602         er_view = ibstr("er_view");
2603
2604         er_num_type = 0;
2605         if (!strcmp(er_type, "hidden"))
2606                 er_num_type = 1;
2607         if (!strcmp(er_type, "passworded"))
2608                 er_num_type = 2;
2609         if (!strcmp(er_type, "invonly"))
2610                 er_num_type = 3;
2611         if (!strcmp(er_type, "personal"))
2612                 er_num_type = 4;
2613
2614         sprintf(buf, "CRE8 1|%s|%d|%s|%d|%d|%d", 
2615                 er_name, er_num_type, er_password, er_floor, 0, er_view);
2616         serv_puts(buf);
2617         serv_getln(buf, sizeof buf);
2618         if (buf[0] != '2') {
2619                 strcpy(WC->ImportantMessage, &buf[4]);
2620                 display_main_menu();
2621                 return;
2622         }
2623         /** TODO: Room created, now udate the left hand icon bar for this user */
2624         burn_folder_cache(0);   /* burn the old folder cache */
2625         
2626         
2627         gotoroom(er_name);
2628         do_change_view(er_view);                /* Now go there */
2629 }
2630
2631
2632 /**
2633  * \brief display the screen to enter a private room
2634  */
2635 void display_private(char *rname, int req_pass)
2636 {
2637         StrBuf *Buf;
2638         output_headers(1, 1, 1, 0, 0, 0);
2639
2640         Buf = NewStrBufPlain(_("Go to a hidden room"), -1);
2641         DoTemplate(HKEY("beginbox"), NULL, Buf, CTX_STRBUF);
2642
2643         FreeStrBuf(&Buf);
2644
2645         wprintf("<p>");
2646         wprintf(_("If you know the name of a hidden (guess-name) or "
2647                 "passworded room, you can enter that room by typing "
2648                 "its name below.  Once you gain access to a private "
2649                 "room, it will appear in your regular room listings "
2650                 "so you don't have to keep returning here."));
2651         wprintf("</p>");
2652
2653         wprintf("<form method=\"post\" action=\"goto_private\">\n");
2654         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2655
2656         wprintf("<table class=\"altern\"> "
2657                 "<tr class=\"even\"><td>");
2658         wprintf(_("Enter room name:"));
2659         wprintf("</td><td>"
2660                 "<input type=\"text\" name=\"gr_name\" "
2661                 "value=\"%s\" maxlength=\"128\">\n", rname);
2662
2663         if (req_pass) {
2664                 wprintf("</td></tr><tr class=\"odd\"><td>");
2665                 wprintf(_("Enter room password:"));
2666                 wprintf("</td><td>");
2667                 wprintf("<input type=\"password\" name=\"gr_pass\" maxlength=\"9\">\n");
2668         }
2669         wprintf("</td></tr></table>\n");
2670
2671         wprintf("<div class=\"buttons\">\n");
2672         wprintf("<input type=\"submit\" name=\"ok_button\" value=\"%s\">"
2673                 "&nbsp;"
2674                 "<input type=\"submit\" name=\"cancel_button\" value=\"%s\">",
2675                 _("Go there"),
2676                 _("Cancel")
2677         );
2678         wprintf("</div></form>\n");
2679
2680         do_template("endbox", NULL);
2681
2682         wDumpContent(1);
2683 }
2684
2685 /**
2686  * \brief goto a private room
2687  */
2688 void goto_private(void)
2689 {
2690         char hold_rm[SIZ];
2691         char buf[SIZ];
2692
2693         if (!havebstr("ok_button")) {
2694                 display_main_menu();
2695                 return;
2696         }
2697         strcpy(hold_rm, WC->wc_roomname);
2698         strcpy(buf, "GOTO ");
2699         strcat(buf, bstr("gr_name"));
2700         strcat(buf, "|");
2701         strcat(buf, bstr("gr_pass"));
2702         serv_puts(buf);
2703         serv_getln(buf, sizeof buf);
2704
2705         if (buf[0] == '2') {
2706                 smart_goto(bstr("gr_name"));
2707                 return;
2708         }
2709         if (!strncmp(buf, "540", 3)) {
2710                 display_private(bstr("gr_name"), 1);
2711                 return;
2712         }
2713         output_headers(1, 1, 1, 0, 0, 0);
2714         wprintf("%s\n", &buf[4]);
2715         wDumpContent(1);
2716         return;
2717 }
2718
2719
2720 /**
2721  * \brief display the screen to zap a room
2722  */
2723 void display_zap(void)
2724 {
2725         output_headers(1, 1, 2, 0, 0, 0);
2726
2727         wprintf("<div id=\"banner\">\n");
2728         wprintf("<h1>");
2729         wprintf(_("Zap (forget/unsubscribe) the current room"));
2730         wprintf("</h1>\n");
2731         wprintf("</div>\n");
2732
2733         wprintf("<div id=\"content\" class=\"service\">\n");
2734
2735         wprintf(_("If you select this option, <em>%s</em> will "
2736                 "disappear from your room list.  Is this what you wish "
2737                 "to do?<br />\n"), WC->wc_roomname);
2738
2739         wprintf("<form method=\"POST\" action=\"zap\">\n");
2740         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2741         wprintf("<input type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Zap this room"));
2742         wprintf("&nbsp;");
2743         wprintf("<input type=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
2744         wprintf("</form>\n");
2745         wDumpContent(1);
2746 }
2747
2748
2749 /**
2750  * \brief zap a room
2751  */
2752 void zap(void)
2753 {
2754         char buf[SIZ];
2755         char final_destination[SIZ];
2756
2757         /**
2758          * If the forget-room routine fails for any reason, we fall back
2759          * to the current room; otherwise, we go to the Lobby
2760          */
2761         strcpy(final_destination, WC->wc_roomname);
2762
2763         if (havebstr("ok_button")) {
2764                 serv_printf("GOTO %s", WC->wc_roomname);
2765                 serv_getln(buf, sizeof buf);
2766                 if (buf[0] == '2') {
2767                         serv_puts("FORG");
2768                         serv_getln(buf, sizeof buf);
2769                         if (buf[0] == '2') {
2770                                 strcpy(final_destination, "_BASEROOM_");
2771                         }
2772                 }
2773         }
2774         smart_goto(final_destination);
2775 }
2776
2777
2778
2779 /**
2780  * \brief Delete the current room
2781  */
2782 void delete_room(void)
2783 {
2784         char buf[SIZ];
2785
2786         
2787         serv_puts("KILL 1");
2788         serv_getln(buf, sizeof buf);
2789         burn_folder_cache(0);   /* Burn the cahce of known rooms to update the icon bar */
2790         if (buf[0] != '2') {
2791                 strcpy(WC->ImportantMessage, &buf[4]);
2792                 display_main_menu();
2793                 return;
2794         } else {
2795                 smart_goto("_BASEROOM_");
2796         }
2797 }
2798
2799
2800
2801 /**
2802  * \brief Perform changes to a room's network configuration
2803  */
2804 void netedit(void) {
2805         FILE *fp;
2806         char buf[SIZ];
2807         char line[SIZ];
2808         char cmpa0[SIZ];
2809         char cmpa1[SIZ];
2810         char cmpb0[SIZ];
2811         char cmpb1[SIZ];
2812         int i, num_addrs;
2813         // TODO: do line dynamic!
2814         if (havebstr("line_pop3host")) {
2815                 strcpy(line, bstr("prefix"));
2816                 strcat(line, bstr("line_pop3host"));
2817                 strcat(line, "|");
2818                 strcat(line, bstr("line_pop3user"));
2819                 strcat(line, "|");
2820                 strcat(line, bstr("line_pop3pass"));
2821                 strcat(line, "|");
2822                 strcat(line, ibstr("line_pop3keep") ? "1" : "0" );
2823                 strcat(line, "|");
2824                 sprintf(&line[strlen(line)],"%ld", lbstr("line_pop3int"));
2825                 strcat(line, bstr("suffix"));
2826         }
2827         else if (havebstr("line")) {
2828                 strcpy(line, bstr("prefix"));
2829                 strcat(line, bstr("line"));
2830                 strcat(line, bstr("suffix"));
2831         }
2832         else {
2833                 display_editroom();
2834                 return;
2835         }
2836
2837
2838         fp = tmpfile();
2839         if (fp == NULL) {
2840                 display_editroom();
2841                 return;
2842         }
2843
2844         serv_puts("GNET");
2845         serv_getln(buf, sizeof buf);
2846         if (buf[0] != '1') {
2847                 fclose(fp);
2848                 display_editroom();
2849                 return;
2850         }
2851
2852         /** This loop works for add *or* remove.  Spiffy, eh? */
2853         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2854                 extract_token(cmpa0, buf, 0, '|', sizeof cmpa0);
2855                 extract_token(cmpa1, buf, 1, '|', sizeof cmpa1);
2856                 extract_token(cmpb0, line, 0, '|', sizeof cmpb0);
2857                 extract_token(cmpb1, line, 1, '|', sizeof cmpb1);
2858                 if ( (strcasecmp(cmpa0, cmpb0)) 
2859                    || (strcasecmp(cmpa1, cmpb1)) ) {
2860                         fprintf(fp, "%s\n", buf);
2861                 }
2862         }
2863
2864         rewind(fp);
2865         serv_puts("SNET");
2866         serv_getln(buf, sizeof buf);
2867         if (buf[0] != '4') {
2868                 fclose(fp);
2869                 display_editroom();
2870                 return;
2871         }
2872
2873         while (fgets(buf, sizeof buf, fp) != NULL) {
2874                 buf[strlen(buf)-1] = 0;
2875                 serv_puts(buf);
2876         }
2877
2878         if (havebstr("add_button")) {
2879                 num_addrs = num_tokens(bstr("line"), ',');
2880                 if (num_addrs < 2) {
2881                         /* just adding one node or address */
2882                         serv_puts(line);
2883                 }
2884                 else {
2885                         /* adding multiple addresses separated by commas */
2886                         for (i=0; i<num_addrs; ++i) {
2887                                 strcpy(line, bstr("prefix"));
2888                                 extract_token(buf, bstr("line"), i, ',', sizeof buf);
2889                                 striplt(buf);
2890                                 strcat(line, buf);
2891                                 strcat(line, bstr("suffix"));
2892                                 serv_puts(line);
2893                         }
2894                 }
2895         }
2896
2897         serv_puts("000");
2898         fclose(fp);
2899         display_editroom();
2900 }
2901
2902
2903
2904 /**
2905  * \brief Convert a room name to a folder-ish-looking name.
2906  * \param folder the folderish name
2907  * \param room the room name
2908  * \param floor the floor name
2909  * \param is_mailbox is it a mailbox?
2910  */
2911 void room_to_folder(char *folder, char *room, int floor, int is_mailbox)
2912 {
2913         int i, len;
2914
2915         /**
2916          * For mailboxes, just do it straight...
2917          */
2918         if (is_mailbox) {
2919                 sprintf(folder, "My folders|%s", room);
2920         }
2921
2922         /**
2923          * Otherwise, prefix the floor name as a "public folders" moniker
2924          */
2925         else {
2926                 if (floor > MAX_FLOORS) {
2927                         wc_backtrace ();
2928                         sprintf(folder, "%%%%%%|%s", room);
2929                 }
2930                 else {
2931                         sprintf(folder, "%s|%s", floorlist[floor], room);
2932                 }
2933         }
2934
2935         /**
2936          * Replace "\" characters with "|" for pseudo-folder-delimiting
2937          */
2938         len = strlen (folder);
2939         for (i=0; i<len; ++i) {
2940                 if (folder[i] == '\\') folder[i] = '|';
2941         }
2942 }
2943
2944
2945
2946
2947 /**
2948  * \brief Back end for change_view()
2949  * \param newview set newview???
2950  */
2951 void do_change_view(int newview) {
2952         char buf[SIZ];
2953
2954         serv_printf("VIEW %d", newview);
2955         serv_getln(buf, sizeof buf);
2956         WC->wc_view = newview;
2957         smart_goto(WC->wc_roomname);
2958 }
2959
2960
2961
2962 /**
2963  * \brief Change the view for this room
2964  */
2965 void change_view(void) {
2966         int view;
2967
2968         view = lbstr("view");
2969         do_change_view(view);
2970 }
2971
2972
2973 /**
2974  * \brief One big expanded tree list view --- like a folder list
2975  * \param fold the folder to view
2976  * \param max_folders how many folders???
2977  * \param num_floors hom many floors???
2978  */
2979 void do_folder_view(struct folder *fold, int max_folders, int num_floors) {
2980         char buf[SIZ];
2981         int levels;
2982         int i;
2983         int has_subfolders = 0;
2984         int *parents;
2985
2986         parents = malloc(max_folders * sizeof(int));
2987
2988         /** BEGIN TREE MENU */
2989         wprintf("<div id=\"roomlist_div\">Loading folder list...</div>\n");
2990
2991         /** include NanoTree */
2992         wprintf("<script type=\"text/javascript\" src=\"static/nanotree.js\"></script>\n");
2993
2994         /** initialize NanoTree */
2995         wprintf("<script type=\"text/javascript\">                      \n"
2996                 "       showRootNode = false;                           \n"
2997                 "       sortNodes = false;                              \n"
2998                 "       dragable = false;                               \n"
2999                 "                                                       \n"
3000                 "       function standardClick(treeNode) {              \n"
3001                 "       }                                               \n"
3002                 "                                                       \n"
3003                 "       var closedGif = 'static/folder_closed.gif';     \n"
3004                 "       var openGif = 'static/folder_open.gif';         \n"
3005                 "                                                       \n"
3006                 "       rootNode = new TreeNode(1, 'root node - hide'); \n"
3007         );
3008
3009         levels = 0;
3010         for (i=0; i<max_folders; ++i) {
3011
3012                 has_subfolders = 0;
3013                 if ((i+1) < max_folders) {
3014                         int len;
3015                         len = strlen(fold[i].name);
3016                         if ( (!strncasecmp(fold[i].name, fold[i+1].name, len))
3017                            && (fold[i+1].name[len] == '|') ) {
3018                                 has_subfolders = 1;
3019                         }
3020                 }
3021
3022                 levels = num_tokens(fold[i].name, '|');
3023                 parents[levels] = i;
3024
3025                 wprintf("var node%d = new TreeNode(%d, '", i, i);
3026
3027                 if (fold[i].selectable) {
3028                         wprintf("<a href=\"dotgoto?room=");
3029                         urlescputs(fold[i].room);
3030                         wprintf("\">");
3031                 }
3032
3033                 if (levels == 1) {
3034                         wprintf("<span class=\"roomlist_floor\">");
3035                 }
3036                 else if (fold[i].hasnewmsgs) {
3037                         wprintf("<span class=\"roomlist_new\">");
3038                 }
3039                 else {
3040                         wprintf("<span class=\"roomlist_old\">");
3041                 }
3042                 extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
3043                 escputs(buf);
3044                 wprintf("</span>");
3045
3046                 wprintf("</a>', ");
3047                 if (has_subfolders) {
3048                         wprintf("new Array(closedGif, openGif)");
3049                 }
3050                 else if (fold[i].view == VIEW_ADDRESSBOOK) {
3051                         wprintf("'static/viewcontacts_16x.gif'");
3052                 }
3053                 else if (fold[i].view == VIEW_CALENDAR) {
3054                         wprintf("'static/calarea_16x.gif'");
3055                 }
3056                 else if (fold[i].view == VIEW_CALBRIEF) {
3057                         wprintf("'static/calarea_16x.gif'");
3058                 }
3059                 else if (fold[i].view == VIEW_TASKS) {
3060                         wprintf("'static/taskmanag_16x.gif'");
3061                 }
3062                 else if (fold[i].view == VIEW_NOTES) {
3063                         wprintf("'static/storenotes_16x.gif'");
3064                 }
3065                 else if (fold[i].view == VIEW_MAILBOX) {
3066                         wprintf("'static/privatemess_16x.gif'");
3067                 }
3068                 else {
3069                         wprintf("'static/chatrooms_16x.gif'");
3070                 }
3071                 wprintf(", '");
3072                 urlescputs(fold[i].name);
3073                 wprintf("');\n");
3074
3075                 if (levels < 2) {
3076                         wprintf("rootNode.addChild(node%d);\n", i);
3077                 }
3078                 else {
3079                         wprintf("node%d.addChild(node%d);\n", parents[levels-1], i);
3080                 }
3081         }
3082
3083         wprintf("container = document.getElementById('roomlist_div');   \n"
3084                 "showTree('');  \n"
3085                 "</script>\n"
3086         );
3087
3088         free(parents);
3089         /** END TREE MENU */
3090 }
3091
3092 /**
3093  * \brief Boxes and rooms and lists ... oh my!
3094  * \param fold the folder to view
3095  * \param max_folders how many folders???
3096  * \param num_floors hom many floors???
3097  */
3098 void do_rooms_view(struct folder *fold, int max_folders, int num_floors) {
3099         char buf[256];
3100         char floor_name[256];
3101         char old_floor_name[256];
3102         int levels, oldlevels;
3103         int i, t;
3104         int num_boxes = 0;
3105         static int columns = 3;
3106         int boxes_per_column = 0;
3107         int current_column = 0;
3108         int nf;
3109
3110         strcpy(floor_name, "");
3111         strcpy(old_floor_name, "");
3112
3113         nf = num_floors;
3114         while (nf % columns != 0) ++nf;
3115         boxes_per_column = (nf / columns);
3116         if (boxes_per_column < 1) boxes_per_column = 1;
3117
3118         /** Outer table (for columnization) */
3119         wprintf("<table BORDER=0 WIDTH=96%% CELLPADDING=5>"
3120                 "<tr><td valign=top>");
3121
3122         levels = 0;
3123         oldlevels = 0;
3124         for (i=0; i<max_folders; ++i) {
3125
3126                 levels = num_tokens(fold[i].name, '|');
3127                 extract_token(floor_name, fold[i].name, 0,
3128                         '|', sizeof floor_name);
3129
3130                 if ( (strcasecmp(floor_name, old_floor_name))
3131                    && (!IsEmptyStr(old_floor_name)) ) {
3132                         /* End inner box */
3133                         do_template("endbox", NULL);
3134                         wprintf("<br>");
3135
3136                         ++num_boxes;
3137                         if ((num_boxes % boxes_per_column) == 0) {
3138                                 ++current_column;
3139                                 if (current_column < columns) {
3140                                         wprintf("</td><td valign=top>\n");
3141                                 }
3142                         }
3143                 }
3144                 strcpy(old_floor_name, floor_name);
3145
3146                 if (levels == 1) {
3147                         StrBuf *Buf;
3148                         
3149                         Buf = NewStrBufPlain(floor_name, -1);
3150                         DoTemplate(HKEY("beginbox"), NULL, Buf, CTX_STRBUF);
3151                         
3152                         FreeStrBuf(&Buf);
3153                 }
3154
3155                 oldlevels = levels;
3156
3157                 if (levels > 1) {
3158                         wprintf("&nbsp;");
3159                         if (levels>2) for (t=0; t<(levels-2); ++t) wprintf("&nbsp;&nbsp;&nbsp;");
3160                         if (fold[i].selectable) {
3161                                 wprintf("<a href=\"dotgoto?room=");
3162                                 urlescputs(fold[i].room);
3163                                 wprintf("\">");
3164                         }
3165                         else {
3166                                 wprintf("<i>");
3167                         }
3168                         if (fold[i].hasnewmsgs) {
3169                                 wprintf("<span class=\"roomlist_new\">");
3170                         }
3171                         else {
3172                                 wprintf("<span class=\"roomlist_old\">");
3173                         }
3174                         extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
3175                         escputs(buf);
3176                         wprintf("</span>");
3177                         if (fold[i].selectable) {
3178                                 wprintf("</A>");
3179                         }
3180                         else {
3181                                 wprintf("</i>");
3182                         }
3183                         if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
3184                                 wprintf(" (INBOX)");
3185                         }
3186                         wprintf("<br />\n");
3187                 }
3188         }
3189         /** End the final inner box */
3190         do_template("endbox", NULL);
3191
3192         wprintf("</td></tr></table>\n");
3193 }
3194
3195 /**
3196  * \brief print a floor div???
3197  * \param which_floordiv name of the floordiv???
3198  */
3199 void set_floordiv_expanded(void) {
3200         struct wcsession *WCC = WC;
3201         StrBuf *FloorDiv;
3202         
3203         FloorDiv = NewStrBuf();
3204         StrBufAppendBuf(FloorDiv, WCC->UrlFragment2, 0);
3205         set_preference("floordiv_expanded", FloorDiv, 1);
3206         WCC->floordiv_expanded = FloorDiv;
3207 }
3208
3209 /**
3210  * \brief view the iconbar
3211  * \param fold the folder to view
3212  * \param max_folders how many folders???
3213  * \param num_floors hom many floors???
3214  */
3215 void do_iconbar_view(struct folder *fold, int max_folders, int num_floors) {
3216         char buf[256];
3217         char floor_name[256];
3218         char old_floor_name[256];
3219         char floordivtitle[256];
3220         char floordiv_id[32];
3221         int levels, oldlevels;
3222         int i, t;
3223         int num_drop_targets = 0;
3224         char *icon = NULL;
3225
3226         strcpy(floor_name, "");
3227         strcpy(old_floor_name, "");
3228
3229         levels = 0;
3230         oldlevels = 0;
3231         for (i=0; i<max_folders; ++i) {
3232
3233                 levels = num_tokens(fold[i].name, '|');
3234                 extract_token(floor_name, fold[i].name, 0,
3235                         '|', sizeof floor_name);
3236
3237                 if ( (strcasecmp(floor_name, old_floor_name))
3238                    && (!IsEmptyStr(old_floor_name)) ) {
3239                         /** End inner box */
3240                         wprintf("<br>\n");
3241                         wprintf("</div>\n");    /** floordiv */
3242                 }
3243                 strcpy(old_floor_name, floor_name);
3244
3245                 if (levels == 1) {
3246                         /** Begin floor */
3247                         stresc(floordivtitle, 256, floor_name, 0, 0);
3248                         sprintf(floordiv_id, "floordiv%d", i);
3249                         wprintf("<span class=\"ib_roomlist_floor\" "
3250                                 "onClick=\"expand_floor('%s')\">"
3251                                 "%s</span><br>\n", floordiv_id, floordivtitle);
3252                         wprintf("<div id=\"%s\" style=\"display:%s\">",
3253                                 floordiv_id,
3254                                 (!strcasecmp(floordiv_id, ChrPtr(WC->floordiv_expanded)) ? "block" : "none")
3255                         );
3256                 }
3257
3258                 oldlevels = levels;
3259
3260                 if (levels > 1) {
3261                         wprintf("<div id=\"roomdiv%d\">", i);
3262                         wprintf("&nbsp;");
3263                         if (levels>2) for (t=0; t<(levels-2); ++t) wprintf("&nbsp;");
3264
3265                         /** choose the icon */
3266                         if (fold[i].view == VIEW_ADDRESSBOOK) {
3267                                 icon = "viewcontacts_16x.gif" ;
3268                         }
3269                         else if (fold[i].view == VIEW_CALENDAR) {
3270                                 icon = "calarea_16x.gif" ;
3271                         }
3272                         else if (fold[i].view == VIEW_CALBRIEF) {
3273                                 icon = "calarea_16x.gif" ;
3274                         }
3275                         else if (fold[i].view == VIEW_TASKS) {
3276                                 icon = "taskmanag_16x.gif" ;
3277                         }
3278                         else if (fold[i].view == VIEW_NOTES) {
3279                                 icon = "storenotes_16x.gif" ;
3280                         }
3281                         else if (fold[i].view == VIEW_MAILBOX) {
3282                                 icon = "privatemess_16x.gif" ;
3283                         }
3284                         else {
3285                                 icon = "chatrooms_16x.gif" ;
3286                         }
3287
3288                         if (fold[i].selectable) {
3289                                 wprintf("<a href=\"dotgoto?room=");
3290                                 urlescputs(fold[i].room);
3291                                 wprintf("\">");
3292                                 wprintf("<img  border=0 src=\"static/%s\" alt=\"\"> ", icon);
3293                         }
3294                         else {
3295                                 wprintf("<i>");
3296                         }
3297                         if (fold[i].hasnewmsgs) {
3298                                 wprintf("<span class=\"ib_roomlist_new\">");
3299                         }
3300                         else {
3301                                 wprintf("<span class=\"ib_roomlist_old\">");
3302                         }
3303                         extract_token(buf, fold[i].name, levels-1, '|', sizeof buf);
3304                         escputs(buf);
3305                         if (!strcasecmp(fold[i].name, "My Folders|Mail")) {
3306                                 wprintf(" (INBOX)");
3307                         }
3308                         wprintf("</span>");
3309                         if (fold[i].selectable) {
3310                                 wprintf("</A>");
3311                         }
3312                         else {
3313                                 wprintf("</i>");
3314                         }
3315                         wprintf("<br />");
3316                         wprintf("</div>\n");    /** roomdiv */
3317                 }
3318         }
3319         wprintf("</div>\n");    /** floordiv */
3320
3321
3322         /** BEGIN: The old invisible pixel trick, to get our JavaScript to initialize */
3323         wprintf("<img src=\"static/blank.gif\" onLoad=\"\n");
3324
3325         num_drop_targets = 0;
3326
3327         for (i=0; i<max_folders; ++i) {
3328                 levels = num_tokens(fold[i].name, '|');
3329                 if (levels > 1) {
3330                         wprintf("drop_targets_elements[%d]=$('roomdiv%d');\n", num_drop_targets, i);
3331                         wprintf("drop_targets_roomnames[%d]='", num_drop_targets);
3332                         jsescputs(fold[i].room);
3333                         wprintf("';\n");
3334                         ++num_drop_targets;
3335                 }
3336         }
3337
3338         wprintf("num_drop_targets = %d;\n", num_drop_targets);
3339         if ((ChrPtr(WC->floordiv_expanded)[0] != '\0')&&
3340             (ChrPtr(WC->floordiv_expanded)[1] != '\0')){
3341                 wprintf("which_div_expanded = '%s';\n", ChrPtr(WC->floordiv_expanded));
3342         }
3343
3344         wprintf("\">\n");
3345         /** END: The old invisible pixel trick, to get our JavaScript to initialize */
3346 }
3347
3348
3349
3350 /**
3351  * \brief Burn the cached folder list.  
3352  * \param age How old the cahce needs to be before we burn it.
3353  */
3354
3355 void burn_folder_cache(time_t age)
3356 {
3357         /** If our cached folder list is very old, burn it. */
3358         if (WC->cache_fold != NULL) {
3359                 if ((time(NULL) - WC->cache_timestamp) > age) {
3360                         free(WC->cache_fold);
3361                         WC->cache_fold = NULL;
3362                 }
3363         }
3364 }
3365
3366
3367
3368
3369 /**
3370  * \brief Show the room list.  
3371  * (only should get called by
3372  * knrooms() because that's where output_headers() is called from)
3373  * \param viewpref the view preferences???
3374  */
3375
3376 void list_all_rooms_by_floor(const char *viewpref) {
3377         char buf[SIZ];
3378         int swap = 0;
3379         struct folder *fold = NULL;
3380         struct folder ftmp;
3381         int max_folders = 0;
3382         int alloc_folders = 0;
3383         int *floor_mapping;
3384         int IDMax;
3385         int i, j;
3386         int ShowEmptyFloors;
3387         int ra_flags = 0;
3388         int flags = 0;
3389         int num_floors = 1;     /** add an extra one for private folders */
3390         char buf3[SIZ];
3391         
3392         /** If our cached folder list is very old, burn it. */
3393         burn_folder_cache(300);
3394         
3395         /** Can we do the iconbar roomlist from cache? */
3396         if ((WC->cache_fold != NULL) && (!strcasecmp(viewpref, "iconbar"))) {
3397                 do_iconbar_view(WC->cache_fold, WC->cache_max_folders, WC->cache_num_floors);
3398                 return;
3399         }
3400
3401         /** Grab the floor table so we know how to build the list... */
3402         load_floorlist();
3403
3404         /** Start with the mailboxes */
3405         max_folders = 1;
3406         alloc_folders = 1;
3407         fold = malloc(sizeof(struct folder));
3408         memset(fold, 0, sizeof(struct folder));
3409         strcpy(fold[0].name, "My folders");
3410         fold[0].is_mailbox = 1;
3411
3412         /** Then add floors */
3413         serv_puts("LFLR");
3414         serv_getln(buf, sizeof buf);
3415         if (buf[0]=='1') while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
3416                 if (max_folders >= alloc_folders) {
3417                         alloc_folders = max_folders + 100;
3418                         fold = realloc(fold,
3419                                 alloc_folders * sizeof(struct folder));
3420                 }
3421                 memset(&fold[max_folders], 0, sizeof(struct folder));
3422                 extract_token(fold[max_folders].name, buf, 1, '|', sizeof fold[max_folders].name);
3423                 extract_token(buf3, buf, 0, '|', SIZ);
3424                 fold[max_folders].floor = atol (buf3);
3425                 ++max_folders;
3426                 ++num_floors;
3427         }
3428         IDMax = 0;
3429         for (i=0; i<num_floors; i++)
3430                 if (IDMax < fold[i].floor)
3431                         IDMax = fold[i].floor;
3432         floor_mapping = malloc (sizeof (int) * (IDMax + 1));
3433         memset (floor_mapping, 0, sizeof (int) * (IDMax + 1));
3434         for (i=0; i<num_floors; i++)
3435                 floor_mapping[fold[i].floor]=i;
3436         
3437         /** refresh the messages index for this room */
3438 //      serv_puts("GOTO ");
3439 //      while (serv_getln(buf, sizeof buf), strcmp(buf, "000"));
3440         /** Now add rooms */
3441         serv_puts("LKRA");
3442         serv_getln(buf, sizeof buf);
3443         if (buf[0]=='1') while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
3444                 if (max_folders >= alloc_folders) {
3445                         alloc_folders = max_folders + 100;
3446                         fold = realloc(fold,
3447                                 alloc_folders * sizeof(struct folder));
3448                 }
3449                 memset(&fold[max_folders], 0, sizeof(struct folder));
3450                 extract_token(fold[max_folders].room, buf, 0, '|', sizeof fold[max_folders].room);
3451                 ra_flags = extract_int(buf, 5);
3452                 flags = extract_int(buf, 1);
3453                 fold[max_folders].floor = extract_int(buf, 2);
3454                 fold[max_folders].hasnewmsgs =
3455                         ((ra_flags & UA_HASNEWMSGS) ? 1 : 0 );
3456                 if (flags & QR_MAILBOX) {
3457                         fold[max_folders].is_mailbox = 1;
3458                 }
3459                 fold[max_folders].view = extract_int(buf, 6);
3460                 room_to_folder(fold[max_folders].name,
3461                                 fold[max_folders].room,
3462                                 fold[max_folders].floor,
3463                                 fold[max_folders].is_mailbox);
3464                 fold[max_folders].selectable = 1;
3465                 /* Increase the room count for the associtaed floor */
3466                 if (fold[max_folders].is_mailbox) {
3467                         fold[0].num_rooms++;
3468                 }
3469                 else {
3470                         i = floor_mapping[fold[max_folders].floor];
3471                         fold[i].num_rooms++;
3472                 }
3473                 ++max_folders;
3474         }
3475         
3476         /*
3477          * Remove any floors that don't have rooms
3478          */
3479         get_pref_yesno("emptyfloors", &ShowEmptyFloors, 0);
3480         if (ShowEmptyFloors)
3481         {
3482                 for (i=0; i<num_floors; i++)
3483                 {
3484                         if (fold[i].num_rooms == 0) {
3485                                 for (j=i; j<max_folders; j++) {
3486                                         memcpy(&fold[j], &fold[j+1], sizeof(struct folder));
3487                                 }
3488                                 max_folders--;
3489                                 num_floors--;
3490                                 i--;
3491                         }
3492                 }
3493         }
3494         
3495         /** Bubble-sort the folder list */
3496         for (i=0; i<max_folders; ++i) {
3497                 for (j=0; j<(max_folders-1)-i; ++j) {
3498                         if (fold[j].is_mailbox == fold[j+1].is_mailbox) {
3499                                 swap = strcasecmp(fold[j].name, fold[j+1].name);
3500                         }
3501                         else {
3502                                 if ( (fold[j+1].is_mailbox)
3503                                    && (!fold[j].is_mailbox)) {
3504                                         swap = 1;
3505                                 }
3506                                 else {
3507                                         swap = 0;
3508                                 }
3509                         }
3510                         if (swap > 0) {
3511                                 memcpy(&ftmp, &fold[j], sizeof(struct folder));
3512                                 memcpy(&fold[j], &fold[j+1],
3513                                                         sizeof(struct folder));
3514                                 memcpy(&fold[j+1], &ftmp,
3515                                                         sizeof(struct folder));
3516                         }
3517                 }
3518         }
3519
3520
3521         if (!strcasecmp(viewpref, "folders")) {
3522                 do_folder_view(fold, max_folders, num_floors);
3523         }
3524         else if (!strcasecmp(viewpref, "hackish_view")) {
3525                 for (i=0; i<max_folders; ++i) {
3526                         escputs(fold[i].name);
3527                         wprintf("<br />\n");
3528                 }
3529         }
3530         else if (!strcasecmp(viewpref, "iconbar")) {
3531                 do_iconbar_view(fold, max_folders, num_floors);
3532         }
3533         else {
3534                 do_rooms_view(fold, max_folders, num_floors);
3535         }
3536
3537         /* Don't free the folder list ... cache it for future use! */
3538         if (WC->cache_fold != NULL) {
3539                 free(WC->cache_fold);
3540         }
3541         WC->cache_fold = fold;
3542         WC->cache_max_folders = max_folders;
3543         WC->cache_num_floors = num_floors;
3544         WC->cache_timestamp = time(NULL);
3545         free(floor_mapping);
3546 }
3547
3548
3549 /**
3550  * \brief Do either a known rooms list or a folders list, depending on the
3551  * user's preference
3552  */
3553 void knrooms(void)
3554 {
3555         StrBuf *ListView = NULL;
3556
3557         output_headers(1, 1, 2, 0, 0, 0);
3558
3559         /** Determine whether the user is trying to change views */
3560         if (havebstr("view")) {
3561                 ListView = NewStrBufPlain(bstr("view"), -1);
3562                 set_preference("roomlistview", ListView, 1);
3563         }
3564         /** Sanitize the input so its safe */
3565         if(!get_preference("roomlistview", &ListView) ||
3566            ((strcasecmp(ChrPtr(ListView), "folders") != 0) &&
3567             (strcasecmp(ChrPtr(ListView), "table") != 0))) 
3568         {
3569                 if (ListView == NULL) {
3570                         ListView = NewStrBufPlain("rooms", sizeof("rooms") - 1);
3571                         set_preference("roomlistview", ListView, 0);
3572                 }
3573                 else {
3574                         StrBufPrintf(ListView, "rooms");
3575                         save_preferences();
3576                 }
3577         }
3578
3579         /** title bar */
3580         wprintf("<div id=\"banner\">\n");
3581         wprintf("<div class=\"room_banner\">");
3582         wprintf("<h1>");
3583         if (!strcasecmp(ChrPtr(ListView), "rooms")) {
3584                 wprintf(_("Room list"));
3585         }
3586         else if (!strcasecmp(ChrPtr(ListView), "folders")) {
3587                 wprintf(_("Folder list"));
3588         }
3589         else if (!strcasecmp(ChrPtr(ListView), "table")) {
3590                 wprintf(_("Room list"));
3591         }
3592         wprintf("</h1></div>\n");
3593
3594         /** offer the ability to switch views */
3595         wprintf("<ul class=\"room_actions\">\n");
3596         wprintf("<li class=\"start_page\">");
3597         offer_start_page(NULL, 0, NULL, NULL, CTX_NONE);
3598         wprintf("</li>");
3599         wprintf("<li><form name=\"roomlistomatic\">\n"
3600                 "<select name=\"newview\" size=\"1\" "
3601                 "OnChange=\"location.href=roomlistomatic.newview.options"
3602                 "[selectedIndex].value\">\n");
3603
3604         wprintf("<option %s value=\"knrooms&view=rooms\">"
3605                 "View as room list"
3606                 "</option>\n",
3607                 ( !strcasecmp(ChrPtr(ListView), "rooms") ? "SELECTED" : "" )
3608         );
3609
3610         wprintf("<option %s value=\"knrooms&view=folders\">"
3611                 "View as folder list"
3612                 "</option>\n",
3613                 ( !strcasecmp(ChrPtr(ListView), "folders") ? "SELECTED" : "" )
3614         );
3615
3616         wprintf("</select>");
3617         wprintf("</form></li>");
3618         wprintf("</ul></div>\n");
3619
3620         wprintf("<div id=\"content\" class=\"service\">\n");
3621
3622         /** Display the room list in the user's preferred format */
3623         list_all_rooms_by_floor(ChrPtr(ListView));
3624         wDumpContent(1);
3625 }
3626
3627
3628
3629 /**
3630  * \brief Set the message expire policy for this room and/or floor
3631  */
3632 void set_room_policy(void) {
3633         char buf[SIZ];
3634
3635         if (!havebstr("ok_button")) {
3636                 strcpy(WC->ImportantMessage,
3637                         _("Cancelled.  Changes were not saved."));
3638                 display_editroom();
3639                 return;
3640         }
3641
3642         serv_printf("SPEX room|%d|%d", ibstr("roompolicy"), ibstr("roomvalue"));
3643         serv_getln(buf, sizeof buf);
3644         strcpy(WC->ImportantMessage, &buf[4]);
3645
3646         if (WC->axlevel >= 6) {
3647                 strcat(WC->ImportantMessage, "<br />\n");
3648                 serv_printf("SPEX floor|%d|%d", ibstr("floorpolicy"), ibstr("floorvalue"));
3649                 serv_getln(buf, sizeof buf);
3650                 strcat(WC->ImportantMessage, &buf[4]);
3651         }
3652
3653         display_editroom();
3654 }
3655
3656
3657 void tmplput_RoomName(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
3658 {
3659         StrBuf *tmp;
3660         tmp = NewStrBufPlain(WC->wc_roomname, -1);;
3661         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, tmp, 0);
3662         FreeStrBuf(&tmp);
3663 }
3664
3665 void _gotonext(void) { slrp_highest(); gotonext(); }
3666 void dotskip(void) {smart_goto(bstr("room"));}
3667 void _display_private(void) { display_private("", 0); }
3668 void dotgoto(void) {
3669         if (WC->wc_view != VIEW_MAILBOX) {      /* dotgoto acts like dotskip when we're in a mailbox view */
3670                 slrp_highest();
3671         }
3672         smart_goto(bstr("room"));
3673 }
3674
3675 void tmplput_roombanner(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
3676 {
3677         wprintf("<div id=\"banner\">\n");
3678         embed_room_banner(NULL, navbar_default);
3679         wprintf("</div>\n");
3680 }
3681
3682
3683 void tmplput_ungoto(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
3684 {
3685         struct wcsession *WCC = WC;
3686
3687         if ((WCC!=NULL) && 
3688             (!IsEmptyStr(WCC->ugname)))
3689                 StrBufAppendBufPlain(Target, WCC->ugname, -1, 0);
3690 }
3691
3692
3693 int ConditionalHaveUngoto(WCTemplateToken *Tokens, void *Context, int ContextType)
3694 {
3695         struct wcsession *WCC = WC;
3696         
3697         return ((WCC!=NULL) && 
3698                 (!IsEmptyStr(WCC->ugname)) && 
3699                 (strcasecmp(WCC->ugname, WCC->wc_roomname) == 0));
3700 }
3701
3702
3703
3704
3705 int ConditionalRoomHas_QR_PERMANENT(WCTemplateToken *Tokens, void *Context, int ContextType)
3706 {
3707         struct wcsession *WCC = WC;
3708         
3709         return ((WCC!=NULL) &&
3710                 ((WCC->room_flags & QR_PERMANENT) != 0));
3711 }
3712
3713 int ConditionalRoomHas_QR_INUSE(WCTemplateToken *Tokens, void *Context, int ContextType)
3714 {
3715         struct wcsession *WCC = WC;
3716         
3717         return ((WCC!=NULL) &&
3718                 ((WCC->room_flags & QR_INUSE) != 0));
3719 }
3720
3721 int ConditionalRoomHas_QR_PRIVATE(WCTemplateToken *Tokens, void *Context, int ContextType)
3722 {
3723         struct wcsession *WCC = WC;
3724         
3725         return ((WCC!=NULL) &&
3726                 ((WCC->room_flags & QR_PRIVATE) != 0));
3727 }
3728
3729 int ConditionalRoomHas_QR_PASSWORDED(WCTemplateToken *Tokens, void *Context, int ContextType)
3730 {
3731         struct wcsession *WCC = WC;
3732         
3733         return ((WCC!=NULL) &&
3734                 ((WCC->room_flags & QR_PASSWORDED) != 0));
3735 }
3736
3737 int ConditionalRoomHas_QR_GUESSNAME(WCTemplateToken *Tokens, void *Context, int ContextType)
3738 {
3739         struct wcsession *WCC = WC;
3740         
3741         return ((WCC!=NULL) &&
3742                 ((WCC->room_flags & QR_GUESSNAME) != 0));
3743 }
3744
3745 int ConditionalRoomHas_QR_DIRECTORY(WCTemplateToken *Tokens, void *Context, int ContextType)
3746 {
3747         struct wcsession *WCC = WC;
3748         
3749         return ((WCC!=NULL) &&
3750                 ((WCC->room_flags & QR_DIRECTORY) != 0));
3751 }
3752
3753 int ConditionalRoomHas_QR_UPLOAD(WCTemplateToken *Tokens, void *Context, int ContextType)
3754 {
3755         struct wcsession *WCC = WC;
3756         
3757         return ((WCC!=NULL) &&
3758                 ((WCC->room_flags & QR_UPLOAD) != 0));
3759 }
3760
3761 int ConditionalRoomHas_QR_DOWNLOAD(WCTemplateToken *Tokens, void *Context, int ContextType)
3762 {
3763         struct wcsession *WCC = WC;
3764         
3765         return ((WCC!=NULL) &&
3766                 ((WCC->room_flags & QR_DOWNLOAD) != 0));
3767 }
3768
3769 int ConditionalRoomHas_QR_VISDIR(WCTemplateToken *Tokens, void *Context, int ContextType)
3770 {
3771         struct wcsession *WCC = WC;
3772         
3773         return ((WCC!=NULL) &&
3774                 ((WCC->room_flags & QR_VISDIR) != 0));
3775 }
3776
3777 int ConditionalRoomHas_QR_ANONONLY(WCTemplateToken *Tokens, void *Context, int ContextType)
3778 {
3779         struct wcsession *WCC = WC;
3780         
3781         return ((WCC!=NULL) &&
3782                 ((WCC->room_flags & QR_ANONONLY) != 0));
3783 }
3784
3785 int ConditionalRoomHas_QR_ANONOPT(WCTemplateToken *Tokens, void *Context, int ContextType)
3786 {
3787         struct wcsession *WCC = WC;
3788         
3789         return ((WCC!=NULL) &&
3790                 ((WCC->room_flags & QR_ANONOPT) != 0));
3791 }
3792
3793 int ConditionalRoomHas_QR_NETWORK(WCTemplateToken *Tokens, void *Context, int ContextType)
3794 {
3795         struct wcsession *WCC = WC;
3796         
3797         return ((WCC!=NULL) &&
3798                 ((WCC->room_flags & QR_NETWORK) != 0));
3799 }
3800
3801 int ConditionalRoomHas_QR_PREFONLY(WCTemplateToken *Tokens, void *Context, int ContextType)
3802 {
3803         struct wcsession *WCC = WC;
3804         
3805         return ((WCC!=NULL) &&
3806                 ((WCC->room_flags & QR_PREFONLY) != 0));
3807 }
3808
3809 int ConditionalRoomHas_QR_READONLY(WCTemplateToken *Tokens, void *Context, int ContextType)
3810 {
3811         struct wcsession *WCC = WC;
3812         
3813         return ((WCC!=NULL) &&
3814                 ((WCC->room_flags & QR_READONLY) != 0));
3815 }
3816
3817 int ConditionalRoomHas_QR_MAILBOX(WCTemplateToken *Tokens, void *Context, int ContextType)
3818 {
3819         struct wcsession *WCC = WC;
3820         
3821         return ((WCC!=NULL) &&
3822                 ((WCC->room_flags & QR_MAILBOX) != 0));
3823 }
3824
3825
3826
3827
3828
3829
3830 int ConditionalHaveRoomeditRights(WCTemplateToken *Tokens, void *Context, int ContextType)
3831 {
3832         struct wcsession *WCC = WC;
3833
3834         return ( (WCC!= NULL) && 
3835                  ((WCC->axlevel >= 6) || 
3836                   (WCC->is_room_aide) || 
3837                   (WCC->is_mailbox) ));
3838 }
3839
3840 void 
3841 InitModule_ROOMOPS
3842 (void)
3843 {
3844         RegisterNamespace("ROOMNAME", 0, 1, tmplput_RoomName, 0);
3845
3846         WebcitAddUrlHandler(HKEY("knrooms"), knrooms, 0);
3847         WebcitAddUrlHandler(HKEY("gotonext"), _gotonext, 0);
3848         WebcitAddUrlHandler(HKEY("skip"), gotonext, 0);
3849         WebcitAddUrlHandler(HKEY("ungoto"), ungoto, 0);
3850         WebcitAddUrlHandler(HKEY("dotgoto"), dotgoto, 0);
3851         WebcitAddUrlHandler(HKEY("dotskip"), dotskip, 0);
3852         WebcitAddUrlHandler(HKEY("display_private"), _display_private, 0);
3853         WebcitAddUrlHandler(HKEY("goto_private"), goto_private, 0);
3854         WebcitAddUrlHandler(HKEY("zapped_list"), zapped_list, 0);
3855         WebcitAddUrlHandler(HKEY("display_zap"), display_zap, 0);
3856         WebcitAddUrlHandler(HKEY("zap"), zap, 0);
3857         WebcitAddUrlHandler(HKEY("display_entroom"), display_entroom, 0);
3858         WebcitAddUrlHandler(HKEY("entroom"), entroom, 0);
3859         WebcitAddUrlHandler(HKEY("display_whok"), display_whok, 0);
3860         WebcitAddUrlHandler(HKEY("do_invt_kick"), do_invt_kick, 0);
3861         WebcitAddUrlHandler(HKEY("display_editroom"), display_editroom, 0);
3862         WebcitAddUrlHandler(HKEY("netedit"), netedit, 0);
3863         WebcitAddUrlHandler(HKEY("editroom"), editroom, 0);
3864         WebcitAddUrlHandler(HKEY("delete_room"), delete_room, 0);
3865         WebcitAddUrlHandler(HKEY("set_room_policy"), set_room_policy, 0);
3866         WebcitAddUrlHandler(HKEY("set_floordiv_expanded"), set_floordiv_expanded, NEED_URL|AJAX);
3867         WebcitAddUrlHandler(HKEY("changeview"), change_view, 0);
3868         WebcitAddUrlHandler(HKEY("toggle_self_service"), toggle_self_service, 0);
3869         RegisterNamespace("ROOMBANNER", 0, 1, tmplput_roombanner, 0);
3870
3871         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_PERMANENT"), 0, ConditionalRoomHas_QR_PERMANENT, CTX_NONE);
3872         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_INUSE"), 0, ConditionalRoomHas_QR_INUSE, CTX_NONE);
3873         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_PRIVATE"), 0, ConditionalRoomHas_QR_PRIVATE, CTX_NONE);
3874         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_PASSWORDED"), 0, ConditionalRoomHas_QR_PASSWORDED, CTX_NONE);
3875         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_GUESSNAME"), 0, ConditionalRoomHas_QR_GUESSNAME, CTX_NONE);
3876         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_DIRECTORY"), 0, ConditionalRoomHas_QR_DIRECTORY, CTX_NONE);
3877         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_UPLOAD"), 0, ConditionalRoomHas_QR_UPLOAD, CTX_NONE);
3878         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_DOWNLOAD"), 0, ConditionalRoomHas_QR_DOWNLOAD, CTX_NONE);
3879         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_VISIDIR"), 0, ConditionalRoomHas_QR_VISDIR, CTX_NONE);
3880         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_ANONONLY"), 0, ConditionalRoomHas_QR_ANONONLY, CTX_NONE);
3881         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_ANONOPT"), 0, ConditionalRoomHas_QR_ANONOPT, CTX_NONE);
3882         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_NETWORK"), 0, ConditionalRoomHas_QR_NETWORK, CTX_NONE);
3883         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_PREFONLY"), 0, ConditionalRoomHas_QR_PREFONLY, CTX_NONE);
3884         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_READONLY"), 0, ConditionalRoomHas_QR_READONLY, CTX_NONE);
3885         RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_MAILBOX"), 0, ConditionalRoomHas_QR_MAILBOX, CTX_NONE);
3886
3887         RegisterConditional(HKEY("COND:UNGOTO"), 0, ConditionalHaveUngoto, CTX_NONE);
3888         RegisterConditional(HKEY("COND:ROOM:EDITACCESS"), 0, ConditionalHaveRoomeditRights, CTX_NONE);
3889
3890         RegisterNamespace("ROOM:UNGOTO", 0, 0, tmplput_ungoto, 0);
3891 }
3892
3893 /*@}*/