8e05a246888ee36337451054c4e8ae3cdc2a2a37
[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
10 char floorlist[MAX_FLOORS][SIZ];        /* list of our floor names */
11
12 /* See GetFloorListHash and GetRoomListHash for info on these.
13  * Basically we pull LFLR/LKRA etc. and set up a room HashList with these keys.
14  */
15
16 void display_whok(void);
17 int ConditionalHaveRoomeditRights(StrBuf *Target, WCTemplputParams *TP);
18
19
20 char *viewdefs[VIEW_MAX];                       /* the different kinds of available views */
21
22 ROOM_VIEWS exchangeable_views[VIEW_MAX][VIEW_MAX] = {   /* the different kinds of available views for a view */
23 {VIEW_BBS, VIEW_MAILBOX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
24 {VIEW_BBS, VIEW_MAILBOX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
25 {VIEW_MAX, VIEW_MAX, VIEW_ADDRESSBOOK, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
26 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX /*VIEW_CALBRIEF*/, VIEW_MAX, VIEW_MAX }, 
27 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_TASKS, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, },
28 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_NOTES, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, },
29 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_WIKI, VIEW_MAX, VIEW_MAX, VIEW_MAX}, 
30 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX/*VIEW_CALBRIEF*/, VIEW_MAX, VIEW_MAX},
31 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_JOURNAL, VIEW_MAX }, 
32 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_BLOG }, 
33         };
34 /* the brief calendar view is disabled: VIEW_CALBRIEF */
35
36 allowed_default_views[VIEW_MAX] = {
37         1, /* VIEW_BBS          Bulletin board view */
38         1, /* VIEW_MAILBOX              Mailbox summary */
39         1, /* VIEW_ADDRESSBOOK  Address book view */
40         1, /* VIEW_CALENDAR             Calendar view */
41         1, /* VIEW_TASKS                Tasks view */
42         1, /* VIEW_NOTES                Notes view */
43         1, /* VIEW_WIKI         Wiki view */
44         0, /* VIEW_CALBRIEF             Brief Calendar view */
45         0, /* VIEW_JOURNAL              Journal view */
46         0  /* VIEW_BLOG         Blog view (not yet implemented) */
47 };
48
49
50 /*
51  * Initialize the viewdefs with localized strings
52  */
53 void initialize_viewdefs(void) {
54         viewdefs[VIEW_BBS] = _("Bulletin Board");
55         viewdefs[VIEW_MAILBOX] = _("Mail Folder");
56         viewdefs[VIEW_ADDRESSBOOK] = _("Address Book");
57         viewdefs[VIEW_CALENDAR] = _("Calendar");
58         viewdefs[VIEW_TASKS] = _("Task List");
59         viewdefs[VIEW_NOTES] = _("Notes List");
60         viewdefs[VIEW_WIKI] = _("Wiki");
61         viewdefs[VIEW_CALBRIEF] = _("Calendar List");
62         viewdefs[VIEW_JOURNAL] = _("Journal");
63         viewdefs[VIEW_BLOG] = _("Blog");
64 }
65
66
67
68 /*
69  * load the list of floors
70  * /
71 void load_floorlist(StrBuf *Buf)
72 {
73         int a;
74         int Done = 0;
75
76         for (a = 0; a < MAX_FLOORS; ++a)
77                 floorlist[a][0] = 0;
78
79         serv_puts("LFLR");
80         StrBuf_ServGetln(Buf);
81         if (GetServerStatus(Buf, NULL) != 1) {
82                 strcpy(floorlist[0], "Main Floor");
83                 return;
84         }
85         while (!Done && (StrBuf_ServGetln(Buf)>=0)) {
86                 if ( (StrLength(Buf)==3) && 
87                      !strcmp(ChrPtr(Buf), "000")) {
88                         Done = 1;
89                         break;
90                 }
91                 extract_token(floorlist[StrBufExtract_int(Buf, 0, '|')], ChrPtr(Buf), 1, '|', sizeof floorlist[0]);
92         }
93 }
94 */
95
96
97 /*
98  * Embed the room banner
99  *
100  * got                  The information returned from a GOTO server command
101  * navbar_style         Determines which navigation buttons to display
102  *
103  */
104
105 void embed_room_banner(void) 
106 {
107         wcsession *WCC = WC;
108         char buf[256];
109
110         /* refresh current room states... */
111         /* dosen't work??? gotoroom(NULL); */
112
113         /* The browser needs some information for its own use */
114         wc_printf("<script type=\"text/javascript\">    \n"
115                   "     room_is_trash = %d;             \n"
116                   "</script>\n",
117                   ((WC->CurRoom.RAFlags & UA_ISTRASH) != 0)
118                 );
119
120         /*
121          * If the user happens to select the "make this my start page" link,
122          * we want it to remember the URL as a "/dotskip" one instead of
123          * a "skip" or "gotonext" or something like that.
124          */
125         if (WCC->Hdr->this_page == NULL) {
126                 WCC->Hdr->this_page = NewStrBuf();
127         }
128         StrBufPrintf(WCC->Hdr->this_page, 
129                      "dotskip?room=%s",
130                      ChrPtr(WC->CurRoom.name)
131                 );
132
133         do_template("roombanner", NULL);
134         /* roombanner contains this for mobile */
135         if (WC->is_mobile)
136                 return;
137
138
139         wc_printf("<div id=\"navbar\"><ul>");
140
141         wc_printf(
142                 "<li class=\"ungoto\">"
143                 "<a href=\"ungoto\">"
144                 "<img src=\"static/ungoto2_24x.gif\" alt=\"\" width=\"24\" height=\"24\">"
145                 "<span class=\"navbar_link\">%s</span></A>"
146                 "</li>\n", _("Ungoto")
147                 );
148         
149         if (WC->CurRoom.view == VIEW_BBS) {
150                 wc_printf(
151                         "<li class=\"newmess\">"
152                         "<a href=\"readnew\">"
153                         "<img src=\"static/newmess2_24x.gif\" alt=\"\" width=\"24\" height=\"24\">"
154                         "<span class=\"navbar_link\">%s</span></A>"
155                         "</li>\n", _("Read new messages")
156                         );
157         }
158
159         switch(WC->CurRoom.view) {
160         case VIEW_ADDRESSBOOK:
161                 wc_printf(
162                         "<li class=\"viewcontacts\">"
163                         "<a href=\"readfwd\">"
164                         "<img src=\"static/viewcontacts_24x.gif\" "
165                         "alt=\"\" width=\"24\" height=\"24\">"
166                         "<span class=\"navbar_link\">"
167                         "%s"
168                         "</span></a></li>\n", _("View contacts")
169                         );
170                 break;
171         case VIEW_CALENDAR:
172                 wc_printf(
173                         "<li class=\"staskday\">"
174                         "<a href=\"readfwd?calview=day\">"
175                         "<img src=\"static/taskday2_24x.gif\" "
176                         "alt=\"\" width=\"24\" height=\"24\">"
177                         "<span class=\"navbar_link\">"
178                         "%s"
179                         "</span></a></li>\n", _("Day view")
180                         );
181                 wc_printf(
182                         "<li class=\"monthview\">"
183                         "<a href=\"readfwd?calview=month\">"
184                         "<img src=\"static/monthview2_24x.gif\" "
185                         "alt=\"\" width=\"24\" height=\"24\">"
186                         "<span class=\"navbar_link\">"
187                         "%s"
188                         "</span></a></li>\n", _("Month view")
189                         );
190                 break;
191         case VIEW_CALBRIEF:
192                 wc_printf(
193                         "<li class=\"monthview\">"
194                         "<a href=\"readfwd?calview=month\">"
195                         "<img src=\"static/monthview2_24x.gif\" "
196                         "alt=\"\" width=\"24\" height=\"24\">"
197                         "<span class=\"navbar_link\">"
198                         "%s"
199                         "</span></a></li>\n", _("Calendar list")
200                         );
201                 break;
202         case VIEW_TASKS:
203                 wc_printf(
204                         "<li class=\"taskmanag\">"
205                         "<a href=\"readfwd\">"
206                         "<img src=\"static/taskmanag_24x.gif\" "
207                         "alt=\"\" width=\"24\" height=\"24\">"
208                         "<span class=\"navbar_link\">"
209                         "%s"
210                         "</span></a></li>\n", _("View tasks")
211                         );
212                 break;
213         case VIEW_NOTES:
214                 wc_printf(
215                         "<li class=\"viewnotes\">"
216                         "<a href=\"readfwd\">"
217                         "<img src=\"static/viewnotes_24x.gif\" "
218                         "alt=\"\" width=\"24\" height=\"24\">"
219                         "<span class=\"navbar_link\">"
220                         "%s"
221                         "</span></a></li>\n", _("View notes")
222                         );
223                 break;
224         case VIEW_MAILBOX:
225                 wc_printf(
226                         "<li class=\"readallmess\">"
227                         "<a id=\"m_refresh\" href=\"readfwd\">"
228                         "<img src=\"static/readallmess3_24x.gif\" "
229                         "alt=\"\" width=\"24\" height=\"24\">"
230                         "<span class=\"navbar_link\">"
231                         "%s"
232                         "</span></a></li>\n", _("Refresh message list")
233                         );
234                 break;
235         case VIEW_WIKI:
236                 wc_printf(
237                         "<li class=\"readallmess\">"
238                         "<a href=\"wiki?page=home\">"
239                         "<img src=\"static/readallmess3_24x.gif\" "
240                         "alt=\"\" width=\"24\" height=\"24\">"
241                         "<span class=\"navbar_link\">"
242                         "%s"
243                         "</span></a></li>\n", _("Wiki home")
244                         );
245                 break;
246         default:
247                 wc_printf(
248                         "<li class=\"readallmess\">"
249                         "<a href=\"readfwd\">"
250                         "<img src=\"static/readallmess3_24x.gif\" "
251                         "alt=\"\" width=\"24\" height=\"24\">"
252                         "<span class=\"navbar_link\">"
253                         "%s"
254                         "</span></a></li>\n", _("Read all messages")
255                         );
256                 break;
257         }
258         
259         switch(WC->CurRoom.view) {
260         case VIEW_ADDRESSBOOK:
261                 wc_printf(
262                         "<li class=\"addnewcontact\">"
263                         "<a href=\"display_enter\">"
264                         "<img src=\"static/addnewcontact_24x.gif\" "
265                         "alt=\"\" width=\"24\" height=\"24\">"
266                         "<span class=\"navbar_link\">"
267                         "%s"
268                         "</span></a></li>\n", _("Add new contact")
269                         );
270                 break;
271         case VIEW_CALENDAR:
272         case VIEW_CALBRIEF:
273                 wc_printf("<li class=\"addevent\"><a href=\"display_enter");
274                 if (havebstr("year" )) wc_printf("?year=%s", bstr("year"));
275                 if (havebstr("month")) wc_printf("?month=%s", bstr("month"));
276                 if (havebstr("day"  )) wc_printf("?day=%s", bstr("day"));
277                 wc_printf("\">"
278                           "<img  src=\"static/addevent_24x.gif\" "
279                           "alt=\"\" width=\"24\" height=\"24\">"
280                           "<span class=\"navbar_link\">"
281                           "%s"
282                           "</span></a></li>\n", _("Add new event")
283                         );
284                 break;
285         case VIEW_TASKS:
286                 wc_printf(
287                         "<li class=\"newmess\">"
288                         "<a href=\"display_enter\">"
289                         "<img  src=\"static/newmess3_24x.gif\" "
290                         "alt=\"\" width=\"24\" height=\"24\">"
291                         "<span class=\"navbar_link\">"
292                         "%s"
293                         "</span></a></li>\n", _("Add new task")
294                         );
295                 break;
296         case VIEW_NOTES:
297                 wc_printf(
298                         "<li class=\"enternewnote\">"
299                         "<a href=\"add_new_note\">"
300                         "<img  src=\"static/enternewnote_24x.gif\" "
301                         "alt=\"\" width=\"24\" height=\"24\">"
302                         "<span class=\"navbar_link\">"
303                         "%s"
304                         "</span></a></li>\n", _("Add new note")
305                         );
306                 break;
307         case VIEW_WIKI:
308                 safestrncpy(buf, bstr("page"), sizeof buf);
309                 if (IsEmptyStr(buf)) {
310                         safestrncpy(buf, "home", sizeof buf);
311                 }
312                 str_wiki_index(buf);
313                 wc_printf(
314                         "<li class=\"newmess\">"
315                         "<a href=\"display_enter?page=%s\">"
316                         "<img  src=\"static/newmess3_24x.gif\" "
317                         "alt=\"\" width=\"24\" height=\"24\">"
318                         "<span class=\"navbar_link\">"
319                         "%s"
320                         "</span></a></li>\n", buf, _("Edit this page")
321                         );
322                 
323                 if (bmstrcasestr((char *)ChrPtr(WCC->Hdr->HR.ReqLine), "wiki_history")) {
324                         /* already viewing history; display a link to the current page */
325                         wc_printf(
326                                 "<li class=\"newmess\">"
327                                 "<a href=\"wiki?page=%s\">"
328                                 "<img  src=\"static/newmess3_24x.gif\" "
329                                 "alt=\"\" width=\"24\" height=\"24\">"
330                                 "<span class=\"navbar_link\">"
331                                 "%s"
332                                 "</span></a></li>\n", buf, _("Current version")
333                                 );
334                 }
335                 else {
336                         /* display a link to the history */
337                         wc_printf(
338                                 "<li class=\"newmess\">"
339                                 "<a href=\"wiki_history?page=%s\">"
340                                 "<img  src=\"static/newmess3_24x.gif\" "
341                                 "alt=\"\" width=\"24\" height=\"24\">"
342                                 "<span class=\"navbar_link\">"
343                                 "%s"
344                                 "</span></a></li>\n", buf, _("History")
345                                 );
346                 }
347                 break;
348         case VIEW_MAILBOX:
349                 wc_printf(
350                         "<li class=\"newmess\">"
351                         "<a href=\"display_enter\">"
352                         "<img  src=\"static/newmess3_24x.gif\" "
353                         "alt=\"\" width=\"24\" height=\"24\">"
354                         "<span class=\"navbar_link\">"
355                         "%s"
356                         "</span></a></li>\n", _("Write mail")
357                         );
358                 wc_printf(
359                         "<li class=\"newmess\">"
360                         "<a href=\"javascript:deleteAllSelectedMessages();\">"
361                         "<img  src=\"static/delete.gif\" "
362                         "alt=\"\" width=\"24\" height=\"24\"><span class=\"navbar_link\">"
363                         "%s"
364                         "</span></a></li>\n", _("Delete")
365                         );
366                 break;
367         default:
368                 wc_printf(
369                         "<li class=\"newmess\">"
370                         "<a href=\"display_enter\">"
371                         "<img  src=\"static/newmess3_24x.gif\" "
372                         "alt=\"\" width=\"24\" height=\"24\">"
373                         "<span class=\"navbar_link\">"
374                         "%s"
375                         "</span></a></li>\n", _("Enter a message")
376                         );
377                 break;
378         }
379         
380         wc_printf(
381                 "<li class=\"skipthisroom\">"
382                 "<a href=\"skip\" "
383                 "title=\"%s\">"
384                 "<img  src=\"static/skipthisroom_24x.gif\" alt=\"\" "
385                 "width=\"24\" height=\"24\">"
386                 "<span class=\"navbar_link\">%s</span></a>"
387                 "</li>\n",
388                 _("Leave all messages marked as unread, go to next room with unread messages"),
389                 _("Skip this room")
390                 );
391         
392         wc_printf(
393                 "<li class=\"markngo\">"
394                 "<a href=\"gotonext\" "
395                 "title=\"%s\">"
396                 "<img  src=\"static/markngo_24x.gif\" alt=\"\" "
397                 "width=\"24\" height=\"24\">"
398                 "<span class=\"navbar_link\">%s</span></a>"
399                 "</li>\n",
400                 _("Mark all messages as read, go to next room with unread messages"),
401                 _("Goto next room")
402                 );
403         
404         wc_printf("</ul></div>\n");
405 }
406
407
408 /*
409  * back end routine to take the session to a new room
410  */
411 long gotoroom(const StrBuf *gname)
412 {
413         wcsession *WCC = WC;
414         StrBuf *Buf;
415         static long ls = (-1L);
416         long err = 0;
417
418         /* store ungoto information */
419         if (StrLength(gname) > 0)
420                 strcpy(WCC->ugname, ChrPtr(WCC->CurRoom.name));
421         WCC->uglsn = ls;
422         Buf = NewStrBuf();
423
424         /* move to the new room */
425         if (StrLength(gname) > 0)
426                 serv_printf("GOTO %s", ChrPtr(gname));
427         else /* or just refresh the current state... */
428                 serv_printf("GOTO 00000000000000000000");
429         StrBuf_ServGetln(Buf);
430         if  (GetServerStatus(Buf, &err) != 2) {
431                 serv_puts("GOTO _BASEROOM_");
432                 StrBuf_ServGetln(Buf);
433                 /* 
434                  * well, we know that this is the fallback case, 
435                  * but we're interested that the first command 
436                  * didn't work out in first place.
437                  */
438                 if (GetServerStatus(Buf, NULL) != 2) {
439                         FreeStrBuf(&Buf);
440                         return err;
441                 }
442         }
443         ParseGoto(&WCC->CurRoom, Buf);
444
445         if (StrLength(gname) > 0)
446         {
447                 remove_march(WCC->CurRoom.name);
448                 if (!strcasecmp(ChrPtr(gname), "_BASEROOM_"))
449                         remove_march(gname);
450         }
451         FreeStrBuf(&Buf);
452
453         return err;
454 }
455
456
457 void ParseGoto(folder *room, StrBuf *Line)
458 {
459         wcsession *WCC = WC;
460         const char *Pos;
461         int flag;
462         void *vFloor = NULL;
463         StrBuf *pBuf;
464
465         if (StrLength(Line) < 4) {
466                 return;
467         }
468         
469         /* ignore the commandstate... */
470         Pos = ChrPtr(Line) + 4;
471
472         if (room->RoomNameParts != NULL)
473         {
474                 int i;
475                 for (i=0; i < room->nRoomNameParts; i++)
476                         FreeStrBuf(&room->RoomNameParts[i]);
477                 free(room->RoomNameParts);
478                 room->RoomNameParts = NULL;
479         }
480
481         pBuf = room->name;  
482         if (pBuf == NULL)
483                 pBuf = NewStrBufPlain(NULL, StrLength(Line));
484         else
485                 FlushStrBuf(pBuf);
486         memset(room, 0, sizeof(folder));
487         room->name = pBuf;
488
489         StrBufExtract_NextToken(room->name, Line, &Pos, '|'); // WC->CurRoom->name
490
491         room->nNewMessages = StrBufExtractNext_long(Line, &Pos, '|'); 
492         if (room->nNewMessages > 0)
493                 room->RAFlags |= UA_HASNEWMSGS;
494
495         room->nTotalMessages = StrBufExtractNext_long(Line, &Pos, '|');
496
497         room->ShowInfo =  StrBufExtractNext_long(Line, &Pos, '|');
498         
499         room->QRFlags = StrBufExtractNext_long(Line, &Pos, '|'); //CurRoom->QRFlags
500
501         room->HighestRead = StrBufExtractNext_long(Line, &Pos, '|');
502         room->LastMessageRead = StrBufExtractNext_long(Line, &Pos, '|');
503
504         room->is_inbox = StrBufExtractNext_long(Line, &Pos, '|'); // is_mailbox
505
506         flag = StrBufExtractNext_long(Line, &Pos, '|');
507         if (WCC->is_aide || flag) {
508                 room->RAFlags |= UA_ADMINALLOWED;
509         }
510
511         room->UsersNewMAilboxMessages = StrBufExtractNext_long(Line, &Pos, '|');
512
513         room->floorid = StrBufExtractNext_int(Line, &Pos, '|'); // wc_floor
514
515         room->view = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->view
516
517         room->defview = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->defview
518
519         flag = StrBufExtractNext_long(Line, &Pos, '|');
520         if (flag)
521                 room->RAFlags |= UA_ISTRASH; // wc_is_trash
522
523         room->QRFlags2 = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->QRFlags2
524
525         /* find out, whether we are in a sub-room */
526         room->nRoomNameParts = StrBufNum_tokens(room->name, '\\');
527         if (room->nRoomNameParts > 1)
528         {
529                 int i;
530                 
531                 Pos = NULL;
532                 room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1));
533                 memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1));
534                 for (i=0; i < room->nRoomNameParts; i++)
535                 {
536                         room->RoomNameParts[i] = NewStrBuf();
537                         StrBufExtract_NextToken(room->RoomNameParts[i],
538                                                 room->name, &Pos, '\\');
539                 }
540         }
541
542         /* Private mailboxes on the main floor get remapped to the personal folder */
543         if ((room->QRFlags & QR_MAILBOX) && 
544             (room->floorid == 0))
545         {
546                 room->floorid = VIRTUAL_MY_FLOOR;
547                 if ((room->nRoomNameParts == 1) && 
548                     (StrLength(room->name) == 4) && 
549                     (strcmp(ChrPtr(room->name), "Mail") == 0))
550                 {
551                         room->is_inbox = 1;
552                 }
553                 
554         }
555         /* get a pointer to the floor we're on: */
556         if (WCC->Floors == NULL)
557                 GetFloorListHash(NULL, NULL);
558
559         GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
560         room->Floor = (const Floor*) vFloor;
561 }
562
563 void LoadRoomAide(void)
564 {
565         wcsession *WCC = WC;
566         StrBuf *Buf;
567         
568         if (WCC->CurRoom.RoomAideLoaded)
569                 return;
570
571         WCC->CurRoom.RoomAideLoaded = 1;
572         Buf = NewStrBuf();
573         serv_puts("GETA");
574         StrBuf_ServGetln(Buf);
575         if (GetServerStatus(Buf, NULL) != 2) {
576                 FlushStrBuf(WCC->CurRoom.RoomAide);
577                 AppendImportantMessage (ChrPtr(Buf) + 4, 
578                                         StrLength(Buf) - 4);
579         } else {
580                 const char *Pos;
581
582                 Pos = ChrPtr(Buf) + 4;
583
584                 FreeStrBuf(&WCC->CurRoom.RoomAide);
585                 WCC->CurRoom.RoomAide = NewStrBufPlain (NULL, StrLength (Buf));
586
587                 StrBufExtract_NextToken(WCC->CurRoom.RoomAide, Buf, &Pos, '|'); 
588         }
589         FreeStrBuf (&Buf);
590 }
591 void tmplput_CurrentRoomFloorName(StrBuf *Target, WCTemplputParams *TP) 
592 {
593         wcsession *WCC = WC;
594         folder *Folder = &WCC->CurRoom;
595         const Floor *pFloor = Folder->Floor;
596
597         if (pFloor == NULL)
598                 return;
599
600         StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
601 }
602
603 void tmplput_CurrentRoomAide(StrBuf *Target, WCTemplputParams *TP) 
604 {
605         wcsession *WCC = WC;
606
607         LoadRoomAide();
608
609         StrBufAppendTemplate(Target, TP, WCC->CurRoom.RoomAide, 0);
610 }
611
612
613 void LoadRoomXA (void)
614 {
615         wcsession *WCC = WC;
616         StrBuf *Buf;
617         
618         if (WCC->CurRoom.XALoaded)
619                 return;
620
621         WCC->CurRoom.XALoaded = 1;
622         Buf = NewStrBuf();
623         serv_puts("GETA");
624         StrBuf_ServGetln(Buf);
625         if (GetServerStatus(Buf, NULL) != 2) {
626                 FlushStrBuf(WCC->CurRoom.XAPass);
627                 FlushStrBuf(WCC->CurRoom.Directory);
628
629                 AppendImportantMessage (ChrPtr(Buf) + 4, 
630                                         StrLength(Buf) - 4);
631         } else {
632                 const char *Pos;
633
634                 Pos = ChrPtr(Buf) + 4;
635
636                 FreeStrBuf(&WCC->CurRoom.XAPass);
637                 FreeStrBuf(&WCC->CurRoom.Directory);
638
639                 WCC->CurRoom.XAPass = NewStrBufPlain (NULL, StrLength (Buf));
640                 WCC->CurRoom.Directory = NewStrBufPlain (NULL, StrLength (Buf));
641
642                 StrBufSkip_NTokenS(Buf, &Pos, '|', 1); /* The Name, we already know... */
643                 StrBufExtract_NextToken(WCC->CurRoom.XAPass, Buf, &Pos, '|'); 
644                 StrBufExtract_NextToken(WCC->CurRoom.Directory, Buf, &Pos, '|'); 
645                 StrBufSkip_NTokenS(Buf, &Pos, '|', 2); /* QRFlags, FloorNum we already know... */
646                 WCC->CurRoom.Order = StrBufExtractNext_long(Buf, &Pos, '|');
647                 /* defview, we already know you. */
648                 /* QR2Flags, we already know them... */
649
650         }
651         FreeStrBuf (&Buf);
652 }
653
654
655 void LoadXRoomPic(void)
656 {
657         wcsession *WCC = WC;
658         StrBuf *Buf;
659         
660         if (WCC->CurRoom.XHaveRoomPicLoaded)
661                 return;
662
663         WCC->CurRoom.XHaveRoomPicLoaded = 1;
664         Buf = NewStrBuf();
665         serv_puts("OIMG _roompic_");
666         StrBuf_ServGetln(Buf);
667         if (GetServerStatus(Buf, NULL) != 2) {
668                 WCC->CurRoom.XHaveRoomPic = 0;
669         } else {
670                 WCC->CurRoom.XHaveRoomPic = 1;
671         }
672         serv_puts("CLOS");
673         StrBuf_ServGetln(Buf);
674         GetServerStatus(Buf, NULL);
675         FreeStrBuf (&Buf);
676 }
677
678 int ConditionalThisRoomXHavePic(StrBuf *Target, WCTemplputParams *TP)
679 {
680         wcsession *WCC = WC;
681         
682         if (WCC == NULL)
683                 return 0;
684
685         LoadXRoomPic();
686         return WCC->CurRoom.XHaveRoomPic == 1;
687 }
688
689 void LoadXRoomInfoText(void)
690 {
691         wcsession *WCC = WC;
692         StrBuf *Buf;
693         int Done = 0;
694         
695         if (WCC->CurRoom.XHaveInfoTextLoaded)
696                 return;
697
698         WCC->CurRoom.XHaveInfoTextLoaded = 1;
699         Buf = NewStrBuf();
700
701         serv_puts("RINF");
702
703         StrBuf_ServGetln(Buf);
704         if (GetServerStatus(Buf, NULL) == 1) {
705                 WCC->CurRoom.XInfoText = NewStrBuf ();
706                 
707                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
708                         if ( (StrLength(Buf)==3) && 
709                              !strcmp(ChrPtr(Buf), "000")) 
710                                 Done = 1;
711                         else 
712                                 StrBufAppendBuf(WCC->CurRoom.XInfoText, Buf, 0);
713                 }
714         }
715
716         FreeStrBuf (&Buf);
717 }
718
719 int ConditionalThisRoomXHaveInfoText(StrBuf *Target, WCTemplputParams *TP)
720 {
721         wcsession *WCC = WC;
722         
723         if (WCC == NULL)
724                 return 0;
725
726         LoadXRoomInfoText();
727         return (StrLength(WCC->CurRoom.XInfoText)>0);
728 }
729
730 void tmplput_CurrentRoomInfoText(StrBuf *Target, WCTemplputParams *TP) 
731 {
732         wcsession *WCC = WC;
733
734         LoadXRoomInfoText();
735
736         StrBufAppendTemplate(Target, TP, WCC->CurRoom.XAPass, 1);
737 }
738
739 void LoadXRoomXCountFiles(void)
740 {
741         wcsession *WCC = WC;
742         StrBuf *Buf;
743         int Done = 0;
744         
745         if (WCC->CurRoom.XHaveDownloadCount)
746                 return;
747
748         WCC->CurRoom.XHaveDownloadCount = 1;
749
750         Buf = NewStrBuf();
751         serv_puts("RDIR");
752         StrBuf_ServGetln(Buf);
753         if (GetServerStatus(Buf, NULL) == 1) {
754                 
755                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
756                         if ( (StrLength(Buf)==3) && 
757                              !strcmp(ChrPtr(Buf), "000")) 
758                                 Done = 1;
759                         else 
760                                 WCC->CurRoom.XDownloadCount++;
761                 }
762         }
763
764         FreeStrBuf (&Buf);
765 }
766
767 void tmplput_CurrentRoomXNFiles(StrBuf *Target, WCTemplputParams *TP) 
768 {
769         wcsession *WCC = WC;
770
771         LoadXRoomXCountFiles();
772
773         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.XDownloadCount);
774 }
775
776 void tmplput_CurrentRoomX_FileString(StrBuf *Target, WCTemplputParams *TP) 
777 {
778         wcsession *WCC = WC;
779
780         LoadXRoomXCountFiles();
781
782         if (WCC->CurRoom.XDownloadCount == 1)
783                 StrBufAppendBufPlain(Target, _("file"), -1, 0);
784         else
785                 StrBufAppendBufPlain(Target, _("files"), -1, 0);
786 }
787
788 void tmplput_CurrentRoomPass(StrBuf *Target, WCTemplputParams *TP) 
789 {
790         wcsession *WCC = WC;
791
792         LoadRoomXA();
793
794         StrBufAppendTemplate(Target, TP, WCC->CurRoom.XAPass, 0);
795 }
796 void tmplput_CurrentRoomDirectory(StrBuf *Target, WCTemplputParams *TP) 
797 {
798         wcsession *WCC = WC;
799
800         LoadRoomXA();
801
802         StrBufAppendTemplate(Target, TP, WCC->CurRoom.Directory, 0);
803 }
804 void tmplput_CurrentRoomOrder(StrBuf *Target, WCTemplputParams *TP) 
805 {
806         wcsession *WCC = WC;
807
808         LoadRoomXA();
809
810         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.Order);
811 }
812 void tmplput_CurrentRoomDefView(StrBuf *Target, WCTemplputParams *TP) 
813 {
814         wcsession *WCC = WC;
815
816         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.defview);
817 }
818
819 void tmplput_CurrentRoom_nNewMessages(StrBuf *Target, WCTemplputParams *TP) 
820 {
821         wcsession *WCC = WC;
822
823         LoadRoomXA();
824
825         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.nNewMessages);
826 }
827
828 void tmplput_CurrentRoom_nTotalMessages(StrBuf *Target, WCTemplputParams *TP) 
829 {
830         wcsession *WCC = WC;
831
832         LoadRoomXA();
833
834         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.nTotalMessages);
835 }
836
837 int ConditionalThisRoomOrder(StrBuf *Target, WCTemplputParams *TP)
838 {
839         wcsession *WCC = WC;
840         long CheckThis;
841
842         if (WCC == NULL)
843                 return 0;
844
845         LoadRoomXA();
846
847         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
848         return CheckThis == WCC->CurRoom.Order;
849 }
850
851 int ConditionalThisRoomDefView(StrBuf *Target, WCTemplputParams *TP)
852 {
853         wcsession *WCC = WC;
854         long CheckThis;
855
856         if (WCC == NULL)
857                 return 0;
858
859         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
860         return CheckThis == WCC->CurRoom.defview;
861 }
862
863 int ConditionalThisRoomCurrView(StrBuf *Target, WCTemplputParams *TP)
864 {
865         wcsession *WCC = WC;
866         long CheckThis;
867
868         if (WCC == NULL)
869                 return 0;
870
871         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
872         return CheckThis == WCC->CurRoom.view;
873 }
874
875 int ConditionalThisRoomHaveView(StrBuf *Target, WCTemplputParams *TP)
876 {
877         wcsession *WCC = WC;
878         long CheckThis;
879         
880         if (WCC == NULL)
881                 return 0;
882
883         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
884         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
885         {
886                 LogTemplateError(Target, "Conditional", ERR_PARM2, TP,
887                                  "Roomview [%ld] not valid\n", 
888                                  CheckThis);
889                 return 0;
890         }
891
892         return exchangeable_views [WCC->CurRoom.defview][CheckThis] != VIEW_MAX;
893 }
894
895 void tmplput_CurrentRoomViewString(StrBuf *Target, WCTemplputParams *TP) 
896 {
897         wcsession *WCC = WC;
898         StrBuf *Buf;
899
900         if ((WCC == NULL) ||
901             (WCC->CurRoom.defview >= VIEW_MAX) || 
902             (WCC->CurRoom.defview < VIEW_BBS))
903         {
904                 LogTemplateError(Target, "Token", ERR_PARM2, TP,
905                                  "Roomview [%ld] not valid\n", 
906                                  (WCC != NULL)? 
907                                  WCC->CurRoom.defview : -1);
908                 return;
909         }
910
911         Buf = NewStrBufPlain(_(viewdefs[WCC->CurRoom.defview]), -1);
912         StrBufAppendTemplate(Target, TP, Buf, 0);
913         FreeStrBuf(&Buf);
914 }
915
916 void tmplput_RoomViewString(StrBuf *Target, WCTemplputParams *TP) 
917 {
918         long CheckThis;
919         StrBuf *Buf;
920
921         CheckThis = GetTemplateTokenNumber(Target, TP, 0, 0);
922         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
923         {
924                 LogTemplateError(Target, "Token", ERR_PARM2, TP,
925                                  "Roomview [%ld] not valid\n", 
926                                  CheckThis);
927                 return;
928         }
929
930         Buf = NewStrBufPlain(_(viewdefs[CheckThis]), -1);
931         StrBufAppendTemplate(Target, TP, Buf, 0);
932         FreeStrBuf(&Buf);
933 }
934
935
936 int ConditionalIsAllowedDefaultView(StrBuf *Target, WCTemplputParams *TP)
937 {
938         wcsession *WCC = WC;
939         long CheckThis;
940         
941         if (WCC == NULL)
942                 return 0;
943
944         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
945         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
946         {
947                 LogTemplateError(Target, "Conditional", ERR_PARM2, TP,
948                                  "Roomview [%ld] not valid\n", 
949                                  CheckThis);
950                 return 0;
951         }
952
953         return allowed_default_views[CheckThis] != 0;
954 }
955
956 /*
957  * goto next room
958  */
959 void smart_goto(const StrBuf *next_room) {
960         gotoroom(next_room);
961         readloop(readnew, eUseDefault);
962 }
963
964
965
966 /*
967  * mark all messages in current room as having been read
968  */
969 void slrp_highest(void)
970 {
971         char buf[256];
972
973         serv_puts("SLRP HIGHEST");
974         serv_getln(buf, sizeof buf);
975 }
976
977
978 typedef struct __room_states {
979         char password[SIZ];
980         char dirname[SIZ];
981         char name[SIZ];
982         int flags;
983         int floor;
984         int order;
985         int view;
986         int flags2;
987 } room_states;
988
989
990
991
992 /*
993  * Set/clear/read the "self-service list subscribe" flag for a room
994  * 
995  * set newval to 0 to clear, 1 to set, any other value to leave unchanged.
996  * returns the new value.
997  */
998
999 int self_service(int newval) {
1000         int current_value = 0;
1001         char buf[SIZ];
1002         
1003         char name[SIZ];
1004         char password[SIZ];
1005         char dirname[SIZ];
1006         int flags, floor, order, view, flags2;
1007
1008         serv_puts("GETR");
1009         serv_getln(buf, sizeof buf);
1010         if (buf[0] != '2') return(0);
1011
1012         extract_token(name, &buf[4], 0, '|', sizeof name);
1013         extract_token(password, &buf[4], 1, '|', sizeof password);
1014         extract_token(dirname, &buf[4], 2, '|', sizeof dirname);
1015         flags = extract_int(&buf[4], 3);
1016         floor = extract_int(&buf[4], 4);
1017         order = extract_int(&buf[4], 5);
1018         view = extract_int(&buf[4], 6);
1019         flags2 = extract_int(&buf[4], 7);
1020
1021         if (flags2 & QR2_SELFLIST) {
1022                 current_value = 1;
1023         }
1024         else {
1025                 current_value = 0;
1026         }
1027
1028         if (newval == 1) {
1029                 flags2 = flags2 | QR2_SELFLIST;
1030         }
1031         else if (newval == 0) {
1032                 flags2 = flags2 & ~QR2_SELFLIST;
1033         }
1034         else {
1035                 return(current_value);
1036         }
1037
1038         if (newval != current_value) {
1039                 serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1040                             name, password, dirname, flags,
1041                             floor, order, view, flags2);
1042                 serv_getln(buf, sizeof buf);
1043         }
1044
1045         return(newval);
1046
1047 }
1048
1049 int is_selflist(room_states *RoomFlags)
1050 {
1051         return ((RoomFlags->flags2 & QR2_SELFLIST) != 0);
1052 }
1053
1054 int is_publiclist(room_states *RoomFlags)
1055 {
1056         return ((RoomFlags->flags2 & QR2_SMTP_PUBLIC) != 0);
1057 }
1058
1059 int is_moderatedlist(room_states *RoomFlags)
1060 {
1061         return ((RoomFlags->flags2 & QR2_MODERATED) != 0);
1062 }
1063
1064 /*
1065  * Set/clear/read the "self-service list subscribe" flag for a room
1066  * 
1067  * set newval to 0 to clear, 1 to set, any other value to leave unchanged.
1068  * returns the new value.
1069  */
1070
1071 int get_roomflags(room_states *RoomOps) 
1072 {
1073         char buf[SIZ];
1074         
1075         serv_puts("GETR");
1076         serv_getln(buf, sizeof buf);
1077         if (buf[0] != '2') return(0);
1078
1079         extract_token(RoomOps->name, &buf[4], 0, '|', sizeof RoomOps->name);
1080         extract_token(RoomOps->password, &buf[4], 1, '|', sizeof RoomOps->password);
1081         extract_token(RoomOps->dirname, &buf[4], 2, '|', sizeof RoomOps->dirname);
1082         RoomOps->flags = extract_int(&buf[4], 3);
1083         RoomOps->floor = extract_int(&buf[4], 4);
1084         RoomOps->order = extract_int(&buf[4], 5);
1085         RoomOps->view = extract_int(&buf[4], 6);
1086         RoomOps->flags2 = extract_int(&buf[4], 7);
1087         return (1);
1088 }
1089
1090 int set_roomflags(room_states *RoomOps)
1091 {
1092         char buf[SIZ];
1093
1094         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1095                     RoomOps->name, 
1096                     RoomOps->password, 
1097                     RoomOps->dirname, 
1098                     RoomOps->flags,
1099                     RoomOps->floor, 
1100                     RoomOps->order, 
1101                     RoomOps->view, 
1102                     RoomOps->flags2);
1103         serv_getln(buf, sizeof buf);
1104         return (1);
1105 }
1106
1107
1108
1109
1110
1111
1112 /*
1113  * display the form for editing a room
1114  */
1115 void display_editroom(void)
1116 {
1117         char buf[SIZ];
1118         char cmd[1024];
1119         char node[256];
1120         char remote_room[128];
1121         char recp[1024];
1122         char er_name[128];
1123         char er_password[10];
1124         char er_dirname[15];
1125         char er_roomaide[26];
1126         unsigned er_flags;
1127         unsigned er_flags2;
1128         int er_floor;
1129         int i, j;
1130         char *tab;
1131         char *shared_with;
1132         char *not_shared_with = NULL;
1133         int roompolicy = 0;
1134         int roomvalue = 0;
1135         int floorpolicy = 0;
1136         int floorvalue = 0;
1137         char pop3_host[128];
1138         char pop3_user[32];
1139         int bg = 0;
1140
1141         tab = bstr("tab");
1142         if (IsEmptyStr(tab)) tab = "admin";
1143
1144 //      Buf = NewStrBuf();
1145 //      load_floorlist(Buf);
1146 //      FreeStrBuf(&Buf);
1147         output_headers(1, 1, 1, 0, 0, 0);
1148
1149         wc_printf("<div class=\"fix_scrollbar_bug\">");
1150
1151         wc_printf("<br />\n");
1152
1153         /* print the tabbed dialog */
1154         wc_printf("<div align=\"center\">");
1155         wc_printf("<table id=\"AdminTabs\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
1156                 "<tr align=\"center\" style=\"cursor:pointer\"><td>&nbsp;</td>"
1157                 );
1158
1159         wc_printf("<td class=\"");
1160         if (!strcmp(tab, "admin")) {
1161                 wc_printf(" tab_cell_label\">");
1162                 wc_printf(_("Administration"));
1163         }
1164         else {
1165                 wc_printf("< tab_cell_edit\"><a href=\"display_editroom?tab=admin\">");
1166                 wc_printf(_("Administration"));
1167                 wc_printf("</a>");
1168         }
1169         wc_printf("</td>\n");
1170         wc_printf("<td>&nbsp;</td>\n");
1171
1172         if ( ConditionalHaveRoomeditRights(NULL, NULL)) {
1173
1174                 wc_printf("<td class=\"");
1175                 if (!strcmp(tab, "config")) {
1176                         wc_printf(" tab_cell_label\">");
1177                         wc_printf(_("Configuration"));
1178                 }
1179                 else {
1180                         wc_printf(" tab_cell_edit\"><a href=\"display_editroom?tab=config\">");
1181                         wc_printf(_("Configuration"));
1182                         wc_printf("</a>");
1183                 }
1184                 wc_printf("</td>\n");
1185                 wc_printf("<td>&nbsp;</td>\n");
1186
1187                 wc_printf("<td class=\"");
1188                 if (!strcmp(tab, "expire")) {
1189                         wc_printf(" tab_cell_label\">");
1190                         wc_printf(_("Message expire policy"));
1191                 }
1192                 else {
1193                         wc_printf(" tab_cell_edit\"><a href=\"display_editroom?tab=expire\">");
1194                         wc_printf(_("Message expire policy"));
1195                         wc_printf("</a>");
1196                 }
1197                 wc_printf("</td>\n");
1198                 wc_printf("<td>&nbsp;</td>\n");
1199         
1200                 wc_printf("<td class=\"");
1201                 if (!strcmp(tab, "access")) {
1202                         wc_printf(" tab_cell_label\">");
1203                         wc_printf(_("Access controls"));
1204                 }
1205                 else {
1206                         wc_printf(" tab_cell_edit\"><a href=\"display_editroom?tab=access\">");
1207                         wc_printf(_("Access controls"));
1208                         wc_printf("</a>");
1209                 }
1210                 wc_printf("</td>\n");
1211                 wc_printf("<td>&nbsp;</td>\n");
1212
1213                 wc_printf("<td class=\"");
1214                 if (!strcmp(tab, "sharing")) {
1215                         wc_printf(" tab_cell_label\">");
1216                         wc_printf(_("Sharing"));
1217                 }
1218                 else {
1219                         wc_printf(" tab_cell_edit\"><a href=\"display_editroom?tab=sharing\">");
1220                         wc_printf(_("Sharing"));
1221                         wc_printf("</a>");
1222                 }
1223                 wc_printf("</td>\n");
1224                 wc_printf("<td>&nbsp;</td>\n");
1225
1226                 wc_printf("<td class=\"");
1227                 if (!strcmp(tab, "listserv")) {
1228                         wc_printf(" tab_cell_label\">");
1229                         wc_printf(_("Mailing list service"));
1230                 }
1231                 else {
1232                         wc_printf("< tab_cell_edit\"><a href=\"display_editroom?tab=listserv\">");
1233                         wc_printf(_("Mailing list service"));
1234                         wc_printf("</a>");
1235                 }
1236                 wc_printf("</td>\n");
1237                 wc_printf("<td>&nbsp;</td>\n");
1238
1239         }
1240
1241         wc_printf("<td class=\"");
1242         if (!strcmp(tab, "feeds")) {
1243                 wc_printf(" tab_cell_label\">");
1244                 wc_printf(_("Remote retrieval"));
1245         }
1246         else {
1247                 wc_printf("< tab_cell_edit\"><a href=\"display_editroom?tab=feeds\">");
1248                 wc_printf(_("Remote retrieval"));
1249                 wc_printf("</a>");
1250         }
1251         wc_printf("</td>\n");
1252         wc_printf("<td>&nbsp;</td>\n");
1253
1254         wc_printf("</tr></table>\n");
1255         wc_printf("</div>\n");
1256         /* end tabbed dialog */ 
1257
1258         wc_printf("<script type=\"text/javascript\">"
1259                 " Nifty(\"table#AdminTabs td\", \"small transparent top\");"
1260                 "</script>"
1261                 );
1262
1263         /* begin content of whatever tab is open now */
1264
1265         if (!strcmp(tab, "admin")) {
1266                 wc_printf("<div class=\"tabcontent\">");
1267                 wc_printf("<ul>"
1268                         "<li><a href=\"delete_room\" "
1269                         "onClick=\"return confirm('");
1270                 wc_printf(_("Are you sure you want to delete this room?"));
1271                 wc_printf("');\">\n");
1272                 wc_printf(_("Delete this room"));
1273                 wc_printf("</a>\n"
1274                         "<li><a href=\"display_editroompic?which_room=");
1275                 urlescputs(ChrPtr(WC->CurRoom.name));
1276                 wc_printf("\">\n");
1277                 wc_printf(_("Set or change the icon for this room's banner"));
1278                 wc_printf("</a>\n"
1279                         "<li><a href=\"display_editinfo\">\n");
1280                 wc_printf(_("Edit this room's Info file"));
1281                 wc_printf("</a>\n"
1282                         "</ul>");
1283                 wc_printf("</div>");
1284         }
1285
1286         if (!strcmp(tab, "config")) {
1287                 wc_printf("<div class=\"tabcontent\">");
1288                 serv_puts("GETR");
1289                 serv_getln(buf, sizeof buf);
1290
1291                 if (!strncmp(buf, "550", 3)) {
1292                         wc_printf("<br><br><div align=center>%s</div><br><br>\n",
1293                                 _("Higher access is required to access this function.")
1294                                 );
1295                 }
1296                 else if (buf[0] != '2') {
1297                         wc_printf("<br><br><div align=center>%s</div><br><br>\n", &buf[4]);
1298                 }
1299                 else {
1300                         extract_token(er_name, &buf[4], 0, '|', sizeof er_name);
1301                         extract_token(er_password, &buf[4], 1, '|', sizeof er_password);
1302                         extract_token(er_dirname, &buf[4], 2, '|', sizeof er_dirname);
1303                         er_flags = extract_int(&buf[4], 3);
1304                         er_floor = extract_int(&buf[4], 4);
1305                         er_flags2 = extract_int(&buf[4], 7);
1306         
1307                         wc_printf("<form method=\"POST\" action=\"editroom\">\n");
1308                         wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1309                 
1310                         wc_printf("<ul><li>");
1311                         wc_printf(_("Name of room: "));
1312                         wc_printf("<input type=\"text\" NAME=\"er_name\" VALUE=\"%s\" MAXLENGTH=\""ULONG_FMT"\">\n",
1313                                 er_name,
1314                                 (sizeof(er_name)-1)
1315                                 );
1316                 
1317                         wc_printf("<li>");
1318                         wc_printf(_("Resides on floor: "));
1319                         wc_printf("<select NAME=\"er_floor\" SIZE=\"1\"");
1320                         if (er_flags & QR_MAILBOX)
1321                                 wc_printf("disabled >\n");
1322                         for (i = 0; i < 128; ++i)
1323                                 if (!IsEmptyStr(floorlist[i])) {
1324                                         wc_printf("<OPTION ");
1325                                         if (i == er_floor )
1326                                                 wc_printf("SELECTED ");
1327                                         wc_printf("VALUE=\"%d\">", i);
1328                                         escputs(floorlist[i]);
1329                                         wc_printf("</OPTION>\n");
1330                                 }
1331                         wc_printf("</select>\n");
1332
1333                         wc_printf("<li>");
1334                         wc_printf(_("Type of room:"));
1335                         wc_printf("<ul>\n");
1336         
1337                         wc_printf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"public\" ");
1338                         if ((er_flags & (QR_PRIVATE + QR_MAILBOX)) == 0)
1339                                 wc_printf("CHECKED ");
1340                         wc_printf("OnChange=\""
1341                                 "       if (this.form.type[0].checked == true) {        "
1342                                 "               this.form.er_floor.disabled = false;    "
1343                                 "       }                                               "
1344                                 "\"> ");
1345                         wc_printf(_("Public (automatically appears to everyone)"));
1346                         wc_printf("\n");
1347         
1348                         wc_printf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"hidden\" ");
1349                         if ((er_flags & QR_PRIVATE) &&
1350                             (er_flags & QR_GUESSNAME))
1351                                 wc_printf("CHECKED ");
1352                         wc_printf(" OnChange=\""
1353                                 "       if (this.form.type[1].checked == true) {        "
1354                                 "               this.form.er_floor.disabled = false;    "
1355                                 "       }                                               "
1356                                 "\"> ");
1357                         wc_printf(_("Private - hidden (accessible to anyone who knows its name)"));
1358                 
1359                         wc_printf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"passworded\" ");
1360                         if ((er_flags & QR_PRIVATE) &&
1361                             (er_flags & QR_PASSWORDED))
1362                                 wc_printf("CHECKED ");
1363                         wc_printf(" OnChange=\""
1364                                 "       if (this.form.type[2].checked == true) {        "
1365                                 "               this.form.er_floor.disabled = false;    "
1366                                 "       }                                               "
1367                                 "\"> ");
1368                         wc_printf(_("Private - require password: "));
1369                         wc_printf("\n<input type=\"text\" NAME=\"er_password\" VALUE=\"%s\" MAXLENGTH=\"9\">\n",
1370                                 er_password);
1371                 
1372                         wc_printf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"invonly\" ");
1373                         if ((er_flags & QR_PRIVATE)
1374                             && ((er_flags & QR_GUESSNAME) == 0)
1375                             && ((er_flags & QR_PASSWORDED) == 0))
1376                                 wc_printf("CHECKED ");
1377                         wc_printf(" OnChange=\""
1378                                 "       if (this.form.type[3].checked == true) {        "
1379                                 "               this.form.er_floor.disabled = false;    "
1380                                 "       }                                               "
1381                                 "\"> ");
1382                         wc_printf(_("Private - invitation only"));
1383                 
1384                         wc_printf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"personal\" ");
1385                         if (er_flags & QR_MAILBOX)
1386                                 wc_printf("CHECKED ");
1387                         wc_printf (" OnChange=\""
1388                                  "      if (this.form.type[4].checked == true) {        "
1389                                  "              this.form.er_floor.disabled = true;     "
1390                                  "      }                                               "
1391                                  "\"> ");
1392                         wc_printf(_("Personal (mailbox for you only)"));
1393                         
1394                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"bump\" VALUE=\"yes\" ");
1395                         wc_printf("> ");
1396                         wc_printf(_("If private, cause current users to forget room"));
1397                 
1398                         wc_printf("\n</ul>\n");
1399                 
1400                         wc_printf("<li><input type=\"checkbox\" NAME=\"prefonly\" VALUE=\"yes\" ");
1401                         if (er_flags & QR_PREFONLY)
1402                                 wc_printf("CHECKED ");
1403                         wc_printf("> ");
1404                         wc_printf(_("Preferred users only"));
1405                 
1406                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"readonly\" VALUE=\"yes\" ");
1407                         if (er_flags & QR_READONLY)
1408                                 wc_printf("CHECKED ");
1409                         wc_printf("> ");
1410                         wc_printf(_("Read-only room"));
1411                 
1412                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"collabdel\" VALUE=\"yes\" ");
1413                         if (er_flags2 & QR2_COLLABDEL)
1414                                 wc_printf("CHECKED ");
1415                         wc_printf("> ");
1416                         wc_printf(_("All users allowed to post may also delete messages"));
1417                 
1418                         /** directory stuff */
1419                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"directory\" VALUE=\"yes\" ");
1420                         if (er_flags & QR_DIRECTORY)
1421                                 wc_printf("CHECKED ");
1422                         wc_printf("> ");
1423                         wc_printf(_("File directory room"));
1424         
1425                         wc_printf("\n<ul><li>");
1426                         wc_printf(_("Directory name: "));
1427                         wc_printf("<input type=\"text\" NAME=\"er_dirname\" VALUE=\"%s\" MAXLENGTH=\"14\">\n",
1428                                 er_dirname);
1429         
1430                         wc_printf("<li><input type=\"checkbox\" NAME=\"ulallowed\" VALUE=\"yes\" ");
1431                         if (er_flags & QR_UPLOAD)
1432                                 wc_printf("CHECKED ");
1433                         wc_printf("> ");
1434                         wc_printf(_("Uploading allowed"));
1435                 
1436                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"dlallowed\" VALUE=\"yes\" ");
1437                         if (er_flags & QR_DOWNLOAD)
1438                                 wc_printf("CHECKED ");
1439                         wc_printf("> ");
1440                         wc_printf(_("Downloading allowed"));
1441                 
1442                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"visdir\" VALUE=\"yes\" ");
1443                         if (er_flags & QR_VISDIR)
1444                                 wc_printf("CHECKED ");
1445                         wc_printf("> ");
1446                         wc_printf(_("Visible directory"));
1447                         wc_printf("</ul>\n");
1448                 
1449                         /** end of directory stuff */
1450         
1451                         wc_printf("<li><input type=\"checkbox\" NAME=\"network\" VALUE=\"yes\" ");
1452                         if (er_flags & QR_NETWORK)
1453                                 wc_printf("CHECKED ");
1454                         wc_printf("> ");
1455                         wc_printf(_("Network shared room"));
1456         
1457                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"permanent\" VALUE=\"yes\" ");
1458                         if (er_flags & QR_PERMANENT)
1459                                 wc_printf("CHECKED ");
1460                         wc_printf("> ");
1461                         wc_printf(_("Permanent (does not auto-purge)"));
1462         
1463                         wc_printf("\n<li><input type=\"checkbox\" NAME=\"subjectreq\" VALUE=\"yes\" ");
1464                         if (er_flags2 & QR2_SUBJECTREQ)
1465                                 wc_printf("CHECKED ");
1466                         wc_printf("> ");
1467                         wc_printf(_("Subject Required (Force users to specify a message subject)"));
1468         
1469                         /** start of anon options */
1470                 
1471                         wc_printf("\n<li>");
1472                         wc_printf(_("Anonymous messages"));
1473                         wc_printf("<ul>\n");
1474                 
1475                         wc_printf("<li><input type=\"radio\" NAME=\"anon\" VALUE=\"no\" ");
1476                         if (((er_flags & QR_ANONONLY) == 0)
1477                             && ((er_flags & QR_ANONOPT) == 0))
1478                                 wc_printf("CHECKED ");
1479                         wc_printf("> ");
1480                         wc_printf(_("No anonymous messages"));
1481         
1482                         wc_printf("\n<li><input type=\"radio\" NAME=\"anon\" VALUE=\"anononly\" ");
1483                         if (er_flags & QR_ANONONLY)
1484                                 wc_printf("CHECKED ");
1485                         wc_printf("> ");
1486                         wc_printf(_("All messages are anonymous"));
1487                 
1488                         wc_printf("\n<li><input type=\"radio\" NAME=\"anon\" VALUE=\"anon2\" ");
1489                         if (er_flags & QR_ANONOPT)
1490                                 wc_printf("CHECKED ");
1491                         wc_printf("> ");
1492                         wc_printf(_("Prompt user when entering messages"));
1493                         wc_printf("</ul>\n");
1494                 
1495                         /* end of anon options */
1496                 
1497                         wc_printf("<li>");
1498                         wc_printf(_("Room aide: "));
1499                         serv_puts("GETA");
1500                         serv_getln(buf, sizeof buf);
1501                         if (buf[0] != '2') {
1502                                 wc_printf("<em>%s</em>\n", &buf[4]);
1503                         } else {
1504                                 extract_token(er_roomaide, &buf[4], 0, '|', sizeof er_roomaide);
1505                                 wc_printf("<input type=\"text\" NAME=\"er_roomaide\" VALUE=\"%s\" MAXLENGTH=\"25\">\n", er_roomaide);
1506                         }
1507                 
1508                         wc_printf("</ul><CENTER>\n");
1509                         wc_printf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"config\">\n"
1510                                 "<input type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">"
1511                                 "&nbsp;"
1512                                 "<input type=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">"
1513                                 "</CENTER>\n",
1514                                 _("Save changes"),
1515                                 _("Cancel")
1516                                 );
1517                 }
1518                 wc_printf("</div>");
1519         }
1520
1521
1522         /* Sharing the room with other Citadel nodes... */
1523         if (!strcmp(tab, "sharing")) {
1524                 wc_printf("<div class=\"tabcontent\">");
1525
1526                 shared_with = strdup("");
1527                 not_shared_with = strdup("");
1528
1529                 /** Learn the current configuration */
1530                 serv_puts("CONF getsys|application/x-citadel-ignet-config");
1531                 serv_getln(buf, sizeof buf);
1532                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1533                                 extract_token(node, buf, 0, '|', sizeof node);
1534                                 not_shared_with = realloc(not_shared_with,
1535                                                           strlen(not_shared_with) + 32);
1536                                 strcat(not_shared_with, node);
1537                                 strcat(not_shared_with, "\n");
1538                         }
1539
1540                 serv_puts("GNET");
1541                 serv_getln(buf, sizeof buf);
1542                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1543                                 extract_token(cmd, buf, 0, '|', sizeof cmd);
1544                                 extract_token(node, buf, 1, '|', sizeof node);
1545                                 extract_token(remote_room, buf, 2, '|', sizeof remote_room);
1546                                 if (!strcasecmp(cmd, "ignet_push_share")) {
1547                                         shared_with = realloc(shared_with,
1548                                                               strlen(shared_with) + 32);
1549                                         strcat(shared_with, node);
1550                                         if (!IsEmptyStr(remote_room)) {
1551                                                 strcat(shared_with, "|");
1552                                                 strcat(shared_with, remote_room);
1553                                         }
1554                                         strcat(shared_with, "\n");
1555                                 }
1556                         }
1557
1558                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1559                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1560                         extract_token(node, buf, 0, '|', sizeof node);
1561                         for (j=0; j<num_tokens(not_shared_with, '\n'); ++j) {
1562                                 extract_token(cmd, not_shared_with, j, '\n', sizeof cmd);
1563                                 if (!strcasecmp(node, cmd)) {
1564                                         remove_token(not_shared_with, j, '\n');
1565                                 }
1566                         }
1567                 }
1568
1569                 /* Display the stuff */
1570                 wc_printf("<CENTER><br />"
1571                         "<table border=1 cellpadding=5><tr>"
1572                         "<td><B><I>");
1573                 wc_printf(_("Shared with"));
1574                 wc_printf("</I></B></td>"
1575                         "<td><B><I>");
1576                 wc_printf(_("Not shared with"));
1577                 wc_printf("</I></B></td></tr>\n"
1578                         "<tr><td VALIGN=TOP>\n");
1579
1580                 wc_printf("<table border=0 cellpadding=5><tr class=\"tab_cell\"><td>");
1581                 wc_printf(_("Remote node name"));
1582                 wc_printf("</td><td>");
1583                 wc_printf(_("Remote room name"));
1584                 wc_printf("</td><td>");
1585                 wc_printf(_("Actions"));
1586                 wc_printf("</td></tr>\n");
1587
1588                 for (i=0; i<num_tokens(shared_with, '\n'); ++i) {
1589                         extract_token(buf, shared_with, i, '\n', sizeof buf);
1590                         extract_token(node, buf, 0, '|', sizeof node);
1591                         extract_token(remote_room, buf, 1, '|', sizeof remote_room);
1592                         if (!IsEmptyStr(node)) {
1593                                 wc_printf("<form method=\"POST\" action=\"netedit\">");
1594                                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1595                                 wc_printf("<tr><td>%s</td>\n", node);
1596
1597                                 wc_printf("<td>");
1598                                 if (!IsEmptyStr(remote_room)) {
1599                                         escputs(remote_room);
1600                                 }
1601                                 wc_printf("</td>");
1602
1603                                 wc_printf("<td>");
1604                 
1605                                 wc_printf("<input type=\"hidden\" NAME=\"line\" "
1606                                         "VALUE=\"ignet_push_share|");
1607                                 urlescputs(node);
1608                                 if (!IsEmptyStr(remote_room)) {
1609                                         wc_printf("|");
1610                                         urlescputs(remote_room);
1611                                 }
1612                                 wc_printf("\">");
1613                                 wc_printf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"sharing\">\n");
1614                                 wc_printf("<input type=\"hidden\" NAME=\"cmd\" VALUE=\"remove\">\n");
1615                                 wc_printf("<input type=\"submit\" "
1616                                         "NAME=\"unshare_button\" VALUE=\"%s\">", _("Unshare"));
1617                                 wc_printf("</td></tr></form>\n");
1618                         }
1619                 }
1620
1621                 wc_printf("</table>\n");
1622                 wc_printf("</td><td VALIGN=TOP>\n");
1623                 wc_printf("<table border=0 cellpadding=5><tr class=\"tab_cell\"><td>");
1624                 wc_printf(_("Remote node name"));
1625                 wc_printf("</td><td>");
1626                 wc_printf(_("Remote room name"));
1627                 wc_printf("</td><td>");
1628                 wc_printf(_("Actions"));
1629                 wc_printf("</td></tr>\n");
1630
1631                 for (i=0; i<num_tokens(not_shared_with, '\n'); ++i) {
1632                         extract_token(node, not_shared_with, i, '\n', sizeof node);
1633                         if (!IsEmptyStr(node)) {
1634                                 wc_printf("<form method=\"POST\" action=\"netedit\">");
1635                                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1636                                 wc_printf("<tr><td>");
1637                                 escputs(node);
1638                                 wc_printf("</td><td>"
1639                                         "<input type=\"INPUT\" "
1640                                         "NAME=\"suffix\" "
1641                                         "MAXLENGTH=128>"
1642                                         "</td><td>");
1643                                 wc_printf("<input type=\"hidden\" "
1644                                         "NAME=\"line\" "
1645                                         "VALUE=\"ignet_push_share|");
1646                                 urlescputs(node);
1647                                 wc_printf("|\">");
1648                                 wc_printf("<input type=\"hidden\" NAME=\"tab\" "
1649                                         "VALUE=\"sharing\">\n");
1650                                 wc_printf("<input type=\"hidden\" NAME=\"cmd\" "
1651                                         "VALUE=\"add\">\n");
1652                                 wc_printf("<input type=\"submit\" "
1653                                         "NAME=\"add_button\" VALUE=\"%s\">", _("Share"));
1654                                 wc_printf("</td></tr></form>\n");
1655                         }
1656                 }
1657
1658                 wc_printf("</table>\n");
1659                 wc_printf("</td></tr>"
1660                         "</table></CENTER><br />\n"
1661                         "<I><B>%s</B><ul><li>", _("Notes:"));
1662                 wc_printf(_("When sharing a room, "
1663                           "it must be shared from both ends.  Adding a node to "
1664                           "the 'shared' list sends messages out, but in order to"
1665                           " receive messages, the other nodes must be configured"
1666                           " to send messages out to your system as well. "
1667                           "<li>If the remote room name is blank, it is assumed "
1668                           "that the room name is identical on the remote node."
1669                           "<li>If the remote room name is different, the remote "
1670                           "node must also configure the name of the room here."
1671                           "</ul></I><br />\n"
1672                                 ));
1673
1674                 wc_printf("</div>");
1675         }
1676
1677         if (not_shared_with != NULL)
1678                 free (not_shared_with);
1679
1680         /* Mailing list management */
1681         if (!strcmp(tab, "listserv")) {
1682                 room_states RoomFlags;
1683                 wc_printf("<div class=\"tabcontent\">");
1684
1685                 wc_printf("<br /><center>"
1686                         "<table BORDER=0 WIDTH=100%% CELLPADDING=5>"
1687                         "<tr><td VALIGN=TOP>");
1688
1689                 wc_printf(_("<i>The contents of this room are being "
1690                           "mailed <b>as individual messages</b> "
1691                           "to the following list recipients:"
1692                           "</i><br /><br />\n"));
1693
1694                 serv_puts("GNET");
1695                 serv_getln(buf, sizeof buf);
1696                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1697                                 extract_token(cmd, buf, 0, '|', sizeof cmd);
1698                                 if (!strcasecmp(cmd, "listrecp")) {
1699                                         extract_token(recp, buf, 1, '|', sizeof recp);
1700                         
1701                                         escputs(recp);
1702                                         wc_printf(" <a href=\"netedit?cmd=remove?tab=listserv?line=listrecp|");
1703                                         urlescputs(recp);
1704                                         wc_printf("\">");
1705                                         wc_printf(_("(remove)"));
1706                                         wc_printf("</A><br />");
1707                                 }
1708                         }
1709                 wc_printf("<br /><form method=\"POST\" action=\"netedit\">\n"
1710                         "<input type=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1711                         "<input type=\"hidden\" NAME=\"prefix\" VALUE=\"listrecp|\">\n");
1712                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1713                 wc_printf("<input type=\"text\" id=\"add_as_listrecp\" NAME=\"line\">\n");
1714                 wc_printf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1715                 wc_printf("</form>\n");
1716
1717                 wc_printf("</td><td VALIGN=TOP>\n");
1718                 
1719                 wc_printf(_("<i>The contents of this room are being "
1720                           "mailed <b>in digest form</b> "
1721                           "to the following list recipients:"
1722                           "</i><br /><br />\n"));
1723
1724                 serv_puts("GNET");
1725                 serv_getln(buf, sizeof buf);
1726                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1727                                 extract_token(cmd, buf, 0, '|', sizeof cmd);
1728                                 if (!strcasecmp(cmd, "digestrecp")) {
1729                                         extract_token(recp, buf, 1, '|', sizeof recp);
1730                         
1731                                         escputs(recp);
1732                                         wc_printf(" <a href=\"netedit?cmd=remove?tab=listserv?line="
1733                                                 "digestrecp|");
1734                                         urlescputs(recp);
1735                                         wc_printf("\">");
1736                                         wc_printf(_("(remove)"));
1737                                         wc_printf("</A><br />");
1738                                 }
1739                         }
1740                 wc_printf("<br /><form method=\"POST\" action=\"netedit\">\n"
1741                         "<input type=\"hidden\" NAME=\"tab\" VALUE=\"listserv\">\n"
1742                         "<input type=\"hidden\" NAME=\"prefix\" VALUE=\"digestrecp|\">\n");
1743                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1744                 wc_printf("<input type=\"text\" id=\"add_as_digestrecp\" NAME=\"line\">\n");
1745                 wc_printf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1746                 wc_printf("</form>\n");
1747                 
1748                 wc_printf("</td></tr></table>\n");
1749
1750                 /** Pop open an address book -- begin **/
1751                 wc_printf("<div align=right>"
1752                         "<a href=\"javascript:PopOpenAddressBook('add_as_listrecp|%s|add_as_digestrecp|%s');\" "
1753                         "title=\"%s\">"
1754                         "<img align=middle border=0 width=24 height=24 src=\"static/viewcontacts_24x.gif\">"
1755                         "&nbsp;%s</a>"
1756                         "</div>",
1757                         _("List"),
1758                         _("Digest"),
1759                         _("Add recipients from Contacts or other address books"),
1760                         _("Add recipients from Contacts or other address books")
1761                         );
1762                 /* Pop open an address book -- end **/
1763
1764                 wc_printf("<br />\n<form method=\"GET\" action=\"toggle_self_service\">\n");
1765
1766                 get_roomflags (&RoomFlags);
1767                 
1768                 /* Self Service subscription? */
1769                 wc_printf("<table><tr><td>\n");
1770                 wc_printf(_("Allow self-service subscribe/unsubscribe requests."));
1771                 wc_printf("</td><td><input type=\"checkbox\" name=\"QR2_SelfList\" value=\"yes\" %s></td></tr>\n"
1772                         " <tr><td colspan=\"2\">\n",
1773                         (is_selflist(&RoomFlags))?"checked":"");
1774                 wc_printf(_("The URL for subscribe/unsubscribe is: "));
1775                 wc_printf("<TT>%s://%s/listsub</TT></td></tr>\n",
1776                         (is_https ? "https" : "http"),
1777                         ChrPtr(WC->Hdr->HR.http_host));
1778                 /* Public posting? */
1779                 wc_printf("<tr><td>");
1780                 wc_printf(_("Allow non-subscribers to mail to this room."));
1781                 wc_printf("</td><td><input type=\"checkbox\" name=\"QR2_SubsOnly\" value=\"yes\" %s></td></tr>\n",
1782                         (is_publiclist(&RoomFlags))?"checked":"");
1783                 
1784                 /* Moderated List? */
1785                 wc_printf("<tr><td>");
1786                 wc_printf(_("Room post publication needs Aide permission."));
1787                 wc_printf("</td><td><input type=\"checkbox\" name=\"QR2_Moderated\" value=\"yes\" %s></td></tr>\n",
1788                         (is_moderatedlist(&RoomFlags))?"checked":"");
1789
1790
1791                 wc_printf("<tr><td colspan=\"2\" align=\"center\">"
1792                         "<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\"></td></tr>", _("Save changes"));
1793                 wc_printf("</table></form>");
1794                         
1795
1796                 wc_printf("</CENTER>\n");
1797                 wc_printf("</div>");
1798         }
1799
1800
1801         /* Configuration of The Dreaded Auto-Purger */
1802         if (!strcmp(tab, "expire")) {
1803                 wc_printf("<div class=\"tabcontent\">");
1804
1805                 serv_puts("GPEX room");
1806                 serv_getln(buf, sizeof buf);
1807                 if (!strncmp(buf, "550", 3)) {
1808                         wc_printf("<br><br><div align=center>%s</div><br><br>\n",
1809                                 _("Higher access is required to access this function.")
1810                                 );
1811                 }
1812                 else if (buf[0] != '2') {
1813                         wc_printf("<br><br><div align=center>%s</div><br><br>\n", &buf[4]);
1814                 }
1815                 else {
1816                         roompolicy = extract_int(&buf[4], 0);
1817                         roomvalue = extract_int(&buf[4], 1);
1818                 
1819                         serv_puts("GPEX floor");
1820                         serv_getln(buf, sizeof buf);
1821                         if (buf[0] == '2') {
1822                                 floorpolicy = extract_int(&buf[4], 0);
1823                                 floorvalue = extract_int(&buf[4], 1);
1824                         }
1825                         
1826                         wc_printf("<br /><form method=\"POST\" action=\"set_room_policy\">\n");
1827                         wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1828                         wc_printf("<table border=0 cellspacing=5>\n");
1829                         wc_printf("<tr><td>");
1830                         wc_printf(_("Message expire policy for this room"));
1831                         wc_printf("<br />(");
1832                         escputs(ChrPtr(WC->CurRoom.name));
1833                         wc_printf(")</td><td>");
1834                         wc_printf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"0\" %s>",
1835                                 ((roompolicy == 0) ? "CHECKED" : "") );
1836                         wc_printf(_("Use the default policy for this floor"));
1837                         wc_printf("<br />\n");
1838                         wc_printf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"1\" %s>",
1839                                 ((roompolicy == 1) ? "CHECKED" : "") );
1840                         wc_printf(_("Never automatically expire messages"));
1841                         wc_printf("<br />\n");
1842                         wc_printf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"2\" %s>",
1843                                 ((roompolicy == 2) ? "CHECKED" : "") );
1844                         wc_printf(_("Expire by message count"));
1845                         wc_printf("<br />\n");
1846                         wc_printf("<input type=\"radio\" NAME=\"roompolicy\" VALUE=\"3\" %s>",
1847                                 ((roompolicy == 3) ? "CHECKED" : "") );
1848                         wc_printf(_("Expire by message age"));
1849                         wc_printf("<br />");
1850                         wc_printf(_("Number of messages or days: "));
1851                         wc_printf("<input type=\"text\" NAME=\"roomvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">", roomvalue);
1852                         wc_printf("</td></tr>\n");
1853         
1854                         if (WC->axlevel >= 6) {
1855                                 wc_printf("<tr><td COLSPAN=2><hr /></td></tr>\n");
1856                                 wc_printf("<tr><td>");
1857                                 wc_printf(_("Message expire policy for this floor"));
1858                                 wc_printf("<br />(");
1859                                 escputs(floorlist[WC->CurRoom.floorid]);
1860                                 wc_printf(")</td><td>");
1861                                 wc_printf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"0\" %s>",
1862                                         ((floorpolicy == 0) ? "CHECKED" : "") );
1863                                 wc_printf(_("Use the system default"));
1864                                 wc_printf("<br />\n");
1865                                 wc_printf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"1\" %s>",
1866                                         ((floorpolicy == 1) ? "CHECKED" : "") );
1867                                 wc_printf(_("Never automatically expire messages"));
1868                                 wc_printf("<br />\n");
1869                                 wc_printf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"2\" %s>",
1870                                         ((floorpolicy == 2) ? "CHECKED" : "") );
1871                                 wc_printf(_("Expire by message count"));
1872                                 wc_printf("<br />\n");
1873                                 wc_printf("<input type=\"radio\" NAME=\"floorpolicy\" VALUE=\"3\" %s>",
1874                                         ((floorpolicy == 3) ? "CHECKED" : "") );
1875                                 wc_printf(_("Expire by message age"));
1876                                 wc_printf("<br />");
1877                                 wc_printf(_("Number of messages or days: "));
1878                                 wc_printf("<input type=\"text\" NAME=\"floorvalue\" MAXLENGTH=\"5\" VALUE=\"%d\">",
1879                                         floorvalue);
1880                         }
1881         
1882                         wc_printf("<CENTER>\n");
1883                         wc_printf("<tr><td COLSPAN=2><hr /><CENTER>\n");
1884                         wc_printf("<input type=\"submit\" NAME=\"ok_button\" VALUE=\"%s\">", _("Save changes"));
1885                         wc_printf("&nbsp;");
1886                         wc_printf("<input type=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">", _("Cancel"));
1887                         wc_printf("</CENTER></td><tr>\n");
1888         
1889                         wc_printf("</table>\n"
1890                                 "<input type=\"hidden\" NAME=\"tab\" VALUE=\"expire\">\n"
1891                                 "</form>\n"
1892                                 );
1893                 }
1894
1895                 wc_printf("</div>");
1896         }
1897
1898         /* Access controls */
1899         if (!strcmp(tab, "access")) {
1900                 wc_printf("<div class=\"tabcontent\">");
1901                 display_whok();
1902                 wc_printf("</div>");
1903         }
1904
1905         /* Fetch messages from remote locations */
1906         if (!strcmp(tab, "feeds")) {
1907                 wc_printf("<div class=\"tabcontent\">");
1908
1909                 wc_printf("<i>");
1910                 wc_printf(_("Retrieve messages from these remote POP3 accounts and store them in this room:"));
1911                 wc_printf("</i><br />\n");
1912
1913                 wc_printf("<table class=\"altern\" border=0 cellpadding=5>"
1914                         "<tr class=\"even\"><th>");
1915                 wc_printf(_("Remote host"));
1916                 wc_printf("</th><th>");
1917                 wc_printf(_("User name"));
1918                 wc_printf("</th><th>");
1919                 wc_printf(_("Password"));
1920                 wc_printf("</th><th>");
1921                 wc_printf(_("Keep messages on server?"));
1922                 wc_printf("</th><th>");
1923                 wc_printf(_("Interval"));
1924                 wc_printf("</th><th> </th></tr>");
1925
1926                 serv_puts("GNET");
1927                 serv_getln(buf, sizeof buf);
1928                 bg = 1;
1929                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1930                                 extract_token(cmd, buf, 0, '|', sizeof cmd);
1931                                 if (!strcasecmp(cmd, "pop3client")) {
1932                                         safestrncpy(recp, &buf[11], sizeof recp);
1933
1934                                         bg = 1 - bg;
1935                                         wc_printf("<tr class=\"%s\">",
1936                                                 (bg ? "even" : "odd")
1937                                                 );
1938
1939                                         wc_printf("<td>");
1940                                         extract_token(pop3_host, buf, 1, '|', sizeof pop3_host);
1941                                         escputs(pop3_host);
1942                                         wc_printf("</td>");
1943
1944                                         wc_printf("<td>");
1945                                         extract_token(pop3_user, buf, 2, '|', sizeof pop3_user);
1946                                         escputs(pop3_user);
1947                                         wc_printf("</td>");
1948
1949                                         wc_printf("<td>*****</td>");            /* Don't show the password */
1950
1951                                         wc_printf("<td>%s</td>", extract_int(buf, 4) ? _("Yes") : _("No"));
1952
1953                                         wc_printf("<td>%ld</td>", extract_long(buf, 5));        /* Fetching interval */
1954                         
1955                                         wc_printf("<td class=\"button_link\">");
1956                                         wc_printf(" <a href=\"netedit?cmd=remove?tab=feeds?line=pop3client|");
1957                                         urlescputs(recp);
1958                                         wc_printf("\">");
1959                                         wc_printf(_("(remove)"));
1960                                         wc_printf("</a></td>");
1961                         
1962                                         wc_printf("</tr>");
1963                                 }
1964                         }
1965
1966                 wc_printf("<form method=\"POST\" action=\"netedit\">\n"
1967                         "<tr>"
1968                         "<input type=\"hidden\" name=\"tab\" value=\"feeds\">"
1969                         "<input type=\"hidden\" name=\"prefix\" value=\"pop3client|\">\n");
1970                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
1971                 wc_printf("<td>");
1972                 wc_printf("<input type=\"text\" id=\"add_as_pop3host\" NAME=\"line_pop3host\">\n");
1973                 wc_printf("</td>");
1974                 wc_printf("<td>");
1975                 wc_printf("<input type=\"text\" id=\"add_as_pop3user\" NAME=\"line_pop3user\">\n");
1976                 wc_printf("</td>");
1977                 wc_printf("<td>");
1978                 wc_printf("<input type=\"password\" id=\"add_as_pop3pass\" NAME=\"line_pop3pass\">\n");
1979                 wc_printf("</td>");
1980                 wc_printf("<td>");
1981                 wc_printf("<input type=\"checkbox\" id=\"add_as_pop3keep\" NAME=\"line_pop3keep\" VALUE=\"1\">");
1982                 wc_printf("</td>");
1983                 wc_printf("<td>");
1984                 wc_printf("<input type=\"text\" id=\"add_as_pop3int\" NAME=\"line_pop3int\" MAXLENGTH=\"5\">");
1985                 wc_printf("</td>");
1986                 wc_printf("<td>");
1987                 wc_printf("<input type=\"submit\" NAME=\"add_button\" VALUE=\"%s\">", _("Add"));
1988                 wc_printf("</td></tr>");
1989                 wc_printf("</form></table>\n");
1990
1991                 wc_printf("<hr>\n");
1992
1993                 wc_printf("<i>");
1994                 wc_printf(_("Fetch the following RSS feeds and store them in this room:"));
1995                 wc_printf("</i><br />\n");
1996
1997                 wc_printf("<table class=\"altern\" border=0 cellpadding=5>"
1998                         "<tr class=\"even\"><th>");
1999                 wc_printf("<img src=\"static/rss_16x.png\" width=\"16\" height=\"16\" alt=\" \"> ");
2000                 wc_printf(_("Feed URL"));
2001                 wc_printf("</th><th>");
2002                 wc_printf("</th></tr>");
2003
2004                 serv_puts("GNET");
2005                 serv_getln(buf, sizeof buf);
2006                 bg = 1;
2007                 if (buf[0]=='1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2008                                 extract_token(cmd, buf, 0, '|', sizeof cmd);
2009                                 if (!strcasecmp(cmd, "rssclient")) {
2010                                         safestrncpy(recp, &buf[10], sizeof recp);
2011
2012                                         bg = 1 - bg;
2013                                         wc_printf("<tr class=\"%s\">",
2014                                                 (bg ? "even" : "odd")
2015                                                 );
2016
2017                                         wc_printf("<td>");
2018                                         extract_token(pop3_host, buf, 1, '|', sizeof pop3_host);
2019                                         escputs(pop3_host);
2020                                         wc_printf("</td>");
2021
2022                                         wc_printf("<td class=\"button_link\">");
2023                                         wc_printf(" <a href=\"netedit?cmd=remove?tab=feeds?line=rssclient|");
2024                                         urlescputs(recp);
2025                                         wc_printf("\">");
2026                                         wc_printf(_("(remove)"));
2027                                         wc_printf("</a></td>");
2028                         
2029                                         wc_printf("</tr>");
2030                                 }
2031                         }
2032
2033                 wc_printf("<form method=\"POST\" action=\"netedit\">\n"
2034                         "<tr>"
2035                         "<input type=\"hidden\" name=\"tab\" value=\"feeds\">"
2036                         "<input type=\"hidden\" name=\"prefix\" value=\"rssclient|\">\n");
2037                 wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2038                 wc_printf("<td>");
2039                 wc_printf("<input type=\"text\" id=\"add_as_pop3host\" size=\"72\" "
2040                         "maxlength=\"256\" name=\"line_pop3host\">\n");
2041                 wc_printf("</td>");
2042                 wc_printf("<td>");
2043                 wc_printf("<input type=\"submit\" name=\"add_button\" value=\"%s\">", _("Add"));
2044                 wc_printf("</td></tr>");
2045                 wc_printf("</form></table>\n");
2046
2047                 wc_printf("</div>");
2048         }
2049
2050
2051         /* end content of whatever tab is open now */
2052         wc_printf("</div>\n");
2053
2054         address_book_popup();
2055         wDumpContent(1);
2056 }
2057
2058
2059 /* 
2060  * Toggle self-service list subscription
2061  */
2062 void toggle_self_service(void) {
2063         room_states RoomFlags;
2064
2065         get_roomflags (&RoomFlags);
2066
2067         if (yesbstr("QR2_SelfList")) 
2068                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SELFLIST;
2069         else 
2070                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SELFLIST;
2071
2072         if (yesbstr("QR2_SMTP_PUBLIC")) 
2073                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SMTP_PUBLIC;
2074         else
2075                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SMTP_PUBLIC;
2076
2077         if (yesbstr("QR2_Moderated")) 
2078                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_MODERATED;
2079         else
2080                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_MODERATED;
2081         if (yesbstr("QR2_SubsOnly")) 
2082                 RoomFlags.flags2 = RoomFlags.flags2 | QR2_SMTP_PUBLIC;
2083         else
2084                 RoomFlags.flags2 = RoomFlags.flags2 & ~QR2_SMTP_PUBLIC;
2085
2086         set_roomflags (&RoomFlags);
2087         
2088         display_editroom();
2089 }
2090
2091
2092
2093 /*
2094  * save new parameters for a room
2095  */
2096 void editroom(void)
2097 {
2098         const StrBuf *Ptr;
2099         StrBuf *Buf;
2100         StrBuf *er_name;
2101         StrBuf *er_password;
2102         StrBuf *er_dirname;
2103         StrBuf *er_roomaide;
2104         int er_floor;
2105         unsigned er_flags;
2106         int er_listingorder;
2107         int er_defaultview;
2108         unsigned er_flags2;
2109         int bump;
2110
2111
2112         if (!havebstr("ok_button")) {
2113                 strcpy(WC->ImportantMessage,
2114                        _("Cancelled.  Changes were not saved."));
2115                 display_editroom();
2116                 return;
2117         }
2118         serv_puts("GETR");
2119         Buf = NewStrBuf();
2120         StrBuf_ServGetln(Buf);
2121         if (GetServerStatus(Buf, NULL) != 2) {
2122                 StrBufCutLeft(Buf, 4);
2123                 strcpy(WC->ImportantMessage, ChrPtr(Buf));
2124                 display_editroom();
2125                 FreeStrBuf(&Buf);
2126                 return;
2127         }
2128
2129         er_name = NewStrBuf();
2130         er_password = NewStrBuf();
2131         er_dirname = NewStrBuf();
2132         er_roomaide = NewStrBuf();
2133
2134         StrBufCutLeft(Buf, 4);
2135         StrBufExtract_token(er_name, Buf, 0, '|');
2136         StrBufExtract_token(er_password, Buf, 1, '|');
2137         StrBufExtract_token(er_dirname, Buf, 2, '|');
2138         er_flags = StrBufExtract_int(Buf, 3, '|');
2139         er_listingorder = StrBufExtract_int(Buf, 5, '|');
2140         er_defaultview = StrBufExtract_int(Buf, 6, '|');
2141         er_flags2 = StrBufExtract_int(Buf, 7, '|');
2142
2143         er_roomaide = NewStrBufDup(sbstr("er_roomaide"));
2144         if (StrLength(er_roomaide) == 0) {
2145                 serv_puts("GETA");
2146                 StrBuf_ServGetln(Buf);
2147                 if (GetServerStatus(Buf, NULL) != 2) {
2148                         FlushStrBuf(er_roomaide);
2149                 } else {
2150                         StrBufCutLeft(Buf, 4);
2151                         StrBufExtract_token(er_roomaide, Buf, 0, '|');
2152                 }
2153         }
2154         Ptr = sbstr("er_name");
2155         if (StrLength(Ptr) > 0) {
2156                 FlushStrBuf(er_name);
2157                 StrBufAppendBuf(er_name, Ptr, 0);
2158         }
2159
2160         Ptr = sbstr("er_password");
2161         if (StrLength(Ptr) > 0) {
2162                 FlushStrBuf(er_password);
2163                 StrBufAppendBuf(er_password, Ptr, 0);
2164         }
2165                 
2166
2167         Ptr = sbstr("er_dirname");
2168         if (StrLength(Ptr) > 0) { /* todo: cut 15 */
2169                 FlushStrBuf(er_dirname);
2170                 StrBufAppendBuf(er_dirname, Ptr, 0);
2171         }
2172
2173
2174         Ptr = sbstr("type");
2175         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
2176
2177         if (!strcmp(ChrPtr(Ptr), "invonly")) {
2178                 er_flags |= (QR_PRIVATE);
2179         }
2180         if (!strcmp(ChrPtr(Ptr), "hidden")) {
2181                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
2182         }
2183         if (!strcmp(ChrPtr(Ptr), "passworded")) {
2184                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
2185         }
2186         if (!strcmp(ChrPtr(Ptr), "personal")) {
2187                 er_flags |= QR_MAILBOX;
2188         } else {
2189                 er_flags &= ~QR_MAILBOX;
2190         }
2191         
2192         if (yesbstr("prefonly")) {
2193                 er_flags |= QR_PREFONLY;
2194         } else {
2195                 er_flags &= ~QR_PREFONLY;
2196         }
2197
2198         if (yesbstr("readonly")) {
2199                 er_flags |= QR_READONLY;
2200         } else {
2201                 er_flags &= ~QR_READONLY;
2202         }
2203
2204         
2205         if (yesbstr("collabdel")) {
2206                 er_flags2 |= QR2_COLLABDEL;
2207         } else {
2208                 er_flags2 &= ~QR2_COLLABDEL;
2209         }
2210
2211         if (yesbstr("permanent")) {
2212                 er_flags |= QR_PERMANENT;
2213         } else {
2214                 er_flags &= ~QR_PERMANENT;
2215         }
2216
2217         if (yesbstr("subjectreq")) {
2218                 er_flags2 |= QR2_SUBJECTREQ;
2219         } else {
2220                 er_flags2 &= ~QR2_SUBJECTREQ;
2221         }
2222
2223         if (yesbstr("network")) {
2224                 er_flags |= QR_NETWORK;
2225         } else {
2226                 er_flags &= ~QR_NETWORK;
2227         }
2228
2229         if (yesbstr("directory")) {
2230                 er_flags |= QR_DIRECTORY;
2231         } else {
2232                 er_flags &= ~QR_DIRECTORY;
2233         }
2234
2235         if (yesbstr("ulallowed")) {
2236                 er_flags |= QR_UPLOAD;
2237         } else {
2238                 er_flags &= ~QR_UPLOAD;
2239         }
2240
2241         if (yesbstr("dlallowed")) {
2242                 er_flags |= QR_DOWNLOAD;
2243         } else {
2244                 er_flags &= ~QR_DOWNLOAD;
2245         }
2246
2247         if (yesbstr("visdir")) {
2248                 er_flags |= QR_VISDIR;
2249         } else {
2250                 er_flags &= ~QR_VISDIR;
2251         }
2252
2253         Ptr = sbstr("anon");
2254
2255         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
2256         if (!strcmp(ChrPtr(Ptr), "anononly"))
2257                 er_flags |= QR_ANONONLY;
2258         if (!strcmp(ChrPtr(Ptr), "anon2"))
2259                 er_flags |= QR_ANONOPT;
2260
2261         bump = yesbstr("bump");
2262
2263         er_floor = ibstr("er_floor");
2264
2265         StrBufPrintf(Buf, "SETR %s|%s|%s|%u|%d|%d|%d|%d|%u",
2266                      ChrPtr(er_name), 
2267                      ChrPtr(er_password), 
2268                      ChrPtr(er_dirname), 
2269                      er_flags, 
2270                      bump, 
2271                      er_floor,
2272                      er_listingorder, 
2273                      er_defaultview, 
2274                      er_flags2);
2275         serv_putbuf(Buf);
2276         StrBuf_ServGetln(Buf);
2277         if (GetServerStatus(Buf, NULL) != 2) {
2278                 strcpy(WC->ImportantMessage, &ChrPtr(Buf)[4]);
2279                 display_editroom();
2280                 FreeStrBuf(&Buf);
2281                 FreeStrBuf(&er_name);
2282                 FreeStrBuf(&er_password);
2283                 FreeStrBuf(&er_dirname);
2284                 FreeStrBuf(&er_roomaide);
2285                 return;
2286         }
2287         gotoroom(er_name);
2288
2289         if (StrLength(er_roomaide) > 0) {
2290                 serv_printf("SETA %s", ChrPtr(er_roomaide));
2291                 StrBuf_ServGetln(Buf);
2292                 if (GetServerStatus(Buf, NULL) != 2) {
2293                         strcpy(WC->ImportantMessage, &ChrPtr(Buf)[4]);
2294                         display_main_menu();
2295                         FreeStrBuf(&Buf);
2296                         FreeStrBuf(&er_name);
2297                         FreeStrBuf(&er_password);
2298                         FreeStrBuf(&er_dirname);
2299                         FreeStrBuf(&er_roomaide);
2300                         return;
2301                 }
2302         }
2303         gotoroom(er_name);
2304         strcpy(WC->ImportantMessage, _("Your changes have been saved."));
2305         display_editroom();
2306         FreeStrBuf(&Buf);
2307         FreeStrBuf(&er_name);
2308         FreeStrBuf(&er_password);
2309         FreeStrBuf(&er_dirname);
2310         FreeStrBuf(&er_roomaide);
2311         return;
2312 }
2313
2314
2315 /*
2316  * Display form for Invite, Kick, and show Who Knows a room
2317  */
2318 void do_invt_kick(void) {
2319         char buf[SIZ], room[SIZ], username[SIZ];
2320
2321         serv_puts("GETR");
2322         serv_getln(buf, sizeof buf);
2323
2324         if (buf[0] != '2') {
2325                 escputs(&buf[4]);
2326                 return;
2327         }
2328         extract_token(room, &buf[4], 0, '|', sizeof room);
2329
2330         strcpy(username, bstr("username"));
2331
2332         if (havebstr("kick_button")) {
2333                 sprintf(buf, "KICK %s", username);
2334                 serv_puts(buf);
2335                 serv_getln(buf, sizeof buf);
2336
2337                 if (buf[0] != '2') {
2338                         strcpy(WC->ImportantMessage, &buf[4]);
2339                 } else {
2340                         sprintf(WC->ImportantMessage,
2341                                 _("<B><I>User %s kicked out of room %s.</I></B>\n"), 
2342                                 username, room);
2343                 }
2344         }
2345
2346         if (havebstr("invite_button")) {
2347                 sprintf(buf, "INVT %s", username);
2348                 serv_puts(buf);
2349                 serv_getln(buf, sizeof buf);
2350
2351                 if (buf[0] != '2') {
2352                         strcpy(WC->ImportantMessage, &buf[4]);
2353                 } else {
2354                         sprintf(WC->ImportantMessage,
2355                                 _("<B><I>User %s invited to room %s.</I></B>\n"), 
2356                                 username, room);
2357                 }
2358         }
2359
2360         display_editroom();
2361 }
2362
2363
2364
2365 /*
2366  * Display form for Invite, Kick, and show Who Knows a room
2367  */
2368 void display_whok(void)
2369 {
2370         char buf[SIZ], room[SIZ], username[SIZ];
2371
2372         serv_puts("GETR");
2373         serv_getln(buf, sizeof buf);
2374
2375         if (buf[0] != '2') {
2376                 escputs(&buf[4]);
2377                 return;
2378         }
2379         extract_token(room, &buf[4], 0, '|', sizeof room);
2380
2381         
2382         wc_printf("<table border=0 CELLSPACING=10><tr VALIGN=TOP><td>");
2383         wc_printf(_("The users listed below have access to this room.  "
2384                   "To remove a user from the access list, select the user "
2385                   "name from the list and click 'Kick'."));
2386         wc_printf("<br /><br />");
2387         
2388         wc_printf("<CENTER><form method=\"POST\" action=\"do_invt_kick\">\n");
2389         wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2390         wc_printf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
2391         wc_printf("<select NAME=\"username\" SIZE=\"10\" style=\"width:100%%\">\n");
2392         serv_puts("WHOK");
2393         serv_getln(buf, sizeof buf);
2394         if (buf[0] == '1') {
2395                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2396                         extract_token(username, buf, 0, '|', sizeof username);
2397                         wc_printf("<OPTION>");
2398                         escputs(username);
2399                         wc_printf("\n");
2400                 }
2401         }
2402         wc_printf("</select><br />\n");
2403
2404         wc_printf("<input type=\"submit\" name=\"kick_button\" value=\"%s\">", _("Kick"));
2405         wc_printf("</form></CENTER>\n");
2406
2407         wc_printf("</td><td>");
2408         wc_printf(_("To grant another user access to this room, enter the "
2409                   "user name in the box below and click 'Invite'."));
2410         wc_printf("<br /><br />");
2411
2412         wc_printf("<CENTER><form method=\"POST\" action=\"do_invt_kick\">\n");
2413         wc_printf("<input type=\"hidden\" NAME=\"tab\" VALUE=\"access\">\n");
2414         wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2415         wc_printf(_("Invite:"));
2416         wc_printf(" ");
2417         wc_printf("<input type=\"text\" name=\"username\" id=\"username_id\" style=\"width:100%%\"><br />\n"
2418                 "<input type=\"hidden\" name=\"invite_button\" value=\"Invite\">"
2419                 "<input type=\"submit\" value=\"%s\">"
2420                 "</form></CENTER>\n", _("Invite"));
2421         /* Pop open an address book -- begin **/
2422         wc_printf(
2423                 "<a href=\"javascript:PopOpenAddressBook('username_id|%s');\" "
2424                 "title=\"%s\">"
2425                 "<img align=middle border=0 width=24 height=24 src=\"static/viewcontacts_24x.gif\">"
2426                 "&nbsp;%s</a>",
2427                 _("User"), 
2428                 _("Users"), _("Users")
2429                 );
2430         /* Pop open an address book -- end **/
2431
2432         wc_printf("</td></tr></table>\n");
2433         address_book_popup();
2434         wDumpContent(1);
2435 }
2436
2437
2438
2439 /*
2440  * display the form for entering a new room
2441  */
2442 void display_entroom(void)
2443 {
2444         StrBuf *Buf;
2445         int i;
2446         char buf[SIZ];
2447
2448         Buf = NewStrBuf();
2449         serv_puts("CRE8 0");
2450         serv_getln(buf, sizeof buf);
2451
2452         if (buf[0] != '2') {
2453                 strcpy(WC->ImportantMessage, &buf[4]);
2454                 display_main_menu();
2455                 FreeStrBuf(&Buf);
2456                 return;
2457         }
2458
2459         output_headers(1, 1, 1, 0, 0, 0);
2460
2461         svprintf(HKEY("BOXTITLE"), WCS_STRING, _("Create a new room"));
2462         do_template("beginbox", NULL);
2463
2464         wc_printf("<form name=\"create_room_form\" method=\"POST\" action=\"entroom\">\n");
2465         wc_printf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
2466
2467         wc_printf("<table class=\"altern\"> ");
2468
2469         wc_printf("<tr class=\"even\"><td>");
2470         wc_printf(_("Name of room: "));
2471         wc_printf("</td><td>");
2472         wc_printf("<input type=\"text\" NAME=\"er_name\" MAXLENGTH=\"127\">\n");
2473         wc_printf("</td></tr>");
2474
2475         wc_printf("<tr class=\"odd\"><td>");
2476         wc_printf(_("Resides on floor: "));
2477         wc_printf("</td><td>");
2478 //        load_floorlist(Buf); 
2479         wc_printf("<select name=\"er_floor\" size=\"1\">\n");
2480         for (i = 0; i < 128; ++i)
2481                 if (!IsEmptyStr(floorlist[i])) {
2482                         wc_printf("<option ");
2483                         wc_printf("value=\"%d\">", i);
2484                         escputs(floorlist[i]);
2485                         wc_printf("</option>\n");
2486                 }
2487         wc_printf("</select>\n");
2488         wc_printf("</td></tr>");
2489
2490         /*
2491          * Our clever little snippet of JavaScript automatically selects
2492          * a public room if the view is set to Bulletin Board or wiki, and
2493          * it selects a mailbox room otherwise.  The user can override this,
2494          * of course.  We also disable the floor selector for mailboxes.
2495          */
2496         wc_printf("<tr class=\"even\"><td>");
2497         wc_printf(_("Default view for room: "));
2498         wc_printf("</td><td>");
2499         wc_printf("<select name=\"er_view\" size=\"1\" OnChange=\""
2500                 "       if ( (this.form.er_view.value == 0)             "
2501                 "          || (this.form.er_view.value == 6) ) {        "
2502                 "               this.form.type[0].checked=true;         "
2503                 "               this.form.er_floor.disabled = false;    "
2504                 "       }                                               "
2505                 "       else {                                          "
2506                 "               this.form.type[4].checked=true;         "
2507                 "               this.form.er_floor.disabled = true;     "
2508                 "       }                                               "
2509                 "\">\n");
2510         for (i=0; i<(sizeof viewdefs / sizeof (char *)); ++i) {
2511 /*
2512                 if (is_view_allowed_as_default(i)) {
2513                         wc_printf("<option %s value=\"%d\">",
2514                                 ((i == 0) ? "selected" : ""), i );
2515                         escputs(viewdefs[i]);
2516                         wc_printf("</option>\n");
2517                 }
2518 */
2519         }
2520         wc_printf("</select>\n");
2521         wc_printf("</td></tr>");
2522
2523         wc_printf("<tr class=\"even\"><td>");
2524         wc_printf(_("Type of room:"));
2525         wc_printf("</td><td>");
2526         wc_printf("<ul class=\"adminlist\">\n");
2527
2528         wc_printf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"public\" ");
2529         wc_printf("CHECKED OnChange=\""
2530                 "       if (this.form.type[0].checked == true) {        "
2531                 "               this.form.er_floor.disabled = false;    "
2532                 "       }                                               "
2533                 "\"> ");
2534         wc_printf(_("Public (automatically appears to everyone)"));
2535         wc_printf("</li>");
2536
2537         wc_printf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"hidden\" OnChange=\""
2538                 "       if (this.form.type[1].checked == true) {        "
2539                 "               this.form.er_floor.disabled = false;    "
2540                 "       }                                               "
2541                 "\"> ");
2542         wc_printf(_("Private - hidden (accessible to anyone who knows its name)"));
2543         wc_printf("</li>");
2544
2545         wc_printf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"passworded\" OnChange=\""
2546                 "       if (this.form.type[2].checked == true) {        "
2547                 "               this.form.er_floor.disabled = false;    "
2548                 "       }                                               "
2549                 "\"> ");
2550         wc_printf(_("Private - require password: "));
2551         wc_printf("<input type=\"text\" NAME=\"er_password\" MAXLENGTH=\"9\">\n");
2552         wc_printf("</li>");
2553
2554         wc_printf("<li><input type=\"radio\" NAME=\"type\" VALUE=\"invonly\" OnChange=\""
2555                 "       if (this.form.type[3].checked == true) {        "
2556                 "               this.form.er_floor.disabled = false;    "
2557                 "       }                                               "
2558                 "\"> ");
2559         wc_printf(_("Private - invitation only"));
2560         wc_printf("</li>");
2561
2562         wc_printf("\n<li><input type=\"radio\" NAME=\"type\" VALUE=\"personal\" "
2563                 "OnChange=\""
2564                 "       if (this.form.type[4].checked == true) {        "
2565                 "               this.form.er_floor.disabled = true;     "
2566                 "       }                                               "
2567                 "\"> ");
2568         wc_printf(_("Personal (mailbox for you only)"));
2569         wc_printf("</li>");
2570
2571         wc_printf("\n</ul>\n");
2572         wc_printf("</td></tr></table>\n");
2573
2574         wc_printf("<div class=\"buttons\">\n");
2575         wc_printf("<input type=\"submit\" name=\"ok_button\" value=\"%s\">", _("Create new room"));
2576         wc_printf("&nbsp;");
2577         wc_printf("<input type=\"submit\" name=\"cancel_button\" value=\"%s\">", _("Cancel"));
2578         wc_printf("</div>\n");
2579         wc_printf("</form>\n<hr />");
2580         serv_printf("MESG roomaccess");
2581         serv_getln(buf, sizeof buf);
2582         if (buf[0] == '1') {
2583                 fmout("LEFT");
2584         }
2585
2586         do_template("endbox", NULL);
2587
2588         wDumpContent(1);
2589         FreeStrBuf(&Buf);
2590 }
2591
2592
2593
2594
2595 /*
2596  * support function for entroom() -- sets the default view 
2597  */
2598 void er_set_default_view(int newview) {
2599
2600         char buf[SIZ];
2601
2602         char rm_name[SIZ];
2603         char rm_pass[SIZ];
2604         char rm_dir[SIZ];
2605         int rm_bits1;
2606         int rm_floor;
2607         int rm_listorder;
2608         int rm_bits2;
2609
2610         serv_puts("GETR");
2611         serv_getln(buf, sizeof buf);
2612         if (buf[0] != '2') return;
2613
2614         extract_token(rm_name, &buf[4], 0, '|', sizeof rm_name);
2615         extract_token(rm_pass, &buf[4], 1, '|', sizeof rm_pass);
2616         extract_token(rm_dir, &buf[4], 2, '|', sizeof rm_dir);
2617         rm_bits1 = extract_int(&buf[4], 3);
2618         rm_floor = extract_int(&buf[4], 4);
2619         rm_listorder = extract_int(&buf[4], 5);
2620         rm_bits2 = extract_int(&buf[4], 7);
2621
2622         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
2623                     rm_name, rm_pass, rm_dir, rm_bits1, rm_floor,
2624                     rm_listorder, newview, rm_bits2
2625                 );
2626         serv_getln(buf, sizeof buf);
2627 }
2628
2629
2630
2631 /*
2632  * Create a new room
2633  */
2634 void entroom(void)
2635 {
2636         char buf[SIZ];
2637         const StrBuf *er_name;
2638         const StrBuf *er_type;
2639         const StrBuf *er_password;
2640         int er_floor;
2641         int er_num_type;
2642         int er_view;
2643         wcsession *WCC = WC;
2644
2645         if (!havebstr("ok_button")) {
2646                 strcpy(WC->ImportantMessage,
2647                        _("Cancelled.  No new room was created."));
2648                 display_main_menu();
2649                 return;
2650         }
2651         er_name = sbstr("er_name");
2652         er_type = sbstr("type");
2653         er_password = sbstr("er_password");
2654         er_floor = ibstr("er_floor");
2655         er_view = ibstr("er_view");
2656
2657         er_num_type = 0;
2658         if (!strcmp(ChrPtr(er_type), "hidden"))
2659                 er_num_type = 1;
2660         else if (!strcmp(ChrPtr(er_type), "passworded"))
2661                 er_num_type = 2;
2662         else if (!strcmp(ChrPtr(er_type), "invonly"))
2663                 er_num_type = 3;
2664         else if (!strcmp(ChrPtr(er_type), "personal"))
2665                 er_num_type = 4;
2666
2667         serv_printf("CRE8 1|%s|%d|%s|%d|%d|%d", 
2668                     ChrPtr(er_name), 
2669                     er_num_type, 
2670                     ChrPtr(er_password), 
2671                     er_floor, 
2672                     0, 
2673                     er_view);
2674
2675         serv_getln(buf, sizeof buf);
2676         if (buf[0] != '2') {
2677                 strcpy(WCC->ImportantMessage, &buf[4]);
2678                 display_main_menu();
2679                 return;
2680         }
2681         /** TODO: Room created, now update the left hand icon bar for this user */
2682         burn_folder_cache(0);   /* burn the old folder cache */
2683         FlushRoomlist ();
2684         gotoroom(er_name);
2685
2686         serv_printf("VIEW %d", er_view);
2687         serv_getln(buf, sizeof buf);
2688         WCC->CurRoom.view = er_view;
2689
2690         if ( (WCC != NULL) && ( (WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) )  {
2691                 display_editroom ();
2692         } else {
2693                 do_change_view(er_view);                /* Now go there */
2694         }
2695
2696 }
2697
2698
2699 /**
2700  * \brief goto a private room
2701  */
2702 void goto_private(void)
2703 {
2704         char hold_rm[SIZ];
2705         char buf[SIZ];
2706
2707         if (!havebstr("ok_button")) {
2708                 display_main_menu();
2709                 return;
2710         }
2711         FlushRoomlist();
2712         strcpy(hold_rm, ChrPtr(WC->CurRoom.name));
2713         serv_printf("GOTO %s|%s",
2714                     bstr("gr_name"),
2715                     bstr("gr_pass"));
2716         serv_getln(buf, sizeof buf);
2717
2718         if (buf[0] == '2') {
2719                 smart_goto(sbstr("gr_name"));
2720                 return;
2721         }
2722         if (!strncmp(buf, "540", 3)) {
2723                 DoTemplate(HKEY("room_display_private"), NULL, &NoCtx);
2724                 return;
2725         }
2726         output_headers(1, 1, 1, 0, 0, 0);
2727         wc_printf("%s\n", &buf[4]);
2728         wDumpContent(1);
2729         return;
2730 }
2731
2732
2733
2734 /**
2735  * \brief zap a room
2736  */
2737 void zap(void)
2738 {
2739         char buf[SIZ];
2740         StrBuf *final_destination;
2741
2742         /**
2743          * If the forget-room routine fails for any reason, we fall back
2744          * to the current room; otherwise, we go to the Lobby
2745          */
2746         final_destination = NewStrBufDup(WC->CurRoom.name);
2747
2748         if (havebstr("ok_button")) {
2749                 serv_printf("GOTO %s", ChrPtr(WC->CurRoom.name));
2750                 serv_getln(buf, sizeof buf);
2751                 if (buf[0] == '2') {
2752                         serv_puts("FORG");
2753                         serv_getln(buf, sizeof buf);
2754                         if (buf[0] == '2') {
2755                                 FlushStrBuf(final_destination);
2756                                 StrBufAppendBufPlain(final_destination, HKEY("_BASEROOM_"), 0);
2757                         }
2758                 }
2759                 FlushRoomlist ();
2760         }
2761         smart_goto(final_destination);
2762         FreeStrBuf(&final_destination);
2763 }
2764
2765
2766
2767 /**
2768  * \brief Delete the current room
2769  */
2770 void delete_room(void)
2771 {
2772         char buf[SIZ];
2773
2774         
2775         serv_puts("KILL 1");
2776         serv_getln(buf, sizeof buf);
2777         burn_folder_cache(0);   /* Burn the cahce of known rooms to update the icon bar */
2778         FlushRoomlist ();
2779         if (buf[0] != '2') {
2780                 strcpy(WC->ImportantMessage, &buf[4]);
2781                 display_main_menu();
2782                 return;
2783         } else {
2784                 StrBuf *Buf;
2785                 
2786                 Buf = NewStrBufPlain(HKEY("_BASEROOM_"));
2787                 smart_goto(Buf);
2788                 FreeStrBuf(&Buf);
2789         }
2790 }
2791
2792
2793
2794 /**
2795  * \brief Perform changes to a room's network configuration
2796  */
2797 void netedit(void) {
2798         FILE *fp;
2799         char buf[SIZ];
2800         char line[SIZ];
2801         char cmpa0[SIZ];
2802         char cmpa1[SIZ];
2803         char cmpb0[SIZ];
2804         char cmpb1[SIZ];
2805         int i, num_addrs;
2806         /*/ TODO: do line dynamic! */
2807         if (havebstr("line_pop3host")) {
2808                 strcpy(line, bstr("prefix"));
2809                 strcat(line, bstr("line_pop3host"));
2810                 strcat(line, "|");
2811                 strcat(line, bstr("line_pop3user"));
2812                 strcat(line, "|");
2813                 strcat(line, bstr("line_pop3pass"));
2814                 strcat(line, "|");
2815                 strcat(line, ibstr("line_pop3keep") ? "1" : "0" );
2816                 strcat(line, "|");
2817                 sprintf(&line[strlen(line)],"%ld", lbstr("line_pop3int"));
2818                 strcat(line, bstr("suffix"));
2819         }
2820         else if (havebstr("line")) {
2821                 strcpy(line, bstr("prefix"));
2822                 strcat(line, bstr("line"));
2823                 strcat(line, bstr("suffix"));
2824         }
2825         else {
2826                 display_editroom();
2827                 return;
2828         }
2829
2830
2831         fp = tmpfile();
2832         if (fp == NULL) {
2833                 display_editroom();
2834                 return;
2835         }
2836
2837         serv_puts("GNET");
2838         serv_getln(buf, sizeof buf);
2839         if (buf[0] != '1') {
2840                 fclose(fp);
2841                 display_editroom();
2842                 return;
2843         }
2844
2845         /** This loop works for add *or* remove.  Spiffy, eh? */
2846         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
2847                 extract_token(cmpa0, buf, 0, '|', sizeof cmpa0);
2848                 extract_token(cmpa1, buf, 1, '|', sizeof cmpa1);
2849                 extract_token(cmpb0, line, 0, '|', sizeof cmpb0);
2850                 extract_token(cmpb1, line, 1, '|', sizeof cmpb1);
2851                 if ( (strcasecmp(cmpa0, cmpb0)) 
2852                      || (strcasecmp(cmpa1, cmpb1)) ) {
2853                         fprintf(fp, "%s\n", buf);
2854                 }
2855         }
2856
2857         rewind(fp);
2858         serv_puts("SNET");
2859         serv_getln(buf, sizeof buf);
2860         if (buf[0] != '4') {
2861                 fclose(fp);
2862                 display_editroom();
2863                 return;
2864         }
2865
2866         while (fgets(buf, sizeof buf, fp) != NULL) {
2867                 buf[strlen(buf)-1] = 0;
2868                 serv_puts(buf);
2869         }
2870
2871         if (havebstr("add_button")) {
2872                 num_addrs = num_tokens(bstr("line"), ',');
2873                 if (num_addrs < 2) {
2874                         /* just adding one node or address */
2875                         serv_puts(line);
2876                 }
2877                 else {
2878                         /* adding multiple addresses separated by commas */
2879                         for (i=0; i<num_addrs; ++i) {
2880                                 strcpy(line, bstr("prefix"));
2881                                 extract_token(buf, bstr("line"), i, ',', sizeof buf);
2882                                 striplt(buf);
2883                                 strcat(line, buf);
2884                                 strcat(line, bstr("suffix"));
2885                                 serv_puts(line);
2886                         }
2887                 }
2888         }
2889
2890         serv_puts("000");
2891         fclose(fp);
2892         display_editroom();
2893 }
2894
2895
2896
2897 /**
2898  * \brief Convert a room name to a folder-ish-looking name.
2899  * \param folder the folderish name
2900  * \param room the room name
2901  * \param floor the floor name
2902  * \param is_mailbox is it a mailbox?
2903  */
2904 void room_to_folder(char *folder, char *room, int floor, int is_mailbox)
2905 {
2906         int i, len;
2907
2908         /**
2909          * For mailboxes, just do it straight...
2910          */
2911         if (is_mailbox) {
2912                 sprintf(folder, "My folders|%s", room);
2913         }
2914
2915         /**
2916          * Otherwise, prefix the floor name as a "public folders" moniker
2917          */
2918         else {
2919                 if (floor > MAX_FLOORS) {
2920                         wc_backtrace ();
2921                         sprintf(folder, "%%%%%%|%s", room);
2922                 }
2923                 else {
2924                         sprintf(folder, "%s|%s", floorlist[floor], room);
2925                 }
2926         }
2927
2928         /**
2929          * Replace "\" characters with "|" for pseudo-folder-delimiting
2930          */
2931         len = strlen (folder);
2932         for (i=0; i<len; ++i) {
2933                 if (folder[i] == '\\') folder[i] = '|';
2934         }
2935 }
2936
2937
2938
2939
2940 /**
2941  * \brief Back end for change_view()
2942  * \param newview set newview???
2943  */
2944 void do_change_view(int newview) {
2945         char buf[SIZ];
2946
2947         serv_printf("VIEW %d", newview);
2948         serv_getln(buf, sizeof buf);
2949         WC->CurRoom.view = newview;
2950         smart_goto(WC->CurRoom.name);
2951 }
2952
2953
2954
2955 /**
2956  * \brief Change the view for this room
2957  */
2958 void change_view(void) {
2959         int view;
2960
2961         view = lbstr("view");
2962         do_change_view(view);
2963 }
2964
2965 /**
2966  * \brief Burn the cached folder list.  
2967  * \param age How old the cahce needs to be before we burn it.
2968  */
2969
2970 void burn_folder_cache(time_t age)
2971 {
2972         /** If our cached folder list is very old, burn it. */
2973         if (WC->cache_fold != NULL) {
2974                 if ((time(NULL) - WC->cache_timestamp) > age) {
2975                         free(WC->cache_fold);
2976                         WC->cache_fold = NULL;
2977                 }
2978         }
2979 }
2980
2981
2982
2983 /**
2984  * \brief Do either a known rooms list or a folders list, depending on the
2985  * user's preference
2986  */
2987 void knrooms(void)
2988 {
2989         StrBuf *ListView = NULL;
2990
2991         /** Determine whether the user is trying to change views */
2992         if (havebstr("view")) {
2993                 ListView = NewStrBufDup(SBSTR("view"));
2994                 set_preference("roomlistview", ListView, 1);
2995         }
2996         /** Sanitize the input so its safe */
2997         if((get_preference("roomlistview", &ListView) != 0)||
2998            ((strcasecmp(ChrPtr(ListView), "folders") != 0) &&
2999             (strcasecmp(ChrPtr(ListView), "table") != 0))) 
3000         {
3001                 if (ListView == NULL) {
3002                         ListView = NewStrBufPlain(HKEY("rooms"));
3003                         set_preference("roomlistview", ListView, 0);
3004                         ListView = NULL;
3005                 }
3006                 else {
3007                         ListView = NewStrBufPlain(HKEY("rooms"));
3008                         set_preference("roomlistview", ListView, 0);
3009                         ListView = NULL;
3010                 }
3011         }
3012         FreeStrBuf(&ListView);
3013         url_do_template();
3014 }
3015
3016
3017
3018 /**
3019  * \brief Set the message expire policy for this room and/or floor
3020  */
3021 void set_room_policy(void) {
3022         char buf[SIZ];
3023
3024         if (!havebstr("ok_button")) {
3025                 strcpy(WC->ImportantMessage,
3026                        _("Cancelled.  Changes were not saved."));
3027                 display_editroom();
3028                 return;
3029         }
3030
3031         serv_printf("SPEX room|%d|%d", ibstr("roompolicy"), ibstr("roomvalue"));
3032         serv_getln(buf, sizeof buf);
3033         strcpy(WC->ImportantMessage, &buf[4]);
3034
3035         if (WC->axlevel >= 6) {
3036                 strcat(WC->ImportantMessage, "<br />\n");
3037                 serv_printf("SPEX floor|%d|%d", ibstr("floorpolicy"), ibstr("floorvalue"));
3038                 serv_getln(buf, sizeof buf);
3039                 strcat(WC->ImportantMessage, &buf[4]);
3040         }
3041
3042         display_editroom();
3043 }
3044
3045 void tmplput_RoomName(StrBuf *Target, WCTemplputParams *TP)
3046 {
3047         StrBufAppendTemplate(Target, TP, WC->CurRoom.name, 0);
3048 }
3049
3050 void dotgoto(void) {
3051         if (!havebstr("room")) {
3052                 readloop(readnew, eUseDefault);
3053                 return;
3054         }
3055         if (WC->CurRoom.view != VIEW_MAILBOX) { /* dotgoto acts like dotskip when we're in a mailbox view */
3056                 slrp_highest();
3057         }
3058         smart_goto(sbstr("room"));
3059 }
3060
3061
3062
3063 void tmplput_current_room(StrBuf *Target, WCTemplputParams *TP)
3064 {
3065         wcsession *WCC = WC;
3066
3067         if (WCC != NULL)
3068                 StrBufAppendTemplate(Target, TP, 
3069                                      WCC->CurRoom.name, 
3070                                      0); 
3071 }
3072
3073 void tmplput_roombanner(StrBuf *Target, WCTemplputParams *TP)
3074 {
3075         wc_printf("<div id=\"banner\">\n");
3076         embed_room_banner();
3077         wc_printf("</div>\n");
3078 }
3079
3080
3081 void tmplput_ungoto(StrBuf *Target, WCTemplputParams *TP)
3082 {
3083         wcsession *WCC = WC;
3084
3085         if ((WCC!=NULL) && 
3086             (!IsEmptyStr(WCC->ugname)))
3087                 StrBufAppendBufPlain(Target, WCC->ugname, -1, 0);
3088 }
3089
3090 int ConditionalRoomAide(StrBuf *Target, WCTemplputParams *TP)
3091 {
3092         wcsession *WCC = WC;
3093         return (WCC != NULL)? 
3094                 ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) : 0;
3095 }
3096
3097 int ConditionalRoomAcessDelete(StrBuf *Target, WCTemplputParams *TP)
3098 {
3099         wcsession *WCC = WC;
3100         return (WCC == NULL)? 0 : 
3101                 ( ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) ||
3102                    (WCC->CurRoom.is_inbox) || 
3103                    (WCC->CurRoom.QRFlags2 & QR2_COLLABDEL) );
3104 }
3105
3106 int ConditionalHaveUngoto(StrBuf *Target, WCTemplputParams *TP)
3107 {
3108         wcsession *WCC = WC;
3109         
3110         return ((WCC!=NULL) && 
3111                 (!IsEmptyStr(WCC->ugname)) && 
3112                 (strcasecmp(WCC->ugname, ChrPtr(WCC->CurRoom.name)) == 0));
3113 }
3114
3115
3116 int ConditionalRoomHas_UAFlag(StrBuf *Target, WCTemplputParams *TP)
3117 {
3118         folder *Folder = (folder *)(TP->Context);
3119         long UA_CheckFlag;
3120                 
3121         UA_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
3122         if (UA_CheckFlag == 0)
3123                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
3124                                  "requires one of the #\"UA_*\"- defines or an integer flag 0 is invalid!");
3125
3126         return ((Folder->RAFlags & UA_CheckFlag) != 0);
3127 }
3128
3129
3130
3131 int ConditionalCurrentRoomHas_QRFlag(StrBuf *Target, WCTemplputParams *TP)
3132 {
3133         long QR_CheckFlag;
3134         wcsession *WCC = WC;
3135         
3136         QR_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
3137         if (QR_CheckFlag == 0)
3138                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
3139                                  "requires one of the #\"QR*\"- defines or an integer flag 0 is invalid!");
3140
3141         return ((WCC!=NULL) &&
3142                 ((WCC->CurRoom.QRFlags & QR_CheckFlag) != 0));
3143 }
3144
3145 int ConditionalRoomHas_QRFlag(StrBuf *Target, WCTemplputParams *TP)
3146 {
3147         long QR_CheckFlag;
3148         folder *Folder = (folder *)(TP->Context);
3149
3150         QR_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
3151         if (QR_CheckFlag == 0)
3152                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
3153                                  "requires one of the #\"QR*\"- defines or an integer flag 0 is invalid!");
3154         return ((Folder->QRFlags & QR_CheckFlag) != 0);
3155 }
3156
3157
3158 int ConditionalCurrentRoomHas_QRFlag2(StrBuf *Target, WCTemplputParams *TP)
3159 {
3160         long QR2_CheckFlag;
3161         wcsession *WCC = WC;
3162         
3163         QR2_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
3164         if (QR2_CheckFlag == 0)
3165                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
3166                                  "requires one of the #\"QR2*\"- defines or an integer flag 0 is invalid!");
3167
3168         return ((WCC!=NULL) &&
3169                 ((WCC->CurRoom.QRFlags2 & QR2_CheckFlag) != 0));
3170 }
3171
3172 int ConditionalRoomHas_QRFlag2(StrBuf *Target, WCTemplputParams *TP)
3173 {
3174         long QR2_CheckFlag;
3175         folder *Folder = (folder *)(TP->Context);
3176
3177         QR2_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
3178         if (QR2_CheckFlag == 0)
3179                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
3180                                  "requires one of the #\"QR2*\"- defines or an integer flag 0 is invalid!");
3181         return ((Folder->QRFlags2 & QR2_CheckFlag) != 0);
3182 }
3183
3184
3185 int ConditionalHaveRoomeditRights(StrBuf *Target, WCTemplputParams *TP)
3186 {
3187         wcsession *WCC = WC;
3188
3189         return ( (WCC!= NULL) && 
3190                  ((WCC->axlevel >= 6) || 
3191                   ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) ||
3192                   (WCC->CurRoom.is_inbox) ));
3193 }
3194
3195 int ConditionalIsRoomtype(StrBuf *Target, WCTemplputParams *TP)
3196 {
3197         wcsession *WCC = WC;
3198
3199         if ((WCC == NULL) ||
3200             (TP->Tokens->nParameters < 3))
3201         {
3202                 return ((WCC->CurRoom.view < VIEW_BBS) || 
3203                         (WCC->CurRoom.view > VIEW_MAX));
3204         }
3205
3206         return WCC->CurRoom.view == GetTemplateTokenNumber(Target, TP, 2, VIEW_BBS);
3207 }
3208
3209
3210 HashList *GetWhoKnowsHash(StrBuf *Target, WCTemplputParams *TP)
3211 {
3212         wcsession *WCC = WC;
3213         StrBuf *Line;
3214         StrBuf *Token;
3215         long State;
3216         HashList *Whok = NULL;
3217         int Done = 0;
3218         int n;
3219
3220         serv_puts("WHOK");
3221         Line = NewStrBuf();
3222         StrBuf_ServGetln(Line);
3223         if (GetServerStatus(Line, &State) == 1) 
3224         {
3225                 Whok = NewHash(1, Flathash);
3226                 while(!Done && StrBuf_ServGetln(Line))
3227                         if ( (StrLength(Line)==3) && 
3228                              !strcmp(ChrPtr(Line), "000")) 
3229                         {
3230                                 Done = 1;
3231                         }
3232                         else
3233                         {
3234                         
3235                                 const char *Pos = NULL;
3236                                 Token = NewStrBufPlain (NULL, StrLength(Line));
3237                                 StrBufExtract_NextToken(Token, Line, &Pos, '|');
3238
3239                                 Put(Whok, 
3240                                     IKEY(n),
3241                                     Token, 
3242                                     HFreeStrBuf);
3243                         }
3244         }
3245         else if (State == 550)
3246                 StrBufAppendBufPlain(WCC->ImportantMsg,
3247                                      _("Higher access is required to access this function."), -1, 0);
3248
3249
3250         FreeStrBuf(&Line);
3251         return Whok;
3252 }
3253
3254 void _FlushRoomList(wcsession *WCC)
3255 {
3256         free_march_list(WCC);
3257         DeleteHash(&WCC->Floors);
3258         DeleteHash(&WCC->Rooms);
3259         DeleteHash(&WCC->FloorsByName);
3260 }
3261
3262 void FlushRoomlist(void)
3263 {
3264         wcsession *WCC = WC;
3265         _FlushRoomList(WCC);
3266 }
3267
3268
3269 void 
3270 InitModule_ROOMOPS
3271 (void)
3272 {
3273         initialize_viewdefs();
3274         RegisterPreference("roomlistview",
3275                            _("Room list view"),
3276                            PRF_STRING,
3277                            NULL);
3278         RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO, NULL);
3279
3280         RegisterNamespace("ROOMNAME", 0, 1, tmplput_RoomName, NULL, CTX_NONE);
3281
3282
3283         WebcitAddUrlHandler(HKEY("knrooms"), "", 0, knrooms, 0);
3284         WebcitAddUrlHandler(HKEY("dotgoto"), "", 0, dotgoto, NEED_URL);
3285         WebcitAddUrlHandler(HKEY("dotskip"), "", 0, dotskip, NEED_URL);
3286
3287         WebcitAddUrlHandler(HKEY("goto_private"), "", 0, goto_private, NEED_URL);
3288         WebcitAddUrlHandler(HKEY("zap"), "", 0, zap, 0);
3289         WebcitAddUrlHandler(HKEY("display_entroom"), "", 0, display_entroom, 0);
3290         WebcitAddUrlHandler(HKEY("entroom"), "", 0, entroom, 0);
3291         WebcitAddUrlHandler(HKEY("display_whok"), "", 0, display_whok, 0);
3292         WebcitAddUrlHandler(HKEY("do_invt_kick"), "", 0, do_invt_kick, 0);
3293         WebcitAddUrlHandler(HKEY("display_editroom"), "", 0, display_editroom, 0);
3294         WebcitAddUrlHandler(HKEY("netedit"), "", 0, netedit, 0);
3295         WebcitAddUrlHandler(HKEY("editroom"), "", 0, editroom, 0);
3296         WebcitAddUrlHandler(HKEY("delete_room"), "", 0, delete_room, 0);
3297         WebcitAddUrlHandler(HKEY("set_room_policy"), "", 0, set_room_policy, 0);
3298         WebcitAddUrlHandler(HKEY("changeview"), "", 0, change_view, 0);
3299         WebcitAddUrlHandler(HKEY("toggle_self_service"), "", 0, toggle_self_service, 0);
3300         RegisterNamespace("ROOMBANNER", 0, 1, tmplput_roombanner, NULL, CTX_NONE);
3301
3302         RegisterConditional(HKEY("COND:ROOM:TYPE_IS"), 0, ConditionalIsRoomtype, CTX_NONE);
3303         RegisterConditional(HKEY("COND:THISROOM:FLAG:QR"), 0, ConditionalCurrentRoomHas_QRFlag, CTX_NONE);
3304         RegisterConditional(HKEY("COND:ROOM:FLAG:QR"), 0, ConditionalRoomHas_QRFlag, CTX_ROOMS);
3305
3306         RegisterConditional(HKEY("COND:THISROOM:FLAG:QR2"), 0, ConditionalCurrentRoomHas_QRFlag2, CTX_NONE);
3307         RegisterConditional(HKEY("COND:ROOM:FLAG:QR2"), 0, ConditionalRoomHas_QRFlag2, CTX_ROOMS);
3308         RegisterConditional(HKEY("COND:ROOM:FLAG:UA"), 0, ConditionalRoomHas_UAFlag, CTX_ROOMS);
3309
3310         RegisterIterator("ITERATE:THISROOM:WHO_KNOWS", 0, NULL, GetWhoKnowsHash, NULL, DeleteHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
3311         RegisterNamespace("THISROOM:MSGS:NEW", 0, 0, tmplput_CurrentRoom_nNewMessages, NULL, CTX_NONE);
3312         RegisterNamespace("THISROOM:MSGS:TOTAL", 0, 0, tmplput_CurrentRoom_nTotalMessages, NULL, CTX_NONE);
3313
3314         RegisterNamespace("THISROOM:FLOOR:NAME", 0, 1, tmplput_CurrentRoomFloorName, NULL, CTX_NONE);
3315         RegisterNamespace("THISROOM:AIDE", 0, 1, tmplput_CurrentRoomAide, NULL, CTX_NONE);
3316         RegisterNamespace("THISROOM:PASS", 0, 1, tmplput_CurrentRoomPass, NULL, CTX_NONE);
3317         RegisterNamespace("THISROOM:DIRECTORY", 0, 1, tmplput_CurrentRoomDirectory, NULL, CTX_NONE);
3318         RegisterNamespace("THISROOM:ORDER", 0, 0, tmplput_CurrentRoomOrder, NULL, CTX_NONE);
3319         RegisterNamespace("THISROOM:DEFAULT_VIEW", 0, 0, tmplput_CurrentRoomDefView, NULL, CTX_NONE);
3320         RegisterConditional(HKEY("COND:THISROOM:HAVE_VIEW"), 0, ConditionalThisRoomHaveView, CTX_NONE);
3321         RegisterConditional(HKEY("COND:ALLOWED_DEFAULT_VIEW"), 0, ConditionalIsAllowedDefaultView, CTX_NONE);
3322
3323         RegisterNamespace("THISROOM:VIEW_STRING", 0, 1, tmplput_CurrentRoomViewString, NULL, CTX_NONE);
3324         RegisterNamespace("ROOM:VIEW_STRING", 1, 2, tmplput_RoomViewString, NULL, CTX_NONE);
3325
3326         RegisterNamespace("THISROOM:INFOTEXT", 1, 2, tmplput_CurrentRoomInfoText, NULL, CTX_NONE);
3327         RegisterConditional(HKEY("COND:THISROOM:ORDER"), 0, ConditionalThisRoomOrder, CTX_NONE);
3328         RegisterConditional(HKEY("COND:THISROOM:DEFAULT_VIEW"), 0, ConditionalThisRoomDefView, CTX_NONE);
3329         RegisterConditional(HKEY("COND:THISROOM:CURR_VIEW"), 0, ConditionalThisRoomCurrView, CTX_NONE);
3330         RegisterConditional(HKEY("COND:THISROOM:HAVE_PIC"), 0, ConditionalThisRoomXHavePic, CTX_NONE);
3331         RegisterConditional(HKEY("COND:THISROOM:HAVE_INFOTEXT"), 0, ConditionalThisRoomXHaveInfoText, CTX_NONE);
3332         RegisterNamespace("THISROOM:FILES:N", 0, 1, tmplput_CurrentRoomXNFiles, NULL, CTX_NONE);
3333         RegisterNamespace("THISROOM:FILES:STR", 0, 1, tmplput_CurrentRoomX_FileString, NULL, CTX_NONE);
3334
3335         REGISTERTokenParamDefine(QR_PERMANENT);
3336         REGISTERTokenParamDefine(QR_INUSE);
3337         REGISTERTokenParamDefine(QR_PRIVATE);
3338         REGISTERTokenParamDefine(QR_PASSWORDED);
3339         REGISTERTokenParamDefine(QR_GUESSNAME);
3340         REGISTERTokenParamDefine(QR_DIRECTORY);
3341         REGISTERTokenParamDefine(QR_UPLOAD);
3342         REGISTERTokenParamDefine(QR_DOWNLOAD);
3343         REGISTERTokenParamDefine(QR_VISDIR);
3344         REGISTERTokenParamDefine(QR_ANONONLY);
3345         REGISTERTokenParamDefine(QR_ANONOPT);
3346         REGISTERTokenParamDefine(QR_NETWORK);
3347         REGISTERTokenParamDefine(QR_PREFONLY);
3348         REGISTERTokenParamDefine(QR_READONLY);
3349         REGISTERTokenParamDefine(QR_MAILBOX);
3350         REGISTERTokenParamDefine(QR2_SYSTEM);
3351         REGISTERTokenParamDefine(QR2_SELFLIST);
3352         REGISTERTokenParamDefine(QR2_COLLABDEL);
3353         REGISTERTokenParamDefine(QR2_SUBJECTREQ);
3354         REGISTERTokenParamDefine(QR2_SMTP_PUBLIC);
3355         REGISTERTokenParamDefine(QR2_MODERATED);
3356
3357         REGISTERTokenParamDefine(UA_KNOWN);
3358         REGISTERTokenParamDefine(UA_GOTOALLOWED);
3359         REGISTERTokenParamDefine(UA_HASNEWMSGS);
3360         REGISTERTokenParamDefine(UA_ZAPPED);
3361         REGISTERTokenParamDefine(UA_POSTALLOWED);
3362         REGISTERTokenParamDefine(UA_ADMINALLOWED);
3363         REGISTERTokenParamDefine(UA_DELETEALLOWED);
3364         REGISTERTokenParamDefine(UA_ISTRASH);
3365
3366         REGISTERTokenParamDefine(US_NEEDVALID);
3367         REGISTERTokenParamDefine(US_PERM);
3368         REGISTERTokenParamDefine(US_LASTOLD);
3369         REGISTERTokenParamDefine(US_EXPERT);
3370         REGISTERTokenParamDefine(US_UNLISTED);
3371         REGISTERTokenParamDefine(US_NOPROMPT);
3372         REGISTERTokenParamDefine(US_PROMPTCTL);
3373         REGISTERTokenParamDefine(US_DISAPPEAR);
3374         REGISTERTokenParamDefine(US_REGIS);
3375         REGISTERTokenParamDefine(US_PAGINATOR);
3376         REGISTERTokenParamDefine(US_INTERNET);
3377         REGISTERTokenParamDefine(US_FLOORS);
3378         REGISTERTokenParamDefine(US_COLOR);
3379         REGISTERTokenParamDefine(US_USER_SET);
3380
3381         REGISTERTokenParamDefine(VIEW_BBS);
3382         REGISTERTokenParamDefine(VIEW_MAILBOX); 
3383         REGISTERTokenParamDefine(VIEW_ADDRESSBOOK);
3384         REGISTERTokenParamDefine(VIEW_CALENDAR);        
3385         REGISTERTokenParamDefine(VIEW_TASKS);   
3386         REGISTERTokenParamDefine(VIEW_NOTES);           
3387         REGISTERTokenParamDefine(VIEW_WIKI);            
3388         REGISTERTokenParamDefine(VIEW_CALBRIEF);
3389         REGISTERTokenParamDefine(VIEW_JOURNAL);
3390         REGISTERTokenParamDefine(VIEW_BLOG);
3391
3392         /* GNET types: */
3393         REGISTERTokenParamDefine(ignet_push_share);
3394         { /* these are the parts of an IGNET push config */
3395                 REGISTERTokenParamDefine(GNET_IGNET_NODE);
3396                 REGISTERTokenParamDefine(GNET_IGNET_ROOM);
3397         }
3398         REGISTERTokenParamDefine(listrecp);
3399         REGISTERTokenParamDefine(digestrecp);
3400         REGISTERTokenParamDefine(pop3client);
3401         { /* These are the parts of a pop3 client line... */
3402                 REGISTERTokenParamDefine(GNET_POP3_HOST);
3403                 REGISTERTokenParamDefine(GNET_POP3_USER);
3404                 REGISTERTokenParamDefine(GNET_POP3_DONT_DELETE_REMOTE);
3405                 REGISTERTokenParamDefine(GNET_POP3_INTERVAL);
3406         }
3407         REGISTERTokenParamDefine(rssclient);
3408         REGISTERTokenParamDefine(participate);
3409
3410         RegisterConditional(HKEY("COND:ROOMAIDE"), 2, ConditionalRoomAide, CTX_NONE);
3411         RegisterConditional(HKEY("COND:ACCESS:DELETE"), 2, ConditionalRoomAcessDelete, CTX_NONE);
3412
3413         RegisterConditional(HKEY("COND:UNGOTO"), 0, ConditionalHaveUngoto, CTX_NONE);
3414         RegisterConditional(HKEY("COND:ROOM:EDITACCESS"), 0, ConditionalHaveRoomeditRights, CTX_NONE);
3415
3416         RegisterNamespace("CURRENT_ROOM", 0, 1, tmplput_current_room, NULL, CTX_NONE);
3417         RegisterNamespace("ROOM:UNGOTO", 0, 0, tmplput_ungoto, NULL, CTX_NONE);
3418         RegisterIterator("FLOORS", 0, NULL, GetFloorListHash, NULL, NULL, CTX_FLOORS, CTX_NONE, IT_NOFLAG);
3419
3420
3421 }
3422
3423
3424 void 
3425 SessionDestroyModule_ROOMOPS
3426 (wcsession *sess)
3427 {
3428         FlushFolder(&sess->CurRoom);
3429         if (sess->cache_fold != NULL) {
3430                 free(sess->cache_fold);
3431         }
3432         
3433         _FlushRoomList (sess);
3434 }
3435
3436
3437 /*@}*/