* add dummy wiki conditionals
[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
9 char *viewdefs[VIEW_MAX];                       /* the different kinds of available views */
10
11 ROOM_VIEWS exchangeable_views[VIEW_MAX][VIEW_MAX] = {   /* the different kinds of available views for a view */
12 {VIEW_BBS, VIEW_MAILBOX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
13 {VIEW_BBS, VIEW_MAILBOX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
14 {VIEW_MAX, VIEW_MAX, VIEW_ADDRESSBOOK, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX }, 
15 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX /*VIEW_CALBRIEF*/, VIEW_MAX, VIEW_MAX }, 
16 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_TASKS, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, },
17 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_NOTES, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, },
18 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_WIKI, VIEW_MAX, VIEW_MAX, VIEW_MAX}, 
19 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_CALENDAR, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX/*VIEW_CALBRIEF*/, VIEW_MAX, VIEW_MAX},
20 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_JOURNAL, VIEW_MAX }, 
21 {VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_MAX, VIEW_BLOG }, 
22         };
23 /* the brief calendar view is disabled: VIEW_CALBRIEF */
24
25 ROOM_VIEWS allowed_default_views[VIEW_MAX] = {
26         1, /* VIEW_BBS          Bulletin board view */
27         1, /* VIEW_MAILBOX              Mailbox summary */
28         1, /* VIEW_ADDRESSBOOK  Address book view */
29         1, /* VIEW_CALENDAR             Calendar view */
30         1, /* VIEW_TASKS                Tasks view */
31         1, /* VIEW_NOTES                Notes view */
32         1, /* VIEW_WIKI         Wiki view */
33         0, /* VIEW_CALBRIEF             Brief Calendar view */
34         0, /* VIEW_JOURNAL              Journal view */
35         0  /* VIEW_BLOG         Blog view (not yet implemented) */
36 };
37
38
39 /*
40  * Initialize the viewdefs with localized strings
41  */
42 void initialize_viewdefs(void) {
43         viewdefs[VIEW_BBS] = _("Bulletin Board");
44         viewdefs[VIEW_MAILBOX] = _("Mail Folder");
45         viewdefs[VIEW_ADDRESSBOOK] = _("Address Book");
46         viewdefs[VIEW_CALENDAR] = _("Calendar");
47         viewdefs[VIEW_TASKS] = _("Task List");
48         viewdefs[VIEW_NOTES] = _("Notes List");
49         viewdefs[VIEW_WIKI] = _("Wiki");
50         viewdefs[VIEW_CALBRIEF] = _("Calendar List");
51         viewdefs[VIEW_JOURNAL] = _("Journal");
52         viewdefs[VIEW_BLOG] = _("Blog");
53 }
54
55 ConstStr QRFlagList[] = {
56         {HKEY(strof(QR_PERMANENT))},
57         {HKEY(strof(QR_INUSE))},
58         {HKEY(strof(QR_PRIVATE))},
59         {HKEY(strof(QR_PASSWORDED))},
60         {HKEY(strof(QR_GUESSNAME))},
61         {HKEY(strof(QR_DIRECTORY))},
62         {HKEY(strof(QR_UPLOAD))},
63         {HKEY(strof(QR_DOWNLOAD))},
64         {HKEY(strof(QR_VISDIR))},
65         {HKEY(strof(QR_ANONONLY))},
66         {HKEY(strof(QR_ANONOPT))},
67         {HKEY(strof(QR_NETWORK))},
68         {HKEY(strof(QR_PREFONLY))},
69         {HKEY(strof(QR_READONLY))},
70         {HKEY(strof(QR_MAILBOX))}
71 };
72 ConstStr QR2FlagList[] = {
73         {HKEY(strof(QR2_SYSTEM))},
74         {HKEY(strof(QR2_SELFLIST))},
75         {HKEY(strof(QR2_COLLABDEL))},
76         {HKEY(strof(QR2_SUBJECTREQ))},
77         {HKEY(strof(QR2_SMTP_PUBLIC))},
78         {HKEY(strof(QR2_MODERATED))},
79         {HKEY("")}, 
80         {HKEY("")}, 
81         {HKEY("")}, 
82         {HKEY("")}, 
83         {HKEY("")}, 
84         {HKEY("")}, 
85         {HKEY("")}, 
86         {HKEY("")}, 
87         {HKEY("")}
88 };
89
90 void DBG_QR(long QR)
91 {
92         int i = 1;
93         int j=0;
94         StrBuf *QRVec;
95
96         QRVec = NewStrBufPlain(NULL, 256);
97         while (i != 0)
98         {
99                 if ((QR & i) != 0) {
100                         if (StrLength(QRVec) > 0)
101                                 StrBufAppendBufPlain(QRVec, HKEY(" | "), 0);
102                         StrBufAppendBufPlain(QRVec, CKEY(QRFlagList[j]), 0);
103                 }
104                 i = i << 1;
105                 j++;
106         }
107         lprintf(9, "DBG: QR-Vec [%ld] [%s]\n", QR, ChrPtr(QRVec));
108         FreeStrBuf(&QRVec);
109 }
110
111
112
113 void DBG_QR2(long QR2)
114 {
115         int i = 1;
116         int j=0;
117         StrBuf *QR2Vec;
118
119         QR2Vec = NewStrBufPlain(NULL, 256);
120         while (i != 0)
121         {
122                 if ((QR2 & i) != 0) {
123                         if (StrLength(QR2Vec) > 0)
124                                 StrBufAppendBufPlain(QR2Vec, HKEY(" | "), 0);
125                         StrBufAppendBufPlain(QR2Vec, CKEY(QR2FlagList[j]), 0);
126                 }
127                 i = i << 1;
128                 j++;
129         }
130         lprintf(9, "DBG: QR2-Vec [%ld] [%s]\n", QR2, ChrPtr(QR2Vec));
131         FreeStrBuf(&QR2Vec);
132 }
133
134
135 /*
136  * Embed the room banner
137  *
138  * got                  The information returned from a GOTO server command
139  * navbar_style         Determines which navigation buttons to display
140  *
141  */
142
143 void embed_room_banner(void) 
144 {
145         wcsession *WCC = WC;
146         char buf[256];
147
148         /* refresh current room states... */
149         /* dosen't work??? gotoroom(NULL); */
150
151         /* The browser needs some information for its own use */
152         wc_printf("<script type=\"text/javascript\">    \n"
153                   "     room_is_trash = %d;             \n"
154                   "</script>\n",
155                   ((WC->CurRoom.RAFlags & UA_ISTRASH) != 0)
156                 );
157
158         /*
159          * If the user happens to select the "make this my start page" link,
160          * we want it to remember the URL as a "/dotskip" one instead of
161          * a "skip" or "gotonext" or something like that.
162          */
163         if (WCC->Hdr->this_page == NULL) {
164                 WCC->Hdr->this_page = NewStrBuf();
165         }
166         StrBufPrintf(WCC->Hdr->this_page, 
167                      "dotskip?room=%s",
168                      ChrPtr(WC->CurRoom.name)
169                 );
170
171         do_template("roombanner", NULL);
172         /* roombanner contains this for mobile */
173         if (WC->is_mobile)
174                 return;
175
176         do_template("navbar", NULL);
177 /*
178         case VIEW_WIKI:
179                 wc_printf(
180                         "<li class=\"readallmess\">"
181                         "<a href=\"wiki?page=home\">"
182                         "<img src=\"static/readallmess3_24x.gif\" "
183                         "alt=\"\" width=\"24\" height=\"24\">"
184                         "<span class=\"navbar_link\">"
185                         "%s"
186                         "</span></a></li>\n", _("Wiki home")
187                         );
188                 safestrncpy(buf, bstr("page"), sizeof buf);
189                 if (IsEmptyStr(buf)) {
190                         safestrncpy(buf, "home", sizeof buf);
191                 }
192                 str_wiki_index(buf);
193                 wc_printf(
194                         "<li class=\"newmess\">"
195                         "<a href=\"display_enter?page=%s\">"
196                         "<img  src=\"static/newmess3_24x.gif\" "
197                         "alt=\"\" width=\"24\" height=\"24\">"
198                         "<span class=\"navbar_link\">"
199                         "%s"
200                         "</span></a></li>\n", buf, _("Edit this page")
201                         );
202                 
203                 if (bmstrcasestr((char *)ChrPtr(WCC->Hdr->HR.ReqLine), "wiki_history")) {
204                         / * already viewing history; display a link to the current page * /
205                         wc_printf(
206                                 "<li class=\"newmess\">"
207                                 "<a href=\"wiki?page=%s\">"
208                                 "<img  src=\"static/newmess3_24x.gif\" "
209                                 "alt=\"\" width=\"24\" height=\"24\">"
210                                 "<span class=\"navbar_link\">"
211                                 "%s"
212                                 "</span></a></li>\n", buf, _("Current version")
213                                 );
214                 }
215                 else {
216                         / * display a link to the history * /
217                         wc_printf(
218                                 "<li class=\"newmess\">"
219                                 "<a href=\"wiki_history?page=%s\">"
220                                 "<img  src=\"static/newmess3_24x.gif\" "
221                                 "alt=\"\" width=\"24\" height=\"24\">"
222                                 "<span class=\"navbar_link\">"
223                                 "%s"
224                                 "</span></a></li>\n", buf, _("History")
225                                 );
226                 }
227                 break;
228 */
229 }
230
231
232 /*
233  * back end routine to take the session to a new room
234  */
235 long gotoroom(const StrBuf *gname)
236 {
237         wcsession *WCC = WC;
238         StrBuf *Buf;
239         static long ls = (-1L);
240         long err = 0;
241
242         /* store ungoto information */
243         if (StrLength(gname) > 0)
244                 strcpy(WCC->ugname, ChrPtr(WCC->CurRoom.name));
245         WCC->uglsn = ls;
246         Buf = NewStrBuf();
247
248         /* move to the new room */
249         if (StrLength(gname) > 0)
250                 serv_printf("GOTO %s", ChrPtr(gname));
251         else /* or just refresh the current state... */
252                 serv_printf("GOTO 00000000000000000000");
253         StrBuf_ServGetln(Buf);
254         if  (GetServerStatus(Buf, &err) != 2) {
255                 serv_puts("GOTO _BASEROOM_");
256                 StrBuf_ServGetln(Buf);
257                 /* 
258                  * well, we know that this is the fallback case, 
259                  * but we're interested that the first command 
260                  * didn't work out in first place.
261                  */
262                 if (GetServerStatus(Buf, NULL) != 2) {
263                         FreeStrBuf(&Buf);
264                         return err;
265                 }
266         }
267         FlushFolder(&WCC->CurRoom);
268         ParseGoto(&WCC->CurRoom, Buf);
269
270         if (StrLength(gname) > 0)
271         {
272                 remove_march(WCC->CurRoom.name);
273                 if (!strcasecmp(ChrPtr(gname), "_BASEROOM_"))
274                         remove_march(gname);
275         }
276         FreeStrBuf(&Buf);
277
278         return err;
279 }
280
281
282
283 void ParseGoto(folder *room, StrBuf *Line)
284 {
285         wcsession *WCC = WC;
286         const char *Pos;
287         int flag;
288         void *vFloor = NULL;
289         StrBuf *pBuf;
290
291         if (StrLength(Line) < 4) {
292                 return;
293         }
294         
295         /* ignore the commandstate... */
296         Pos = ChrPtr(Line) + 4;
297
298         if (room->RoomNameParts != NULL)
299         {
300                 int i;
301                 for (i=0; i < room->nRoomNameParts; i++)
302                         FreeStrBuf(&room->RoomNameParts[i]);
303                 free(room->RoomNameParts);
304                 room->RoomNameParts = NULL;
305         }
306
307         pBuf = room->name;  
308         if (pBuf == NULL)
309                 pBuf = NewStrBufPlain(NULL, StrLength(Line));
310         else
311                 FlushStrBuf(pBuf);
312         memset(room, 0, sizeof(folder));
313         room->name = pBuf;
314
315         StrBufExtract_NextToken(room->name, Line, &Pos, '|'); // WC->CurRoom->name
316
317         room->nNewMessages = StrBufExtractNext_long(Line, &Pos, '|'); 
318         if (room->nNewMessages > 0)
319                 room->RAFlags |= UA_HASNEWMSGS;
320
321         room->nTotalMessages = StrBufExtractNext_long(Line, &Pos, '|');
322
323         room->ShowInfo =  StrBufExtractNext_long(Line, &Pos, '|');
324         
325         room->QRFlags = StrBufExtractNext_long(Line, &Pos, '|'); //CurRoom->QRFlags
326
327         DBG_QR(room->QRFlags);
328
329         room->HighestRead = StrBufExtractNext_long(Line, &Pos, '|');
330         room->LastMessageRead = StrBufExtractNext_long(Line, &Pos, '|');
331
332         room->is_inbox = StrBufExtractNext_long(Line, &Pos, '|'); // is_mailbox
333
334         flag = StrBufExtractNext_long(Line, &Pos, '|');
335         if (WCC->is_aide || flag) {
336                 room->RAFlags |= UA_ADMINALLOWED;
337         }
338
339         room->UsersNewMAilboxMessages = StrBufExtractNext_long(Line, &Pos, '|');
340
341         room->floorid = StrBufExtractNext_int(Line, &Pos, '|'); // wc_floor
342
343         room->view = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->view
344
345         room->defview = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->defview
346
347         flag = StrBufExtractNext_long(Line, &Pos, '|');
348         if (flag)
349                 room->RAFlags |= UA_ISTRASH; // wc_is_trash
350
351         room->QRFlags2 = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->QRFlags2
352         DBG_QR2(room->QRFlags2);
353
354         /* find out, whether we are in a sub-room */
355         room->nRoomNameParts = StrBufNum_tokens(room->name, '\\');
356         if (room->nRoomNameParts > 1)
357         {
358                 int i;
359                 
360                 Pos = NULL;
361                 room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1));
362                 memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1));
363                 for (i=0; i < room->nRoomNameParts; i++)
364                 {
365                         room->RoomNameParts[i] = NewStrBuf();
366                         StrBufExtract_NextToken(room->RoomNameParts[i],
367                                                 room->name, &Pos, '\\');
368                 }
369         }
370
371         /* Private mailboxes on the main floor get remapped to the personal folder */
372         if ((room->QRFlags & QR_MAILBOX) && 
373             (room->floorid == 0))
374         {
375                 room->floorid = VIRTUAL_MY_FLOOR;
376                 if ((room->nRoomNameParts == 1) && 
377                     (StrLength(room->name) == 4) && 
378                     (strcmp(ChrPtr(room->name), "Mail") == 0))
379                 {
380                         room->is_inbox = 1;
381                 }
382                 
383         }
384         /* get a pointer to the floor we're on: */
385         if (WCC->Floors == NULL)
386                 GetFloorListHash(NULL, NULL);
387
388         GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
389         room->Floor = (const Floor*) vFloor;
390 }
391
392 void LoadRoomAide(void)
393 {
394         wcsession *WCC = WC;
395         StrBuf *Buf;
396         
397         if (WCC->CurRoom.RoomAideLoaded)
398                 return;
399
400         WCC->CurRoom.RoomAideLoaded = 1;
401         Buf = NewStrBuf();
402         serv_puts("GETA");
403         StrBuf_ServGetln(Buf);
404         if (GetServerStatus(Buf, NULL) != 2) {
405                 FlushStrBuf(WCC->CurRoom.RoomAide);
406                 AppendImportantMessage (ChrPtr(Buf) + 4, 
407                                         StrLength(Buf) - 4);
408         } else {
409                 const char *Pos;
410
411                 Pos = ChrPtr(Buf) + 4;
412
413                 FreeStrBuf(&WCC->CurRoom.RoomAide);
414                 WCC->CurRoom.RoomAide = NewStrBufPlain (NULL, StrLength (Buf));
415
416                 StrBufExtract_NextToken(WCC->CurRoom.RoomAide, Buf, &Pos, '|'); 
417         }
418         FreeStrBuf (&Buf);
419 }
420
421 int SaveRoomAide(folder *Room)
422 {
423         StrBuf *Buf;
424         Buf = NewStrBuf ();
425         serv_printf("SETA %s", ChrPtr(Room->RoomAide));
426         StrBuf_ServGetln(Buf);
427         if (GetServerStatus(Buf, NULL) != 2) {
428                 StrBufCutLeft(Buf, 4);
429                 AppendImportantMessage (SKEY(Buf));
430                 FreeStrBuf(&Buf);
431                 return 0;
432         }
433         FreeStrBuf(&Buf);
434         return 1;
435 }
436
437 void tmplput_CurrentRoomFloorName(StrBuf *Target, WCTemplputParams *TP) 
438 {
439         wcsession *WCC = WC;
440         folder *Folder = &WCC->CurRoom;
441         const Floor *pFloor;
442
443         if (Folder == NULL)
444                 return;
445
446         pFloor = Folder->Floor;
447         if (pFloor == NULL)
448                 return;
449
450         StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
451 }
452
453 void tmplput_CurrentRoomAide(StrBuf *Target, WCTemplputParams *TP) 
454 {
455         wcsession *WCC = WC;
456
457         LoadRoomAide();
458
459         StrBufAppendTemplate(Target, TP, WCC->CurRoom.RoomAide, 0);
460 }
461
462 int GetCurrentRoomFlags(folder *Room)
463 {
464         StrBuf *Buf;
465
466         Buf = NewStrBuf();
467         serv_puts("GETR");
468         StrBuf_ServGetln(Buf);
469         if (GetServerStatus(Buf, NULL) != 2) {
470                 FlushStrBuf(Room->XAPass);
471                 FlushStrBuf(Room->Directory);
472                 StrBufCutLeft(Buf, 4);
473                 AppendImportantMessage (SKEY(Buf));
474                 FreeStrBuf(&Buf);
475                 return 0;
476         } else {
477                 const char *Pos;
478
479                 Pos = ChrPtr(Buf) + 4;
480
481                 FreeStrBuf(&Room->XAPass);
482                 FreeStrBuf(&Room->Directory);
483
484                 Room->XAPass = NewStrBufPlain (NULL, StrLength (Buf));
485                 Room->Directory = NewStrBufPlain (NULL, StrLength (Buf));
486
487                 FreeStrBuf(&Room->name);
488                 Room->name = NewStrBufPlain(NULL, StrLength(Buf));
489                 StrBufExtract_NextToken(Room->name, Buf, &Pos, '|'); 
490                                         
491                 StrBufExtract_NextToken(Room->XAPass, Buf, &Pos, '|'); 
492                 StrBufExtract_NextToken(Room->Directory, Buf, &Pos, '|'); 
493                 
494                 Room->QRFlags = StrBufExtractNext_long(Buf, &Pos, '|');
495                 Room->floorid = StrBufExtractNext_long(Buf, &Pos, '|');
496                 Room->Order = StrBufExtractNext_long(Buf, &Pos, '|');
497                 Room->defview = StrBufExtractNext_long(Buf, &Pos, '|');
498                 Room->QRFlags2 = StrBufExtractNext_long(Buf, &Pos, '|');
499                 FreeStrBuf (&Buf);
500                 Room->XALoaded = 1;
501                 return 1;
502         }
503 }
504
505
506 int SetCurrentRoomFlags(folder *Room)
507 {
508         StrBuf *Buf;
509
510         Buf = NewStrBuf();
511         DBG_QR(Room->QRFlags);
512         DBG_QR2(Room->QRFlags2);
513
514         serv_printf("SETR %s|%s|%s|%ld|%d|%d|%ld|%ld|%ld",
515                     ChrPtr(Room->name),
516                     ChrPtr(Room->XAPass),
517                     ChrPtr(Room->Directory),
518                     Room->QRFlags, 
519                     Room->BumpUsers,
520                     Room->floorid, 
521                     Room->Order,
522                     Room->defview,
523                     Room->QRFlags2);
524
525         StrBuf_ServGetln(Buf);
526         if (GetServerStatus(Buf, NULL) != 2) {
527                 StrBufCutLeft(Buf, 4);
528                 AppendImportantMessage (SKEY(Buf));
529                 FreeStrBuf(&Buf);
530                 return 0;
531         } else {
532                 FreeStrBuf(&Buf);
533                 return 1;
534         }
535 }
536
537 void LoadRoomXA (void)
538 {
539         wcsession *WCC = WC;
540                 
541         if (WCC->CurRoom.XALoaded)
542                 return;
543
544         GetCurrentRoomFlags(&WCC->CurRoom);
545 }
546
547
548 void LoadXRoomPic(void)
549 {
550         wcsession *WCC = WC;
551         StrBuf *Buf;
552         
553         if (WCC->CurRoom.XHaveRoomPicLoaded)
554                 return;
555
556         WCC->CurRoom.XHaveRoomPicLoaded = 1;
557         Buf = NewStrBuf();
558         serv_puts("OIMG _roompic_");
559         StrBuf_ServGetln(Buf);
560         if (GetServerStatus(Buf, NULL) != 2) {
561                 WCC->CurRoom.XHaveRoomPic = 0;
562         } else {
563                 WCC->CurRoom.XHaveRoomPic = 1;
564         }
565         serv_puts("CLOS");
566         StrBuf_ServGetln(Buf);
567         GetServerStatus(Buf, NULL);
568         FreeStrBuf (&Buf);
569 }
570
571 int ConditionalThisRoomXHavePic(StrBuf *Target, WCTemplputParams *TP)
572 {
573         wcsession *WCC = WC;
574         
575         if (WCC == NULL)
576                 return 0;
577
578         LoadXRoomPic();
579         return WCC->CurRoom.XHaveRoomPic == 1;
580 }
581
582 void LoadXRoomInfoText(void)
583 {
584         wcsession *WCC = WC;
585         StrBuf *Buf;
586         int Done = 0;
587         
588         if (WCC->CurRoom.XHaveInfoTextLoaded)
589                 return;
590
591         WCC->CurRoom.XHaveInfoTextLoaded = 1;
592         Buf = NewStrBuf();
593
594         serv_puts("RINF");
595
596         StrBuf_ServGetln(Buf);
597         if (GetServerStatus(Buf, NULL) == 1) {
598                 WCC->CurRoom.XInfoText = NewStrBuf ();
599                 
600                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
601                         if ( (StrLength(Buf)==3) && 
602                              !strcmp(ChrPtr(Buf), "000")) 
603                                 Done = 1;
604                         else 
605                                 StrBufAppendBuf(WCC->CurRoom.XInfoText, Buf, 0);
606                 }
607         }
608
609         FreeStrBuf (&Buf);
610 }
611
612 int ConditionalThisRoomXHaveInfoText(StrBuf *Target, WCTemplputParams *TP)
613 {
614         wcsession *WCC = WC;
615         
616         if (WCC == NULL)
617                 return 0;
618
619         LoadXRoomInfoText();
620         return (StrLength(WCC->CurRoom.XInfoText)>0);
621 }
622
623 void tmplput_CurrentRoomInfoText(StrBuf *Target, WCTemplputParams *TP) 
624 {
625         wcsession *WCC = WC;
626
627         LoadXRoomInfoText();
628
629         StrBufAppendTemplate(Target, TP, WCC->CurRoom.XAPass, 1);
630 }
631
632 void LoadXRoomXCountFiles(void)
633 {
634         wcsession *WCC = WC;
635         StrBuf *Buf;
636         int Done = 0;
637         
638         if (WCC->CurRoom.XHaveDownloadCount)
639                 return;
640
641         WCC->CurRoom.XHaveDownloadCount = 1;
642
643         Buf = NewStrBuf();
644         serv_puts("RDIR");
645         StrBuf_ServGetln(Buf);
646         if (GetServerStatus(Buf, NULL) == 1) {
647                 
648                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
649                         if ( (StrLength(Buf)==3) && 
650                              !strcmp(ChrPtr(Buf), "000")) 
651                                 Done = 1;
652                         else 
653                                 WCC->CurRoom.XDownloadCount++;
654                 }
655         }
656
657         FreeStrBuf (&Buf);
658 }
659
660 void tmplput_CurrentRoomXNFiles(StrBuf *Target, WCTemplputParams *TP) 
661 {
662         wcsession *WCC = WC;
663
664         LoadXRoomXCountFiles();
665
666         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.XDownloadCount);
667 }
668
669 void tmplput_CurrentRoomX_FileString(StrBuf *Target, WCTemplputParams *TP) 
670 {
671         wcsession *WCC = WC;
672
673         LoadXRoomXCountFiles();
674
675         if (WCC->CurRoom.XDownloadCount == 1)
676                 StrBufAppendBufPlain(Target, _("file"), -1, 0);
677         else
678                 StrBufAppendBufPlain(Target, _("files"), -1, 0);
679 }
680
681 void tmplput_CurrentRoomPass(StrBuf *Target, WCTemplputParams *TP) 
682 {
683         wcsession *WCC = WC;
684
685         LoadRoomXA();
686
687         StrBufAppendTemplate(Target, TP, WCC->CurRoom.XAPass, 0);
688 }
689 void tmplput_CurrentRoomDirectory(StrBuf *Target, WCTemplputParams *TP) 
690 {
691         wcsession *WCC = WC;
692
693         LoadRoomXA();
694
695         StrBufAppendTemplate(Target, TP, WCC->CurRoom.Directory, 0);
696 }
697 void tmplput_CurrentRoomOrder(StrBuf *Target, WCTemplputParams *TP) 
698 {
699         wcsession *WCC = WC;
700
701         LoadRoomXA();
702
703         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.Order);
704 }
705 void tmplput_CurrentRoomDefView(StrBuf *Target, WCTemplputParams *TP) 
706 {
707         wcsession *WCC = WC;
708
709         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.defview);
710 }
711
712 void tmplput_CurrentRoom_nNewMessages(StrBuf *Target, WCTemplputParams *TP) 
713 {
714         wcsession *WCC = WC;
715
716         LoadRoomXA();
717
718         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.nNewMessages);
719 }
720
721 void tmplput_CurrentRoom_nTotalMessages(StrBuf *Target, WCTemplputParams *TP) 
722 {
723         wcsession *WCC = WC;
724
725         LoadRoomXA();
726
727         StrBufAppendPrintf(Target, "%d", WCC->CurRoom.nTotalMessages);
728 }
729
730 int ConditionalThisRoomOrder(StrBuf *Target, WCTemplputParams *TP)
731 {
732         wcsession *WCC = WC;
733         long CheckThis;
734
735         if (WCC == NULL)
736                 return 0;
737
738         LoadRoomXA();
739
740         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
741         return CheckThis == WCC->CurRoom.Order;
742 }
743
744 int ConditionalThisRoomDefView(StrBuf *Target, WCTemplputParams *TP)
745 {
746         wcsession *WCC = WC;
747         long CheckThis;
748
749         if (WCC == NULL)
750                 return 0;
751
752         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
753         return CheckThis == WCC->CurRoom.defview;
754 }
755
756 int ConditionalThisRoomCurrView(StrBuf *Target, WCTemplputParams *TP)
757 {
758         wcsession *WCC = WC;
759         long CheckThis;
760
761         if (WCC == NULL)
762                 return 0;
763
764         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
765         return CheckThis == WCC->CurRoom.view;
766 }
767
768 int ConditionalThisRoomHaveView(StrBuf *Target, WCTemplputParams *TP)
769 {
770         wcsession *WCC = WC;
771         long CheckThis;
772         
773         if (WCC == NULL)
774                 return 0;
775
776         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
777         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
778         {
779                 LogTemplateError(Target, "Conditional", ERR_PARM2, TP,
780                                  "Roomview [%ld] not valid\n", 
781                                  CheckThis);
782                 return 0;
783         }
784
785         return exchangeable_views [WCC->CurRoom.defview][CheckThis] != VIEW_MAX;
786 }
787
788 void tmplput_CurrentRoomViewString(StrBuf *Target, WCTemplputParams *TP) 
789 {
790         wcsession *WCC = WC;
791         StrBuf *Buf;
792
793         if ((WCC == NULL) ||
794             (WCC->CurRoom.defview >= VIEW_MAX) || 
795             (WCC->CurRoom.defview < VIEW_BBS))
796         {
797                 LogTemplateError(Target, "Token", ERR_PARM2, TP,
798                                  "Roomview [%ld] not valid\n", 
799                                  (WCC != NULL)? 
800                                  WCC->CurRoom.defview : -1);
801                 return;
802         }
803
804         Buf = NewStrBufPlain(_(viewdefs[WCC->CurRoom.defview]), -1);
805         StrBufAppendTemplate(Target, TP, Buf, 0);
806         FreeStrBuf(&Buf);
807 }
808
809 void tmplput_RoomViewString(StrBuf *Target, WCTemplputParams *TP) 
810 {
811         long CheckThis;
812         StrBuf *Buf;
813
814         CheckThis = GetTemplateTokenNumber(Target, TP, 0, 0);
815         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
816         {
817                 LogTemplateError(Target, "Token", ERR_PARM2, TP,
818                                  "Roomview [%ld] not valid\n", 
819                                  CheckThis);
820                 return;
821         }
822
823         Buf = NewStrBufPlain(_(viewdefs[CheckThis]), -1);
824         StrBufAppendTemplate(Target, TP, Buf, 0);
825         FreeStrBuf(&Buf);
826 }
827
828
829 int ConditionalIsAllowedDefaultView(StrBuf *Target, WCTemplputParams *TP)
830 {
831         wcsession *WCC = WC;
832         long CheckThis;
833         
834         if (WCC == NULL)
835                 return 0;
836
837         CheckThis = GetTemplateTokenNumber(Target, TP, 2, 0);
838         if ((CheckThis >= VIEW_MAX) || (CheckThis < VIEW_BBS))
839         {
840                 LogTemplateError(Target, "Conditional", ERR_PARM2, TP,
841                                  "Roomview [%ld] not valid\n", 
842                                  CheckThis);
843                 return 0;
844         }
845
846         return allowed_default_views[CheckThis] != 0;
847 }
848
849 /*
850  * goto next room
851  */
852 void smart_goto(const StrBuf *next_room) {
853         gotoroom(next_room);
854         readloop(readnew, eUseDefault);
855 }
856
857
858
859 /*
860  * mark all messages in current room as having been read
861  */
862 void slrp_highest(void)
863 {
864         char buf[256];
865
866         serv_puts("SLRP HIGHEST");
867         serv_getln(buf, sizeof buf);
868 }
869
870
871
872 /*
873  * Set/clear/read the "self-service list subscribe" flag for a room
874  * 
875  * set newval to 0 to clear, 1 to set, any other value to leave unchanged.
876  * returns the new value.
877  */
878
879 int self_service(int newval) {
880         int current_value = 0;
881         wcsession *WCC = WC;
882
883         if (GetCurrentRoomFlags (&WCC->CurRoom) == 0)
884         {
885                 return 0;
886         }
887
888         if ((WCC->CurRoom.QRFlags2 & QR2_SELFLIST) != 0) {
889                 current_value = 1;
890         }
891         else {
892                 current_value = 0;
893         }
894
895         if (newval == 1) {
896                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SELFLIST;
897         }
898         else if (newval == 0) {
899                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SELFLIST;
900         }
901         else {
902                 return(current_value);
903         }
904
905         if (newval != current_value) {
906                 SetCurrentRoomFlags(&WCC->CurRoom);
907         }
908
909         return(newval);
910
911 }
912
913
914
915 /* 
916  * Toggle self-service list subscription
917  */
918 void toggle_self_service(void) {
919         wcsession *WCC = WC;
920
921         if (GetCurrentRoomFlags (&WCC->CurRoom) == 0)
922                 return;
923
924         if (yesbstr("QR2_SelfList")) 
925                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SELFLIST;
926         else 
927                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SELFLIST;
928
929         if (yesbstr("QR2_SMTP_PUBLIC")) 
930                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SMTP_PUBLIC;
931         else
932                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SMTP_PUBLIC;
933
934         if (yesbstr("QR2_Moderated")) 
935                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_MODERATED;
936         else
937                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_MODERATED;
938         if (yesbstr("QR2_SubsOnly")) 
939                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SMTP_PUBLIC;
940         else
941                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SMTP_PUBLIC;
942
943         SetCurrentRoomFlags (&WCC->CurRoom);
944         
945         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
946 }
947
948
949
950 /*
951  * save new parameters for a room
952  */
953 void editroom(void)
954 {
955         wcsession *WCC = WC;
956         const StrBuf *Ptr;
957         const StrBuf *er_name;
958         const StrBuf *er_password;
959         const StrBuf *er_dirname;
960         const StrBuf *er_roomaide;
961         unsigned er_flags;
962         unsigned er_flags2;
963         int succ1, succ2;
964
965         if (!havebstr("ok_button")) {
966                 strcpy(WC->ImportantMessage,
967                        _("Cancelled.  Changes were not saved."));
968                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
969                 return;
970         }
971         if (GetCurrentRoomFlags (&WCC->CurRoom) == 0)
972                 return;
973
974         LoadRoomAide();
975
976         er_flags = WCC->CurRoom.QRFlags;
977         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
978
979         er_flags2 = WCC->CurRoom.QRFlags2;
980
981         Ptr = sbstr("type");
982         if (!strcmp(ChrPtr(Ptr), "invonly")) {
983                 er_flags |= (QR_PRIVATE);
984         }
985         if (!strcmp(ChrPtr(Ptr), "hidden")) {
986                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
987         }
988         if (!strcmp(ChrPtr(Ptr), "passworded")) {
989                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
990         }
991         if (!strcmp(ChrPtr(Ptr), "personal")) {
992                 er_flags |= QR_MAILBOX;
993         } else {
994                 er_flags &= ~QR_MAILBOX;
995         }
996
997
998         
999         if (yesbstr("prefonly")) {
1000                 er_flags |= QR_PREFONLY;
1001         } else {
1002                 er_flags &= ~QR_PREFONLY;
1003         }
1004
1005         if (yesbstr("readonly")) {
1006                 er_flags |= QR_READONLY;
1007         } else {
1008                 er_flags &= ~QR_READONLY;
1009         }
1010
1011         
1012         if (yesbstr("collabdel")) {
1013                 er_flags2 |= QR2_COLLABDEL;
1014         } else {
1015                 er_flags2 &= ~QR2_COLLABDEL;
1016         }
1017
1018         if (yesbstr("permanent")) {
1019                 er_flags |= QR_PERMANENT;
1020         } else {
1021                 er_flags &= ~QR_PERMANENT;
1022         }
1023
1024         if (yesbstr("subjectreq")) {
1025                 er_flags2 |= QR2_SUBJECTREQ;
1026         } else {
1027                 er_flags2 &= ~QR2_SUBJECTREQ;
1028         }
1029
1030         if (yesbstr("network")) {
1031                 er_flags |= QR_NETWORK;
1032         } else {
1033                 er_flags &= ~QR_NETWORK;
1034         }
1035
1036         if (yesbstr("directory")) {
1037                 er_flags |= QR_DIRECTORY;
1038         } else {
1039                 er_flags &= ~QR_DIRECTORY;
1040         }
1041
1042         if (yesbstr("ulallowed")) {
1043                 er_flags |= QR_UPLOAD;
1044         } else {
1045                 er_flags &= ~QR_UPLOAD;
1046         }
1047
1048         if (yesbstr("dlallowed")) {
1049                 er_flags |= QR_DOWNLOAD;
1050         } else {
1051                 er_flags &= ~QR_DOWNLOAD;
1052         }
1053
1054         if (yesbstr("visdir")) {
1055                 er_flags |= QR_VISDIR;
1056         } else {
1057                 er_flags &= ~QR_VISDIR;
1058         }
1059
1060
1061         Ptr = sbstr("anon");
1062
1063         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
1064         if (!strcmp(ChrPtr(Ptr), "anononly"))
1065                 er_flags |= QR_ANONONLY;
1066         if (!strcmp(ChrPtr(Ptr), "anon2"))
1067                 er_flags |= QR_ANONOPT;
1068
1069         er_name     = sbstr("er_name");
1070         er_dirname  = sbstr("er_dirname");
1071         er_roomaide = sbstr("er_roomaide");
1072         er_password = sbstr("er_password");
1073
1074         FlushStrBuf(WCC->CurRoom.name);
1075         StrBufAppendBuf(WCC->CurRoom.name, er_name, 0);
1076
1077         FlushStrBuf(WCC->CurRoom.Directory);
1078         StrBufAppendBuf(WCC->CurRoom.Directory, er_dirname, 0);
1079
1080         FlushStrBuf(WCC->CurRoom.RoomAide);
1081         StrBufAppendBuf(WCC->CurRoom.RoomAide, er_roomaide, 0);
1082
1083         FlushStrBuf(WCC->CurRoom.XAPass);
1084         StrBufAppendBuf(WCC->CurRoom.XAPass, er_password, 0);
1085
1086         WCC->CurRoom.BumpUsers = yesbstr("bump");
1087
1088         WCC->CurRoom.floorid = ibstr("er_floor");
1089
1090         succ1 = SetCurrentRoomFlags(&WCC->CurRoom);
1091
1092         succ2 = SaveRoomAide (&WCC->CurRoom);
1093         
1094         if (succ1 + succ2 == 0)
1095                 AppendImportantMessage (_("Your changes have been saved."), -1);
1096         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1097         return;
1098 }
1099
1100
1101 /*
1102  * Display form for Invite, Kick, and show Who Knows a room
1103  */
1104 void do_invt_kick(void) 
1105 {
1106         StrBuf *Buf, *User;
1107         const StrBuf *UserNames;
1108         int Kick, Invite;
1109         wcsession *WCC = WC;
1110
1111
1112         if (GetCurrentRoomFlags(&WCC->CurRoom) == 1)
1113         {
1114                 const char *Pos;
1115                 UserNames = sbstr("username");
1116                 Kick = havebstr("kick_button");
1117                 Invite = havebstr("invite_button");
1118
1119                 User = NewStrBufPlain(NULL, StrLength(UserNames));
1120                 Buf = NewStrBuf();
1121                 
1122                 Pos = ChrPtr(UserNames);
1123                 while (Pos != StrBufNOTNULL)
1124                 {
1125                         StrBufExtract_NextToken(User, UserNames, &Pos, ',');
1126                         StrBufTrim(User);
1127                         if ((StrLength(User) > 0) && (Kick))
1128                         {
1129                                 serv_printf("KICK %s", ChrPtr(User));
1130                                 StrBuf_ServGetln(Buf);
1131                                 if (GetServerStatus(Buf, NULL) != 2) {
1132                                         StrBufCutLeft(Buf, 4);
1133                                         AppendImportantMessage(SKEY(Buf));
1134                                 } else {
1135                                         StrBufPrintf(Buf, 
1136                                                      _("User '%s' kicked out of room '%s'."), 
1137                                                      ChrPtr(User), 
1138                                                      ChrPtr(WCC->CurRoom.name)
1139                                                 );
1140                                         AppendImportantMessage(SKEY(Buf));
1141                                 }
1142                         }
1143                         else if ((StrLength(User) > 0) && (Invite))
1144                         {
1145                                 serv_printf("INVT %s", ChrPtr(User));
1146                                 StrBuf_ServGetln(Buf);
1147                                 if (GetServerStatus(Buf, NULL) != 2) {
1148                                         StrBufCutLeft(Buf, 4);
1149                                         AppendImportantMessage(SKEY(Buf));
1150                                 } else {
1151                                         StrBufPrintf(Buf, 
1152                                                      _("User '%s' invited to room '%s'."), 
1153                                                      ChrPtr(User), 
1154                                                      ChrPtr(WCC->CurRoom.name)
1155                                                 );
1156                                         AppendImportantMessage(SKEY(Buf));
1157                                 }
1158                         }
1159                 }
1160         }
1161
1162         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1163 }
1164
1165 /*
1166  * support function for entroom() -- sets the default view 
1167  */
1168 void er_set_default_view(int newview) {
1169
1170         char buf[SIZ];
1171
1172         char rm_name[SIZ];
1173         char rm_pass[SIZ];
1174         char rm_dir[SIZ];
1175         int rm_bits1;
1176         int rm_floor;
1177         int rm_listorder;
1178         int rm_bits2;
1179
1180         serv_puts("GETR");
1181         serv_getln(buf, sizeof buf);
1182         if (buf[0] != '2') return;
1183
1184         extract_token(rm_name, &buf[4], 0, '|', sizeof rm_name);
1185         extract_token(rm_pass, &buf[4], 1, '|', sizeof rm_pass);
1186         extract_token(rm_dir, &buf[4], 2, '|', sizeof rm_dir);
1187         rm_bits1 = extract_int(&buf[4], 3);
1188         rm_floor = extract_int(&buf[4], 4);
1189         rm_listorder = extract_int(&buf[4], 5);
1190         rm_bits2 = extract_int(&buf[4], 7);
1191
1192         serv_printf("SETR %s|%s|%s|%d|0|%d|%d|%d|%d",
1193                     rm_name, rm_pass, rm_dir, rm_bits1, rm_floor,
1194                     rm_listorder, newview, rm_bits2
1195                 );
1196         serv_getln(buf, sizeof buf);
1197 }
1198
1199
1200
1201 /*
1202  * Create a new room
1203  */
1204 void entroom(void)
1205 {
1206         char buf[SIZ];
1207         const StrBuf *er_name;
1208         const StrBuf *er_type;
1209         const StrBuf *er_password;
1210         int er_floor;
1211         int er_num_type;
1212         int er_view;
1213         wcsession *WCC = WC;
1214
1215         if (!havebstr("ok_button")) {
1216                 strcpy(WC->ImportantMessage,
1217                        _("Cancelled.  No new room was created."));
1218                 display_main_menu();
1219                 return;
1220         }
1221         er_name = sbstr("er_name");
1222         er_type = sbstr("type");
1223         er_password = sbstr("er_password");
1224         er_floor = ibstr("er_floor");
1225         er_view = ibstr("er_view");
1226
1227         er_num_type = 0;
1228         if (!strcmp(ChrPtr(er_type), "hidden"))
1229                 er_num_type = 1;
1230         else if (!strcmp(ChrPtr(er_type), "passworded"))
1231                 er_num_type = 2;
1232         else if (!strcmp(ChrPtr(er_type), "invonly"))
1233                 er_num_type = 3;
1234         else if (!strcmp(ChrPtr(er_type), "personal"))
1235                 er_num_type = 4;
1236
1237         serv_printf("CRE8 1|%s|%d|%s|%d|%d|%d", 
1238                     ChrPtr(er_name), 
1239                     er_num_type, 
1240                     ChrPtr(er_password), 
1241                     er_floor, 
1242                     0, 
1243                     er_view);
1244
1245         serv_getln(buf, sizeof buf);
1246         if (buf[0] != '2') {
1247                 strcpy(WCC->ImportantMessage, &buf[4]);
1248                 display_main_menu();
1249                 return;
1250         }
1251         /** TODO: Room created, now update the left hand icon bar for this user */
1252         gotoroom(er_name);
1253
1254         serv_printf("VIEW %d", er_view);
1255         serv_getln(buf, sizeof buf);
1256         WCC->CurRoom.view = er_view;
1257
1258         if ( (WCC != NULL) && ( (WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) )  {
1259                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1260         } else {
1261                 do_change_view(er_view);                /* Now go there */
1262         }
1263
1264 }
1265
1266
1267 /**
1268  * \brief goto a private room
1269  */
1270 void goto_private(void)
1271 {
1272         char hold_rm[SIZ];
1273         StrBuf *Buf;
1274         const StrBuf *gr_name;
1275         long err;
1276
1277         if (!havebstr("ok_button")) {
1278                 display_main_menu();
1279                 return;
1280         }
1281         gr_name = sbstr("gr_name");
1282         Buf = NewStrBuf();
1283         strcpy(hold_rm, ChrPtr(WC->CurRoom.name));
1284         serv_printf("GOTO %s|%s",
1285                     ChrPtr(gr_name),
1286                     bstr("gr_pass"));
1287         StrBuf_ServGetln(Buf);
1288         if  (GetServerStatus(Buf, &err) == 2) {
1289                 FlushRoomlist();
1290                 smart_goto(gr_name);
1291                 FreeStrBuf(&Buf);
1292                 return;
1293         }
1294         if (err == 540) {
1295                 DoTemplate(HKEY("room_display_private"), NULL, &NoCtx);
1296                 FreeStrBuf(&Buf);
1297                 return;
1298         }
1299         StrBufCutLeft(Buf, 4);
1300         AppendImportantMessage (SKEY(Buf));
1301         Buf = NewStrBufPlain(HKEY("_BASEROOM_"));
1302         smart_goto(Buf);
1303         FreeStrBuf(&Buf);
1304         return;
1305 }
1306
1307
1308
1309 /**
1310  * \brief zap a room
1311  */
1312 void zap(void)
1313 {
1314         char buf[SIZ];
1315         StrBuf *final_destination;
1316
1317         /**
1318          * If the forget-room routine fails for any reason, we fall back
1319          * to the current room; otherwise, we go to the Lobby
1320          */
1321         final_destination = NewStrBufDup(WC->CurRoom.name);
1322
1323         if (havebstr("ok_button")) {
1324                 serv_printf("GOTO %s", ChrPtr(WC->CurRoom.name));
1325                 serv_getln(buf, sizeof buf);
1326                 if (buf[0] == '2') {
1327                         serv_puts("FORG");
1328                         serv_getln(buf, sizeof buf);
1329                         if (buf[0] == '2') {
1330                                 FlushStrBuf(final_destination);
1331                                 StrBufAppendBufPlain(final_destination, HKEY("_BASEROOM_"), 0);
1332                         }
1333                 }
1334                 FlushRoomlist ();
1335         }
1336         smart_goto(final_destination);
1337         FreeStrBuf(&final_destination);
1338 }
1339
1340
1341
1342 /**
1343  * \brief Delete the current room
1344  */
1345 void delete_room(void)
1346 {
1347         char buf[SIZ];
1348
1349         
1350         serv_puts("KILL 1");
1351         serv_getln(buf, sizeof buf);
1352
1353         if (buf[0] != '2') {
1354                 strcpy(WC->ImportantMessage, &buf[4]);
1355                 display_main_menu();
1356                 return;
1357         } else {
1358                 StrBuf *Buf;
1359                 
1360                 FlushRoomlist ();
1361                 Buf = NewStrBufPlain(HKEY("_BASEROOM_"));
1362                 smart_goto(Buf);
1363                 FreeStrBuf(&Buf);
1364         }
1365 }
1366
1367
1368
1369 /**
1370  * \brief Perform changes to a room's network configuration
1371  */
1372 void netedit(void) {
1373         FILE *fp;
1374         char buf[SIZ];
1375         char line[SIZ];
1376         char cmpa0[SIZ];
1377         char cmpa1[SIZ];
1378         char cmpb0[SIZ];
1379         char cmpb1[SIZ];
1380         int i, num_addrs;
1381         /*/ TODO: do line dynamic! */
1382         if (havebstr("line_pop3host")) {
1383                 strcpy(line, bstr("prefix"));
1384                 strcat(line, bstr("line_pop3host"));
1385                 strcat(line, "|");
1386                 strcat(line, bstr("line_pop3user"));
1387                 strcat(line, "|");
1388                 strcat(line, bstr("line_pop3pass"));
1389                 strcat(line, "|");
1390                 strcat(line, ibstr("line_pop3keep") ? "1" : "0" );
1391                 strcat(line, "|");
1392                 sprintf(&line[strlen(line)],"%ld", lbstr("line_pop3int"));
1393                 strcat(line, bstr("suffix"));
1394         }
1395         else if (havebstr("line")) {
1396                 strcpy(line, bstr("prefix"));
1397                 strcat(line, bstr("line"));
1398                 strcat(line, bstr("suffix"));
1399         }
1400         else {
1401                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1402                 return;
1403         }
1404
1405
1406         fp = tmpfile();
1407         if (fp == NULL) {
1408                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1409                 return;
1410         }
1411
1412         serv_puts("GNET");
1413         serv_getln(buf, sizeof buf);
1414         if (buf[0] != '1') {
1415                 fclose(fp);
1416                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1417                 return;
1418         }
1419
1420         /** This loop works for add *or* remove.  Spiffy, eh? */
1421         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
1422                 extract_token(cmpa0, buf, 0, '|', sizeof cmpa0);
1423                 extract_token(cmpa1, buf, 1, '|', sizeof cmpa1);
1424                 extract_token(cmpb0, line, 0, '|', sizeof cmpb0);
1425                 extract_token(cmpb1, line, 1, '|', sizeof cmpb1);
1426                 if ( (strcasecmp(cmpa0, cmpb0)) 
1427                      || (strcasecmp(cmpa1, cmpb1)) ) {
1428                         fprintf(fp, "%s\n", buf);
1429                 }
1430         }
1431
1432         rewind(fp);
1433         serv_puts("SNET");
1434         serv_getln(buf, sizeof buf);
1435         if (buf[0] != '4') {
1436                 fclose(fp);
1437                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1438                 return;
1439         }
1440
1441         while (fgets(buf, sizeof buf, fp) != NULL) {
1442                 buf[strlen(buf)-1] = 0;
1443                 serv_puts(buf);
1444         }
1445
1446         if (havebstr("add_button")) {
1447                 num_addrs = num_tokens(bstr("line"), ',');
1448                 if (num_addrs < 2) {
1449                         /* just adding one node or address */
1450                         serv_puts(line);
1451                 }
1452                 else {
1453                         /* adding multiple addresses separated by commas */
1454                         for (i=0; i<num_addrs; ++i) {
1455                                 strcpy(line, bstr("prefix"));
1456                                 extract_token(buf, bstr("line"), i, ',', sizeof buf);
1457                                 striplt(buf);
1458                                 strcat(line, buf);
1459                                 strcat(line, bstr("suffix"));
1460                                 serv_puts(line);
1461                         }
1462                 }
1463         }
1464
1465         serv_puts("000");
1466         fclose(fp);
1467         FlushIgnetCfgs(&WC->CurRoom);
1468
1469         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1470 }
1471
1472 /*
1473  * delete the actual floor
1474  */
1475 void delete_floor(void) {
1476         int floornum;
1477         StrBuf *Buf;
1478         const char *Err;
1479                 
1480         floornum = ibstr("floornum");
1481         Buf = NewStrBuf();
1482         serv_printf("KFLR %d|1", floornum);
1483         
1484         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1485
1486         if (GetServerStatus(Buf, NULL) == 2) {
1487                 StrBufPlain(Buf, _("Floor has been deleted."),-1);
1488         }
1489         else {
1490                 StrBufCutLeft(Buf, 4);
1491         }
1492         AppendImportantMessage (SKEY(Buf));
1493
1494         FlushRoomlist();
1495         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1496         FreeStrBuf(&Buf);
1497 }
1498
1499 /*
1500  * start creating a new floor
1501  */
1502 void create_floor(void) {
1503         StrBuf *Buf;
1504         const char *Err;
1505
1506         Buf = NewStrBuf();
1507         serv_printf("CFLR %s|1", bstr("floorname"));
1508         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1509
1510         if (GetServerStatus(Buf, NULL) == 2) {
1511                 StrBufPlain(Buf, _("New floor has been created."),-1);
1512         }
1513         else {
1514                 StrBufCutLeft(Buf, 4);
1515         }
1516         AppendImportantMessage (SKEY(Buf));
1517         FlushRoomlist();
1518         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1519         FreeStrBuf(&Buf);
1520 }
1521
1522
1523 /*
1524  * rename this floor
1525  */
1526 void rename_floor(void) {
1527         StrBuf *Buf;
1528
1529         Buf = NewStrBuf();
1530         FlushRoomlist();
1531
1532         serv_printf("EFLR %d|%s", ibstr("floornum"), bstr("floorname"));
1533         StrBuf_ServGetln(Buf);
1534
1535         StrBufCutLeft(Buf, 4);
1536         AppendImportantMessage (SKEY(Buf));
1537
1538         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1539         FreeStrBuf(&Buf);
1540 }
1541
1542
1543
1544 /**
1545  * \brief Back end for change_view()
1546  * \param newview set newview???
1547  */
1548 void do_change_view(int newview) {
1549         char buf[SIZ];
1550
1551         serv_printf("VIEW %d", newview);
1552         serv_getln(buf, sizeof buf);
1553         WC->CurRoom.view = newview;
1554         smart_goto(WC->CurRoom.name);
1555 }
1556
1557
1558
1559 /**
1560  * \brief Change the view for this room
1561  */
1562 void change_view(void) {
1563         int view;
1564
1565         view = lbstr("view");
1566         do_change_view(view);
1567 }
1568
1569 /**
1570  * \brief Do either a known rooms list or a folders list, depending on the
1571  * user's preference
1572  */
1573 void knrooms(void)
1574 {
1575         StrBuf *ListView = NULL;
1576
1577         /** Determine whether the user is trying to change views */
1578         if (havebstr("view")) {
1579                 ListView = NewStrBufDup(SBSTR("view"));
1580                 set_preference("roomlistview", ListView, 1);
1581         }
1582         /** Sanitize the input so its safe */
1583         if((get_preference("roomlistview", &ListView) != 0)||
1584            ((strcasecmp(ChrPtr(ListView), "folders") != 0) &&
1585             (strcasecmp(ChrPtr(ListView), "table") != 0))) 
1586         {
1587                 if (ListView == NULL) {
1588                         ListView = NewStrBufPlain(HKEY("rooms"));
1589                         set_preference("roomlistview", ListView, 0);
1590                         ListView = NULL;
1591                 }
1592                 else {
1593                         ListView = NewStrBufPlain(HKEY("rooms"));
1594                         set_preference("roomlistview", ListView, 0);
1595                         ListView = NULL;
1596                 }
1597         }
1598         FreeStrBuf(&ListView);
1599         url_do_template();
1600 }
1601
1602
1603
1604 /**
1605  * \brief Set the message expire policy for this room and/or floor
1606  */
1607 void set_room_policy(void) {
1608         char buf[SIZ];
1609
1610         if (!havebstr("ok_button")) {
1611                 strcpy(WC->ImportantMessage,
1612                        _("Cancelled.  Changes were not saved."));
1613                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1614                 return;
1615         }
1616
1617         serv_printf("SPEX roompolicy|%d|%d", ibstr("roompolicy"), ibstr("roomvalue"));
1618         serv_getln(buf, sizeof buf);
1619         strcpy(WC->ImportantMessage, &buf[4]);
1620
1621         if (WC->axlevel >= 6) {
1622                 strcat(WC->ImportantMessage, "<br />\n");
1623                 serv_printf("SPEX floorpolicy|%d|%d", ibstr("floorpolicy"), ibstr("floorvalue"));
1624                 serv_getln(buf, sizeof buf);
1625                 strcat(WC->ImportantMessage, &buf[4]);
1626         }
1627         ReloadCurrentRoom();
1628         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1629 }
1630
1631 void tmplput_RoomName(StrBuf *Target, WCTemplputParams *TP)
1632 {
1633         StrBufAppendTemplate(Target, TP, WC->CurRoom.name, 0);
1634 }
1635
1636 void dotgoto(void) {
1637         if (!havebstr("room")) {
1638                 readloop(readnew, eUseDefault);
1639                 return;
1640         }
1641         if (WC->CurRoom.view != VIEW_MAILBOX) { /* dotgoto acts like dotskip when we're in a mailbox view */
1642                 slrp_highest();
1643         }
1644         smart_goto(sbstr("room"));
1645 }
1646
1647
1648
1649 void tmplput_current_room(StrBuf *Target, WCTemplputParams *TP)
1650 {
1651         wcsession *WCC = WC;
1652
1653         if (WCC != NULL)
1654                 StrBufAppendTemplate(Target, TP, 
1655                                      WCC->CurRoom.name, 
1656                                      0); 
1657 }
1658
1659 void tmplput_roombanner(StrBuf *Target, WCTemplputParams *TP)
1660 {
1661         wc_printf("<div id=\"banner\">\n");
1662         embed_room_banner();
1663         wc_printf("</div>\n");
1664 }
1665
1666
1667 void tmplput_ungoto(StrBuf *Target, WCTemplputParams *TP)
1668 {
1669         wcsession *WCC = WC;
1670
1671         if ((WCC!=NULL) && 
1672             (!IsEmptyStr(WCC->ugname)))
1673                 StrBufAppendBufPlain(Target, WCC->ugname, -1, 0);
1674 }
1675
1676 int ConditionalRoomAide(StrBuf *Target, WCTemplputParams *TP)
1677 {
1678         wcsession *WCC = WC;
1679         return (WCC != NULL)? 
1680                 ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) : 0;
1681 }
1682
1683 int ConditionalRoomAcessDelete(StrBuf *Target, WCTemplputParams *TP)
1684 {
1685         wcsession *WCC = WC;
1686         return (WCC == NULL)? 0 : 
1687                 ( ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) ||
1688                    (WCC->CurRoom.is_inbox) || 
1689                    (WCC->CurRoom.QRFlags2 & QR2_COLLABDEL) );
1690 }
1691
1692 int ConditionalHaveUngoto(StrBuf *Target, WCTemplputParams *TP)
1693 {
1694         wcsession *WCC = WC;
1695         
1696         return ((WCC!=NULL) && 
1697                 (!IsEmptyStr(WCC->ugname)) && 
1698                 (strcasecmp(WCC->ugname, ChrPtr(WCC->CurRoom.name)) == 0));
1699 }
1700
1701
1702 int ConditionalRoomHas_UAFlag(StrBuf *Target, WCTemplputParams *TP)
1703 {
1704         folder *Folder = (folder *)(TP->Context);
1705         long UA_CheckFlag;
1706                 
1707         UA_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
1708         if (UA_CheckFlag == 0)
1709                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
1710                                  "requires one of the #\"UA_*\"- defines or an integer flag 0 is invalid!");
1711
1712         return ((Folder->RAFlags & UA_CheckFlag) != 0);
1713 }
1714
1715
1716
1717 int ConditionalCurrentRoomHas_QRFlag(StrBuf *Target, WCTemplputParams *TP)
1718 {
1719         long QR_CheckFlag;
1720         wcsession *WCC = WC;
1721         
1722         QR_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
1723         if (QR_CheckFlag == 0)
1724                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
1725                                  "requires one of the #\"QR*\"- defines or an integer flag 0 is invalid!");
1726         
1727         if (WCC == NULL)
1728                 return 0;
1729
1730         if ((TP->Tokens->Params[2]->MaskBy == eOR) ||
1731             (TP->Tokens->Params[2]->MaskBy == eNO))
1732                 return (WCC->CurRoom.QRFlags & QR_CheckFlag) != 0;
1733         else
1734                 return (WCC->CurRoom.QRFlags & QR_CheckFlag) == QR_CheckFlag;
1735 }
1736
1737 int ConditionalRoomHas_QRFlag(StrBuf *Target, WCTemplputParams *TP)
1738 {
1739         long QR_CheckFlag;
1740         folder *Folder = (folder *)(TP->Context);
1741
1742         QR_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
1743         if (QR_CheckFlag == 0)
1744                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
1745                                  "requires one of the #\"QR*\"- defines or an integer flag 0 is invalid!");
1746
1747         if ((TP->Tokens->Params[2]->MaskBy == eOR) ||
1748             (TP->Tokens->Params[2]->MaskBy == eNO))
1749                 return (Folder->QRFlags & QR_CheckFlag) != 0;
1750         else
1751                 return (Folder->QRFlags & QR_CheckFlag) == QR_CheckFlag;
1752 }
1753
1754
1755 int ConditionalCurrentRoomHas_QRFlag2(StrBuf *Target, WCTemplputParams *TP)
1756 {
1757         long QR2_CheckFlag;
1758         wcsession *WCC = WC;
1759         
1760         QR2_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
1761         if (QR2_CheckFlag == 0)
1762                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
1763                                  "requires one of the #\"QR2*\"- defines or an integer flag 0 is invalid!");
1764
1765         
1766         if (WCC == NULL)
1767                 return 0;
1768
1769         if ((TP->Tokens->Params[2]->MaskBy == eOR) ||
1770             (TP->Tokens->Params[2]->MaskBy == eNO))
1771                 return (WCC->CurRoom.QRFlags2 & QR2_CheckFlag) != 0;
1772         else
1773                 return (WCC->CurRoom.QRFlags2 & QR2_CheckFlag) == QR2_CheckFlag;
1774 }
1775
1776 int ConditionalRoomHas_QRFlag2(StrBuf *Target, WCTemplputParams *TP)
1777 {
1778         long QR2_CheckFlag;
1779         folder *Folder = (folder *)(TP->Context);
1780
1781         QR2_CheckFlag = GetTemplateTokenNumber(Target, TP, 2, 0);
1782         if (QR2_CheckFlag == 0)
1783                 LogTemplateError(Target, "Conditional", ERR_PARM1, TP,
1784                                  "requires one of the #\"QR2*\"- defines or an integer flag 0 is invalid!");
1785         return ((Folder->QRFlags2 & QR2_CheckFlag) != 0);
1786 }
1787
1788
1789 int ConditionalHaveRoomeditRights(StrBuf *Target, WCTemplputParams *TP)
1790 {
1791         wcsession *WCC = WC;
1792
1793         return ( (WCC!= NULL) && 
1794                  ((WCC->axlevel >= 6) || 
1795                   ((WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) ||
1796                   (WCC->CurRoom.is_inbox) ));
1797 }
1798
1799 int ConditionalIsRoomtype(StrBuf *Target, WCTemplputParams *TP)
1800 {
1801         wcsession *WCC = WC;
1802
1803         if ((WCC == NULL) ||
1804             (TP->Tokens->nParameters < 3))
1805         {
1806                 return ((WCC->CurRoom.view < VIEW_BBS) || 
1807                         (WCC->CurRoom.view > VIEW_MAX));
1808         }
1809
1810         return WCC->CurRoom.view == GetTemplateTokenNumber(Target, TP, 2, VIEW_BBS);
1811 }
1812
1813
1814 HashList *GetWhoKnowsHash(StrBuf *Target, WCTemplputParams *TP)
1815 {
1816         wcsession *WCC = WC;
1817         StrBuf *Line;
1818         StrBuf *Token;
1819         long State;
1820         HashList *Whok = NULL;
1821         int Done = 0;
1822         int n;
1823
1824         serv_puts("WHOK");
1825         Line = NewStrBuf();
1826         StrBuf_ServGetln(Line);
1827         if (GetServerStatus(Line, &State) == 1) 
1828         {
1829                 Whok = NewHash(1, Flathash);
1830                 while(!Done && StrBuf_ServGetln(Line))
1831                         if ( (StrLength(Line)==3) && 
1832                              !strcmp(ChrPtr(Line), "000")) 
1833                         {
1834                                 Done = 1;
1835                         }
1836                         else
1837                         {
1838                         
1839                                 const char *Pos = NULL;
1840                                 Token = NewStrBufPlain (NULL, StrLength(Line));
1841                                 StrBufExtract_NextToken(Token, Line, &Pos, '|');
1842
1843                                 Put(Whok, 
1844                                     IKEY(n),
1845                                     Token, 
1846                                     HFreeStrBuf);
1847                                 n++;
1848                         }
1849         }
1850         else if (State == 550)
1851                 StrBufAppendBufPlain(WCC->ImportantMsg,
1852                                      _("Higher access is required to access this function."), -1, 0);
1853
1854
1855         FreeStrBuf(&Line);
1856         return Whok;
1857 }
1858
1859
1860
1861 void _FlushRoomList(wcsession *WCC)
1862 {
1863         free_march_list(WCC);
1864         DeleteHash(&WCC->Floors);
1865         DeleteHash(&WCC->Rooms);
1866         DeleteHash(&WCC->FloorsByName);
1867         FlushFolder(&WCC->CurRoom);
1868 }
1869
1870 void ReloadCurrentRoom(void)
1871 {
1872         wcsession *WCC = WC;
1873         StrBuf *CurRoom;
1874
1875         CurRoom = WCC->CurRoom.name;
1876         WCC->CurRoom.name = NULL;
1877         _FlushRoomList(WCC);
1878         gotoroom(CurRoom);
1879         FreeStrBuf(&CurRoom);
1880 }
1881
1882 void FlushRoomlist(void)
1883 {
1884         wcsession *WCC = WC;
1885         _FlushRoomList(WCC);
1886 }
1887
1888
1889 void 
1890 InitModule_ROOMOPS
1891 (void)
1892 {
1893         initialize_viewdefs();
1894         RegisterPreference("roomlistview",
1895                            _("Room list view"),
1896                            PRF_STRING,
1897                            NULL);
1898         RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO, NULL);
1899
1900         RegisterNamespace("ROOMNAME", 0, 1, tmplput_RoomName, NULL, CTX_NONE);
1901
1902
1903         WebcitAddUrlHandler(HKEY("delete_floor"), "", 0, delete_floor, 0);
1904         WebcitAddUrlHandler(HKEY("rename_floor"), "", 0, rename_floor, 0);
1905         WebcitAddUrlHandler(HKEY("create_floor"), "", 0, create_floor, 0);
1906
1907         WebcitAddUrlHandler(HKEY("knrooms"), "", 0, knrooms, 0);
1908         WebcitAddUrlHandler(HKEY("dotgoto"), "", 0, dotgoto, NEED_URL);
1909         WebcitAddUrlHandler(HKEY("dotskip"), "", 0, dotskip, NEED_URL);
1910
1911         WebcitAddUrlHandler(HKEY("goto_private"), "", 0, goto_private, NEED_URL);
1912         WebcitAddUrlHandler(HKEY("zap"), "", 0, zap, 0);
1913         WebcitAddUrlHandler(HKEY("entroom"), "", 0, entroom, 0);
1914         WebcitAddUrlHandler(HKEY("do_invt_kick"), "", 0, do_invt_kick, 0);
1915         
1916         WebcitAddUrlHandler(HKEY("netedit"), "", 0, netedit, 0);
1917         WebcitAddUrlHandler(HKEY("editroom"), "", 0, editroom, 0);
1918         WebcitAddUrlHandler(HKEY("delete_room"), "", 0, delete_room, 0);
1919         WebcitAddUrlHandler(HKEY("set_room_policy"), "", 0, set_room_policy, 0);
1920         WebcitAddUrlHandler(HKEY("changeview"), "", 0, change_view, 0);
1921         WebcitAddUrlHandler(HKEY("toggle_self_service"), "", 0, toggle_self_service, 0);
1922         RegisterNamespace("ROOMBANNER", 0, 1, tmplput_roombanner, NULL, CTX_NONE);
1923
1924         RegisterConditional(HKEY("COND:ROOM:TYPE_IS"), 0, ConditionalIsRoomtype, CTX_NONE);
1925         RegisterConditional(HKEY("COND:THISROOM:FLAG:QR"), 0, ConditionalCurrentRoomHas_QRFlag, CTX_NONE);
1926         RegisterConditional(HKEY("COND:ROOM:FLAG:QR"), 0, ConditionalRoomHas_QRFlag, CTX_ROOMS);
1927
1928         RegisterConditional(HKEY("COND:THISROOM:FLAG:QR2"), 0, ConditionalCurrentRoomHas_QRFlag2, CTX_NONE);
1929         RegisterConditional(HKEY("COND:ROOM:FLAG:QR2"), 0, ConditionalRoomHas_QRFlag2, CTX_ROOMS);
1930         RegisterConditional(HKEY("COND:ROOM:FLAG:UA"), 0, ConditionalRoomHas_UAFlag, CTX_ROOMS);
1931
1932         RegisterIterator("ITERATE:THISROOM:WHO_KNOWS", 0, NULL, GetWhoKnowsHash, NULL, DeleteHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
1933         RegisterNamespace("THISROOM:MSGS:NEW", 0, 0, tmplput_CurrentRoom_nNewMessages, NULL, CTX_NONE);
1934         RegisterNamespace("THISROOM:MSGS:TOTAL", 0, 0, tmplput_CurrentRoom_nTotalMessages, NULL, CTX_NONE);
1935
1936         RegisterNamespace("THISROOM:FLOOR:NAME", 0, 1, tmplput_CurrentRoomFloorName, NULL, CTX_NONE);
1937         RegisterNamespace("THISROOM:AIDE", 0, 1, tmplput_CurrentRoomAide, NULL, CTX_NONE);
1938         RegisterNamespace("THISROOM:PASS", 0, 1, tmplput_CurrentRoomPass, NULL, CTX_NONE);
1939         RegisterNamespace("THISROOM:DIRECTORY", 0, 1, tmplput_CurrentRoomDirectory, NULL, CTX_NONE);
1940         RegisterNamespace("THISROOM:ORDER", 0, 0, tmplput_CurrentRoomOrder, NULL, CTX_NONE);
1941         RegisterNamespace("THISROOM:DEFAULT_VIEW", 0, 0, tmplput_CurrentRoomDefView, NULL, CTX_NONE);
1942         RegisterConditional(HKEY("COND:THISROOM:HAVE_VIEW"), 0, ConditionalThisRoomHaveView, CTX_NONE);
1943         RegisterConditional(HKEY("COND:ALLOWED_DEFAULT_VIEW"), 0, ConditionalIsAllowedDefaultView, CTX_NONE);
1944
1945         RegisterNamespace("THISROOM:VIEW_STRING", 0, 1, tmplput_CurrentRoomViewString, NULL, CTX_NONE);
1946         RegisterNamespace("ROOM:VIEW_STRING", 1, 2, tmplput_RoomViewString, NULL, CTX_NONE);
1947
1948         RegisterNamespace("THISROOM:INFOTEXT", 1, 2, tmplput_CurrentRoomInfoText, NULL, CTX_NONE);
1949         RegisterConditional(HKEY("COND:THISROOM:ORDER"), 0, ConditionalThisRoomOrder, CTX_NONE);
1950         RegisterConditional(HKEY("COND:THISROOM:DEFAULT_VIEW"), 0, ConditionalThisRoomDefView, CTX_NONE);
1951         RegisterConditional(HKEY("COND:THISROOM:CURR_VIEW"), 0, ConditionalThisRoomCurrView, CTX_NONE);
1952         RegisterConditional(HKEY("COND:THISROOM:HAVE_PIC"), 0, ConditionalThisRoomXHavePic, CTX_NONE);
1953         RegisterConditional(HKEY("COND:THISROOM:HAVE_INFOTEXT"), 0, ConditionalThisRoomXHaveInfoText, CTX_NONE);
1954         RegisterNamespace("THISROOM:FILES:N", 0, 1, tmplput_CurrentRoomXNFiles, NULL, CTX_NONE);
1955         RegisterNamespace("THISROOM:FILES:STR", 0, 1, tmplput_CurrentRoomX_FileString, NULL, CTX_NONE);
1956
1957         REGISTERTokenParamDefine(QR_PERMANENT);
1958         REGISTERTokenParamDefine(QR_INUSE);
1959         REGISTERTokenParamDefine(QR_PRIVATE);
1960         REGISTERTokenParamDefine(QR_PASSWORDED);
1961         REGISTERTokenParamDefine(QR_GUESSNAME);
1962         REGISTERTokenParamDefine(QR_DIRECTORY);
1963         REGISTERTokenParamDefine(QR_UPLOAD);
1964         REGISTERTokenParamDefine(QR_DOWNLOAD);
1965         REGISTERTokenParamDefine(QR_VISDIR);
1966         REGISTERTokenParamDefine(QR_ANONONLY);
1967         REGISTERTokenParamDefine(QR_ANONOPT);
1968         REGISTERTokenParamDefine(QR_NETWORK);
1969         REGISTERTokenParamDefine(QR_PREFONLY);
1970         REGISTERTokenParamDefine(QR_READONLY);
1971         REGISTERTokenParamDefine(QR_MAILBOX);
1972         REGISTERTokenParamDefine(QR2_SYSTEM);
1973         REGISTERTokenParamDefine(QR2_SELFLIST);
1974         REGISTERTokenParamDefine(QR2_COLLABDEL);
1975         REGISTERTokenParamDefine(QR2_SUBJECTREQ);
1976         REGISTERTokenParamDefine(QR2_SMTP_PUBLIC);
1977         REGISTERTokenParamDefine(QR2_MODERATED);
1978
1979         REGISTERTokenParamDefine(UA_KNOWN);
1980         REGISTERTokenParamDefine(UA_GOTOALLOWED);
1981         REGISTERTokenParamDefine(UA_HASNEWMSGS);
1982         REGISTERTokenParamDefine(UA_ZAPPED);
1983         REGISTERTokenParamDefine(UA_POSTALLOWED);
1984         REGISTERTokenParamDefine(UA_ADMINALLOWED);
1985         REGISTERTokenParamDefine(UA_DELETEALLOWED);
1986         REGISTERTokenParamDefine(UA_ISTRASH);
1987
1988         REGISTERTokenParamDefine(US_NEEDVALID);
1989         REGISTERTokenParamDefine(US_PERM);
1990         REGISTERTokenParamDefine(US_LASTOLD);
1991         REGISTERTokenParamDefine(US_EXPERT);
1992         REGISTERTokenParamDefine(US_UNLISTED);
1993         REGISTERTokenParamDefine(US_NOPROMPT);
1994         REGISTERTokenParamDefine(US_PROMPTCTL);
1995         REGISTERTokenParamDefine(US_DISAPPEAR);
1996         REGISTERTokenParamDefine(US_REGIS);
1997         REGISTERTokenParamDefine(US_PAGINATOR);
1998         REGISTERTokenParamDefine(US_INTERNET);
1999         REGISTERTokenParamDefine(US_FLOORS);
2000         REGISTERTokenParamDefine(US_COLOR);
2001         REGISTERTokenParamDefine(US_USER_SET);
2002
2003         REGISTERTokenParamDefine(VIEW_BBS);
2004         REGISTERTokenParamDefine(VIEW_MAILBOX); 
2005         REGISTERTokenParamDefine(VIEW_ADDRESSBOOK);
2006         REGISTERTokenParamDefine(VIEW_CALENDAR);        
2007         REGISTERTokenParamDefine(VIEW_TASKS);   
2008         REGISTERTokenParamDefine(VIEW_NOTES);           
2009         REGISTERTokenParamDefine(VIEW_WIKI);            
2010         REGISTERTokenParamDefine(VIEW_CALBRIEF);
2011         REGISTERTokenParamDefine(VIEW_JOURNAL);
2012         REGISTERTokenParamDefine(VIEW_BLOG);
2013
2014         /* GNET types: */
2015         /* server internal, we need to know but ignore them. */
2016         REGISTERTokenParamDefine(subpending);
2017         REGISTERTokenParamDefine(unsubpending);
2018         REGISTERTokenParamDefine(lastsent);
2019
2020         REGISTERTokenParamDefine(ignet_push_share);
2021         { /* these are the parts of an IGNET push config */
2022                 REGISTERTokenParamDefine(GNET_IGNET_NODE);
2023                 REGISTERTokenParamDefine(GNET_IGNET_ROOM);
2024         }
2025         REGISTERTokenParamDefine(listrecp);
2026         REGISTERTokenParamDefine(digestrecp);
2027         REGISTERTokenParamDefine(pop3client);
2028         { /* These are the parts of a pop3 client line... */
2029                 REGISTERTokenParamDefine(GNET_POP3_HOST);
2030                 REGISTERTokenParamDefine(GNET_POP3_USER);
2031                 REGISTERTokenParamDefine(GNET_POP3_DONT_DELETE_REMOTE);
2032                 REGISTERTokenParamDefine(GNET_POP3_INTERVAL);
2033         }
2034         REGISTERTokenParamDefine(rssclient);
2035         REGISTERTokenParamDefine(participate);
2036
2037         RegisterConditional(HKEY("COND:ROOMAIDE"), 2, ConditionalRoomAide, CTX_NONE);
2038         RegisterConditional(HKEY("COND:ACCESS:DELETE"), 2, ConditionalRoomAcessDelete, CTX_NONE);
2039
2040         RegisterConditional(HKEY("COND:UNGOTO"), 0, ConditionalHaveUngoto, CTX_NONE);
2041         RegisterConditional(HKEY("COND:ROOM:EDITACCESS"), 0, ConditionalHaveRoomeditRights, CTX_NONE);
2042
2043         RegisterNamespace("CURRENT_ROOM", 0, 1, tmplput_current_room, NULL, CTX_NONE);
2044         RegisterNamespace("ROOM:UNGOTO", 0, 0, tmplput_ungoto, NULL, CTX_NONE);
2045         RegisterIterator("FLOORS", 0, NULL, GetFloorListHash, NULL, NULL, CTX_FLOORS, CTX_NONE, IT_NOFLAG);
2046
2047
2048 }
2049
2050
2051 void 
2052 SessionDestroyModule_ROOMOPS
2053 (wcsession *sess)
2054 {
2055         _FlushRoomList (sess);
2056 }
2057
2058
2059 /*@}*/