if StrBuf_ServGetln() is called in a loop, its return value has to be checked for...
[citadel.git] / webcit / roomops.c
1 /*
2  * Lots of different room-related operations.
3  *
4  * Copyright (c) 1996-2011 by the citadel.org team
5  *
6  * This program is open source software.  You can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20
21 #include "webcit.h"
22 #include "webserver.h"
23
24 ConstStr QRFlagList[] = {
25         {HKEY(strof(QR_PERMANENT))},
26         {HKEY(strof(QR_INUSE))},
27         {HKEY(strof(QR_PRIVATE))},
28         {HKEY(strof(QR_PASSWORDED))},
29         {HKEY(strof(QR_GUESSNAME))},
30         {HKEY(strof(QR_DIRECTORY))},
31         {HKEY(strof(QR_UPLOAD))},
32         {HKEY(strof(QR_DOWNLOAD))},
33         {HKEY(strof(QR_VISDIR))},
34         {HKEY(strof(QR_ANONONLY))},
35         {HKEY(strof(QR_ANONOPT))},
36         {HKEY(strof(QR_NETWORK))},
37         {HKEY(strof(QR_PREFONLY))},
38         {HKEY(strof(QR_READONLY))},
39         {HKEY(strof(QR_MAILBOX))}
40 };
41 ConstStr QR2FlagList[] = {
42         {HKEY(strof(QR2_SYSTEM))},
43         {HKEY(strof(QR2_SELFLIST))},
44         {HKEY(strof(QR2_COLLABDEL))},
45         {HKEY(strof(QR2_SUBJECTREQ))},
46         {HKEY(strof(QR2_SMTP_PUBLIC))},
47         {HKEY(strof(QR2_MODERATED))},
48         {HKEY("")}, 
49         {HKEY("")}, 
50         {HKEY("")}, 
51         {HKEY("")}, 
52         {HKEY("")}, 
53         {HKEY("")}, 
54         {HKEY("")}, 
55         {HKEY("")}, 
56         {HKEY("")}
57 };
58
59 void _DBG_QR(long QR)
60 {
61         int i = 1;
62         int j=0;
63         StrBuf *QRVec;
64
65         QRVec = NewStrBufPlain(NULL, 256);
66         while (i != 0)
67         {
68                 if ((QR & i) != 0) {
69                         if (StrLength(QRVec) > 0)
70                                 StrBufAppendBufPlain(QRVec, HKEY(" | "), 0);
71                         StrBufAppendBufPlain(QRVec, CKEY(QRFlagList[j]), 0);
72                 }
73                 i = i << 1;
74                 j++;
75         }
76         syslog(9, "DBG: QR-Vec [%ld] [%s]\n", QR, ChrPtr(QRVec));
77         FreeStrBuf(&QRVec);
78 }
79
80
81
82 void _DBG_QR2(long QR2)
83 {
84         int i = 1;
85         int j=0;
86         StrBuf *QR2Vec;
87
88         QR2Vec = NewStrBufPlain(NULL, 256);
89         while (i != 0)
90         {
91                 if ((QR2 & i) != 0) {
92                         if (StrLength(QR2Vec) > 0)
93                                 StrBufAppendBufPlain(QR2Vec, HKEY(" | "), 0);
94                         StrBufAppendBufPlain(QR2Vec, CKEY(QR2FlagList[j]), 0);
95                 }
96                 i = i << 1;
97                 j++;
98         }
99         syslog(9, "DBG: QR2-Vec [%ld] [%s]\n", QR2, ChrPtr(QR2Vec));
100         FreeStrBuf(&QR2Vec);
101 }
102
103
104
105
106
107
108
109
110
111
112
113 /*******************************************************************************
114  ***************************** Goto Commands ***********************************
115  ******************************************************************************/
116 void dotgoto(void) {
117         if (!havebstr("room")) {
118                 readloop(readnew, eUseDefault);
119                 return;
120         }
121         if (WC->CurRoom.view != VIEW_MAILBOX) { /* dotgoto acts like dotskip when we're in a mailbox view */
122                 slrp_highest();
123         }
124         smart_goto(sbstr("room"));
125 }
126
127 /*
128  * goto next room
129  */
130 void smart_goto(const StrBuf *next_room) {
131         gotoroom(next_room);
132         readloop(readnew, eUseDefault);
133 }
134
135 /*
136  * goto a private room
137  */
138 void goto_private(void)
139 {
140         char hold_rm[SIZ];
141         StrBuf *Buf;
142         const StrBuf *gr_name;
143         long err;
144
145         if (!havebstr("ok_button")) {
146                 display_main_menu();
147                 return;
148         }
149         gr_name = sbstr("gr_name");
150         Buf = NewStrBuf();
151         strcpy(hold_rm, ChrPtr(WC->CurRoom.name));
152         serv_printf("GOTO %s|%s",
153                     ChrPtr(gr_name),
154                     bstr("gr_pass"));
155         StrBuf_ServGetln(Buf);
156         if  (GetServerStatus(Buf, &err) == 2) {
157                 FlushRoomlist();
158                 smart_goto(gr_name);
159                 FreeStrBuf(&Buf);
160                 return;
161         }
162         if (err == 540) {
163                 DoTemplate(HKEY("room_display_private"), NULL, &NoCtx);
164                 FreeStrBuf(&Buf);
165                 return;
166         }
167         StrBufCutLeft(Buf, 4);
168         AppendImportantMessage (SKEY(Buf));
169         Buf = NewStrBufPlain(HKEY("_BASEROOM_"));
170         smart_goto(Buf);
171         FreeStrBuf(&Buf);
172         return;
173 }
174
175 /*
176  * back end routine to take the session to a new room
177  */
178 long gotoroom(const StrBuf *gname)
179 {
180         wcsession *WCC = WC;
181         StrBuf *Buf;
182         static long ls = (-1L);
183         long err = 0;
184
185         /* store ungoto information */
186         if (StrLength(gname) > 0)
187                 strcpy(WCC->ugname, ChrPtr(WCC->CurRoom.name));
188         WCC->uglsn = ls;
189         Buf = NewStrBuf();
190
191         /* move to the new room */
192         if (StrLength(gname) > 0)
193                 serv_printf("GOTO %s", ChrPtr(gname));
194         else /* or just refresh the current state... */
195                 serv_printf("GOTO 00000000000000000000");
196         StrBuf_ServGetln(Buf);
197         if  (GetServerStatus(Buf, &err) != 2) {
198                 serv_puts("GOTO _BASEROOM_");
199                 StrBuf_ServGetln(Buf);
200                 /* 
201                  * well, we know that this is the fallback case, 
202                  * but we're interested that the first command 
203                  * didn't work out in first place.
204                  */
205                 if (GetServerStatus(Buf, NULL) != 2) {
206                         FreeStrBuf(&Buf);
207                         return err;
208                 }
209         }
210         FlushFolder(&WCC->CurRoom);
211         ParseGoto(&WCC->CurRoom, Buf);
212
213         if (StrLength(gname) > 0)
214         {
215                 remove_march(WCC->CurRoom.name);
216                 if (!strcasecmp(ChrPtr(gname), "_BASEROOM_"))
217                         remove_march(gname);
218         }
219         FreeStrBuf(&Buf);
220
221         return err;
222 }
223
224
225
226 void ParseGoto(folder *room, StrBuf *Line)
227 {
228         wcsession *WCC = WC;
229         const char *Pos;
230         int flag;
231         void *vFloor = NULL;
232         StrBuf *pBuf;
233
234         if (StrLength(Line) < 4) {
235                 return;
236         }
237         
238         /* ignore the commandstate... */
239         Pos = ChrPtr(Line) + 4;
240
241         if (room->RoomNameParts != NULL)
242         {
243                 int i;
244                 for (i=0; i < room->nRoomNameParts; i++)
245                         FreeStrBuf(&room->RoomNameParts[i]);
246                 free(room->RoomNameParts);
247                 room->RoomNameParts = NULL;
248         }
249
250         pBuf = room->name;  
251         if (pBuf == NULL)
252                 pBuf = NewStrBufPlain(NULL, StrLength(Line));
253         else
254                 FlushStrBuf(pBuf);
255         memset(room, 0, sizeof(folder));
256         room->name = pBuf;
257
258         StrBufExtract_NextToken(room->name, Line, &Pos, '|'); // WC->CurRoom->name
259
260         room->nNewMessages = StrBufExtractNext_long(Line, &Pos, '|'); 
261         if (room->nNewMessages > 0)
262                 room->RAFlags |= UA_HASNEWMSGS;
263
264         room->nTotalMessages = StrBufExtractNext_long(Line, &Pos, '|');
265
266         room->ShowInfo =  StrBufExtractNext_long(Line, &Pos, '|');
267         
268         room->QRFlags = StrBufExtractNext_long(Line, &Pos, '|'); //CurRoom->QRFlags
269
270         DBG_QR(room->QRFlags);
271
272         room->HighestRead = StrBufExtractNext_long(Line, &Pos, '|');
273         room->LastMessageRead = StrBufExtractNext_long(Line, &Pos, '|');
274
275         room->is_inbox = StrBufExtractNext_long(Line, &Pos, '|'); // is_mailbox
276
277         flag = StrBufExtractNext_long(Line, &Pos, '|');
278         if (WCC->is_aide || flag) {
279                 room->RAFlags |= UA_ADMINALLOWED;
280         }
281
282         room->UsersNewMAilboxMessages = StrBufExtractNext_long(Line, &Pos, '|');
283
284         room->floorid = StrBufExtractNext_int(Line, &Pos, '|'); // wc_floor
285
286         room->view = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->view
287
288         room->defview = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->defview
289
290         flag = StrBufExtractNext_long(Line, &Pos, '|');
291         if (flag)
292                 room->RAFlags |= UA_ISTRASH; // wc_is_trash
293
294         room->QRFlags2 = StrBufExtractNext_long(Line, &Pos, '|'); // CurRoom->QRFlags2
295         DBG_QR2(room->QRFlags2);
296
297         /* find out, whether we are in a sub-room */
298         room->nRoomNameParts = StrBufNum_tokens(room->name, '\\');
299         if (room->nRoomNameParts > 1)
300         {
301                 int i;
302                 
303                 Pos = NULL;
304                 room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1));
305                 memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1));
306                 for (i=0; i < room->nRoomNameParts; i++)
307                 {
308                         room->RoomNameParts[i] = NewStrBuf();
309                         StrBufExtract_NextToken(room->RoomNameParts[i],
310                                                 room->name, &Pos, '\\');
311                 }
312         }
313
314         /* Private mailboxes on the main floor get remapped to the personal folder */
315         if ((room->QRFlags & QR_MAILBOX) && 
316             (room->floorid == 0))
317         {
318                 room->floorid = VIRTUAL_MY_FLOOR;
319                 if ((room->nRoomNameParts == 1) && 
320                     (StrLength(room->name) == 4) && 
321                     (strcmp(ChrPtr(room->name), "Mail") == 0))
322                 {
323                         room->is_inbox = 1;
324                 }
325                 
326         }
327         /* get a pointer to the floor we're on: */
328         if (WCC->Floors == NULL)
329                 GetFloorListHash(NULL, NULL);
330
331         GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
332         room->Floor = (const Floor*) vFloor;
333 }
334
335 /**
336  * \brief Delete the current room
337  */
338 void delete_room(void)
339 {
340         char buf[SIZ];
341
342         
343         serv_puts("KILL 1");
344         serv_getln(buf, sizeof buf);
345
346         if (buf[0] != '2') {
347                 strcpy(WC->ImportantMessage, &buf[4]);
348                 display_main_menu();
349                 return;
350         } else {
351                 StrBuf *Buf;
352                 
353                 FlushRoomlist ();
354                 Buf = NewStrBufPlain(HKEY("_BASEROOM_"));
355                 smart_goto(Buf);
356                 FreeStrBuf(&Buf);
357         }
358 }
359
360 /**
361  * \brief zap a room
362  */
363 void zap(void)
364 {
365         char buf[SIZ];
366         StrBuf *final_destination;
367
368         /**
369          * If the forget-room routine fails for any reason, we fall back
370          * to the current room; otherwise, we go to the Lobby
371          */
372         final_destination = NewStrBufDup(WC->CurRoom.name);
373
374         if (havebstr("ok_button")) {
375                 serv_printf("GOTO %s", ChrPtr(WC->CurRoom.name));
376                 serv_getln(buf, sizeof buf);
377                 if (buf[0] == '2') {
378                         serv_puts("FORG");
379                         serv_getln(buf, sizeof buf);
380                         if (buf[0] == '2') {
381                                 FlushStrBuf(final_destination);
382                                 StrBufAppendBufPlain(final_destination, HKEY("_BASEROOM_"), 0);
383                         }
384                 }
385                 FlushRoomlist ();
386         }
387         smart_goto(final_destination);
388         FreeStrBuf(&final_destination);
389 }
390
391
392 /*
393  * mark all messages in current room as having been read
394  */
395 void slrp_highest(void)
396 {
397         char buf[256];
398
399         serv_puts("SLRP HIGHEST");
400         serv_getln(buf, sizeof buf);
401 }
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 /*******************************************************************************
417  ***************************** Modify Rooms ************************************
418  ******************************************************************************/
419
420
421
422
423
424 void LoadRoomAide(void)
425 {
426         wcsession *WCC = WC;
427         StrBuf *Buf;
428         
429         if (WCC->CurRoom.RoomAideLoaded)
430                 return;
431
432         WCC->CurRoom.RoomAideLoaded = 1;
433         Buf = NewStrBuf();
434         serv_puts("GETA");
435         StrBuf_ServGetln(Buf);
436         if (GetServerStatus(Buf, NULL) != 2) {
437                 FlushStrBuf(WCC->CurRoom.RoomAide);
438                 AppendImportantMessage (ChrPtr(Buf) + 4, 
439                                         StrLength(Buf) - 4);
440         } else {
441                 const char *Pos;
442
443                 Pos = ChrPtr(Buf) + 4;
444
445                 FreeStrBuf(&WCC->CurRoom.RoomAide);
446                 WCC->CurRoom.RoomAide = NewStrBufPlain (NULL, StrLength (Buf));
447
448                 StrBufExtract_NextToken(WCC->CurRoom.RoomAide, Buf, &Pos, '|'); 
449         }
450         FreeStrBuf (&Buf);
451 }
452
453 int SaveRoomAide(folder *Room)
454 {
455         StrBuf *Buf;
456         Buf = NewStrBuf ();
457         serv_printf("SETA %s", ChrPtr(Room->RoomAide));
458         StrBuf_ServGetln(Buf);
459         if (GetServerStatus(Buf, NULL) != 2) {
460                 StrBufCutLeft(Buf, 4);
461                 AppendImportantMessage (SKEY(Buf));
462                 FreeStrBuf(&Buf);
463                 return 0;
464         }
465         FreeStrBuf(&Buf);
466         return 1;
467 }
468
469
470 int GetCurrentRoomFlags(folder *Room)
471 {
472         StrBuf *Buf;
473
474         Buf = NewStrBuf();
475         serv_puts("GETR");
476         StrBuf_ServGetln(Buf);
477         if (GetServerStatus(Buf, NULL) != 2) {
478                 FlushStrBuf(Room->XAPass);
479                 FlushStrBuf(Room->Directory);
480                 StrBufCutLeft(Buf, 4);
481                 AppendImportantMessage (SKEY(Buf));
482                 FreeStrBuf(&Buf);
483                 return 0;
484         } else {
485                 const char *Pos;
486
487                 Pos = ChrPtr(Buf) + 4;
488
489                 FreeStrBuf(&Room->XAPass);
490                 FreeStrBuf(&Room->Directory);
491
492                 Room->XAPass = NewStrBufPlain (NULL, StrLength (Buf));
493                 Room->Directory = NewStrBufPlain (NULL, StrLength (Buf));
494
495                 FreeStrBuf(&Room->name);
496                 Room->name = NewStrBufPlain(NULL, StrLength(Buf));
497                 StrBufExtract_NextToken(Room->name, Buf, &Pos, '|'); 
498                                         
499                 StrBufExtract_NextToken(Room->XAPass, Buf, &Pos, '|'); 
500                 StrBufExtract_NextToken(Room->Directory, Buf, &Pos, '|'); 
501                 
502                 Room->QRFlags = StrBufExtractNext_long(Buf, &Pos, '|');
503                 Room->floorid = StrBufExtractNext_long(Buf, &Pos, '|');
504                 Room->Order = StrBufExtractNext_long(Buf, &Pos, '|');
505                 Room->defview = StrBufExtractNext_long(Buf, &Pos, '|');
506                 Room->QRFlags2 = StrBufExtractNext_long(Buf, &Pos, '|');
507                 FreeStrBuf (&Buf);
508                 Room->XALoaded = 1;
509                 return 1;
510         }
511 }
512
513
514 int SetCurrentRoomFlags(folder *Room)
515 {
516         StrBuf *Buf;
517
518         Buf = NewStrBuf();
519         DBG_QR(Room->QRFlags);
520         DBG_QR2(Room->QRFlags2);
521
522         serv_printf("SETR %s|%s|%s|%ld|%d|%d|%ld|%ld|%ld",
523                     ChrPtr(Room->name),
524                     ChrPtr(Room->XAPass),
525                     ChrPtr(Room->Directory),
526                     Room->QRFlags, 
527                     Room->BumpUsers,
528                     Room->floorid, 
529                     Room->Order,
530                     Room->defview,
531                     Room->QRFlags2);
532
533         StrBuf_ServGetln(Buf);
534         if (GetServerStatus(Buf, NULL) != 2) {
535                 StrBufCutLeft(Buf, 4);
536                 AppendImportantMessage (SKEY(Buf));
537                 FreeStrBuf(&Buf);
538                 return 0;
539         } else {
540                 FreeStrBuf(&Buf);
541                 return 1;
542         }
543 }
544
545 void LoadRoomXA (void)
546 {
547         wcsession *WCC = WC;
548                 
549         if (WCC->CurRoom.XALoaded)
550                 return;
551
552         GetCurrentRoomFlags(&WCC->CurRoom);
553 }
554
555
556 void LoadXRoomPic(void)
557 {
558         wcsession *WCC = WC;
559         StrBuf *Buf;
560         
561         if (WCC->CurRoom.XHaveRoomPicLoaded)
562                 return;
563
564         WCC->CurRoom.XHaveRoomPicLoaded = 1;
565         Buf = NewStrBuf();
566         serv_puts("OIMG _roompic_");
567         StrBuf_ServGetln(Buf);
568         if (GetServerStatus(Buf, NULL) != 2) {
569                 WCC->CurRoom.XHaveRoomPic = 0;
570         } else {
571                 WCC->CurRoom.XHaveRoomPic = 1;
572         }
573         serv_puts("CLOS");
574         StrBuf_ServGetln(Buf);
575         GetServerStatus(Buf, NULL);
576         FreeStrBuf (&Buf);
577 }
578
579
580 void LoadXRoomInfoText(void)
581 {
582         wcsession *WCC = WC;
583         StrBuf *Buf;
584         int Done = 0;
585         
586         if (WCC->CurRoom.XHaveInfoTextLoaded) {
587                 return;
588         }
589
590         WCC->CurRoom.XHaveInfoTextLoaded = 1;
591         Buf = NewStrBuf();
592
593         serv_puts("RINF");
594
595         StrBuf_ServGetln(Buf);
596         if (GetServerStatus(Buf, NULL) == 1) {
597                 WCC->CurRoom.XInfoText = NewStrBuf ();
598                 
599                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
600                         if ( (StrLength(Buf)==3) && 
601                              !strcmp(ChrPtr(Buf), "000")) 
602                                 Done = 1;
603                         else 
604                                 StrBufAppendBuf(WCC->CurRoom.XInfoText, Buf, 0);
605                 }
606         }
607
608         FreeStrBuf(&Buf);
609 }
610
611
612 void LoadXRoomXCountFiles(void)
613 {
614         wcsession *WCC = WC;
615         StrBuf *Buf;
616         int Done = 0;
617         
618         if (WCC->CurRoom.XHaveDownloadCount)
619                 return;
620
621         WCC->CurRoom.XHaveDownloadCount = 1;
622
623         Buf = NewStrBuf();
624         serv_puts("RDIR");
625         StrBuf_ServGetln(Buf);
626         if (GetServerStatus(Buf, NULL) == 1) {
627                 
628                 while (!Done && StrBuf_ServGetln(Buf)>=0) {
629                         if ( (StrLength(Buf)==3) && 
630                              !strcmp(ChrPtr(Buf), "000")) 
631                                 Done = 1;
632                         else 
633                                 WCC->CurRoom.XDownloadCount++;
634                 }
635         }
636
637         FreeStrBuf (&Buf);
638 }
639
640
641 /* 
642  * Toggle self-service list subscription
643  */
644 void toggle_self_service(void) {
645         wcsession *WCC = WC;
646
647         if (GetCurrentRoomFlags (&WCC->CurRoom) == 0)
648                 return;
649
650         if (yesbstr("QR2_SelfList")) 
651                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SELFLIST;
652         else 
653                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SELFLIST;
654
655         if (yesbstr("QR2_SMTP_PUBLIC")) 
656                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SMTP_PUBLIC;
657         else
658                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SMTP_PUBLIC;
659
660         if (yesbstr("QR2_Moderated")) 
661                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_MODERATED;
662         else
663                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_MODERATED;
664         if (yesbstr("QR2_SubsOnly")) 
665                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 | QR2_SMTP_PUBLIC;
666         else
667                 WCC->CurRoom.QRFlags2 = WCC->CurRoom.QRFlags2 & ~QR2_SMTP_PUBLIC;
668
669         SetCurrentRoomFlags (&WCC->CurRoom);
670         
671         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
672 }
673
674
675
676 /*
677  * save new parameters for a room
678  */
679 void editroom(void)
680 {
681         wcsession *WCC = WC;
682         const StrBuf *Ptr;
683         const StrBuf *er_name;
684         const StrBuf *er_password;
685         const StrBuf *er_dirname;
686         const StrBuf *er_roomaide;
687         unsigned er_flags;
688         unsigned er_flags2;
689         int succ1, succ2;
690
691         if (!havebstr("ok_button")) {
692                 strcpy(WC->ImportantMessage,
693                        _("Cancelled.  Changes were not saved."));
694                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
695                 return;
696         }
697         if (GetCurrentRoomFlags (&WCC->CurRoom) == 0)
698                 return;
699
700         LoadRoomAide();
701
702         er_flags = WCC->CurRoom.QRFlags;
703         er_flags &= !(QR_PRIVATE | QR_PASSWORDED | QR_GUESSNAME);
704
705         er_flags2 = WCC->CurRoom.QRFlags2;
706
707         Ptr = sbstr("type");
708         if (!strcmp(ChrPtr(Ptr), "invonly")) {
709                 er_flags |= (QR_PRIVATE);
710         }
711         if (!strcmp(ChrPtr(Ptr), "hidden")) {
712                 er_flags |= (QR_PRIVATE | QR_GUESSNAME);
713         }
714         if (!strcmp(ChrPtr(Ptr), "passworded")) {
715                 er_flags |= (QR_PRIVATE | QR_PASSWORDED);
716         }
717         if (!strcmp(ChrPtr(Ptr), "personal")) {
718                 er_flags |= QR_MAILBOX;
719         } else {
720                 er_flags &= ~QR_MAILBOX;
721         }
722
723
724         
725         if (yesbstr("prefonly")) {
726                 er_flags |= QR_PREFONLY;
727         } else {
728                 er_flags &= ~QR_PREFONLY;
729         }
730
731         if (yesbstr("readonly")) {
732                 er_flags |= QR_READONLY;
733         } else {
734                 er_flags &= ~QR_READONLY;
735         }
736
737         
738         if (yesbstr("collabdel")) {
739                 er_flags2 |= QR2_COLLABDEL;
740         } else {
741                 er_flags2 &= ~QR2_COLLABDEL;
742         }
743
744         if (yesbstr("permanent")) {
745                 er_flags |= QR_PERMANENT;
746         } else {
747                 er_flags &= ~QR_PERMANENT;
748         }
749
750         if (yesbstr("subjectreq")) {
751                 er_flags2 |= QR2_SUBJECTREQ;
752         } else {
753                 er_flags2 &= ~QR2_SUBJECTREQ;
754         }
755
756         if (yesbstr("network")) {
757                 er_flags |= QR_NETWORK;
758         } else {
759                 er_flags &= ~QR_NETWORK;
760         }
761
762         if (yesbstr("directory")) {
763                 er_flags |= QR_DIRECTORY;
764         } else {
765                 er_flags &= ~QR_DIRECTORY;
766         }
767
768         if (yesbstr("ulallowed")) {
769                 er_flags |= QR_UPLOAD;
770         } else {
771                 er_flags &= ~QR_UPLOAD;
772         }
773
774         if (yesbstr("dlallowed")) {
775                 er_flags |= QR_DOWNLOAD;
776         } else {
777                 er_flags &= ~QR_DOWNLOAD;
778         }
779
780         if (yesbstr("visdir")) {
781                 er_flags |= QR_VISDIR;
782         } else {
783                 er_flags &= ~QR_VISDIR;
784         }
785
786
787         Ptr = sbstr("anon");
788
789         er_flags &= ~(QR_ANONONLY | QR_ANONOPT);
790         if (!strcmp(ChrPtr(Ptr), "anononly"))
791                 er_flags |= QR_ANONONLY;
792         if (!strcmp(ChrPtr(Ptr), "anon2"))
793                 er_flags |= QR_ANONOPT;
794
795         er_name     = sbstr("er_name");
796         er_dirname  = sbstr("er_dirname");
797         er_roomaide = sbstr("er_roomaide");
798         er_password = sbstr("er_password");
799
800         FlushStrBuf(WCC->CurRoom.name);
801         StrBufAppendBuf(WCC->CurRoom.name, er_name, 0);
802
803         FlushStrBuf(WCC->CurRoom.Directory);
804         StrBufAppendBuf(WCC->CurRoom.Directory, er_dirname, 0);
805
806         FlushStrBuf(WCC->CurRoom.RoomAide);
807         StrBufAppendBuf(WCC->CurRoom.RoomAide, er_roomaide, 0);
808
809         FlushStrBuf(WCC->CurRoom.XAPass);
810         StrBufAppendBuf(WCC->CurRoom.XAPass, er_password, 0);
811
812         WCC->CurRoom.BumpUsers = yesbstr("bump");
813
814         WCC->CurRoom.floorid = ibstr("er_floor");
815
816         succ1 = SetCurrentRoomFlags(&WCC->CurRoom);
817
818         succ2 = SaveRoomAide (&WCC->CurRoom);
819         
820         if (succ1 + succ2 == 0)
821                 AppendImportantMessage (_("Your changes have been saved."), -1);
822         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
823         return;
824 }
825
826
827
828 /*
829  * Display form for Invite, Kick, and show Who Knows a room
830  */
831 void do_invt_kick(void) 
832 {
833         StrBuf *Buf, *User;
834         const StrBuf *UserNames;
835         int Kick, Invite;
836         wcsession *WCC = WC;
837
838
839         if (GetCurrentRoomFlags(&WCC->CurRoom) == 1)
840         {
841                 const char *Pos;
842                 UserNames = sbstr("username");
843                 Kick = havebstr("kick_button");
844                 Invite = havebstr("invite_button");
845
846                 User = NewStrBufPlain(NULL, StrLength(UserNames));
847                 Buf = NewStrBuf();
848                 
849                 Pos = ChrPtr(UserNames);
850                 while (Pos != StrBufNOTNULL)
851                 {
852                         StrBufExtract_NextToken(User, UserNames, &Pos, ',');
853                         StrBufTrim(User);
854                         if ((StrLength(User) > 0) && (Kick))
855                         {
856                                 serv_printf("KICK %s", ChrPtr(User));
857                                 if (StrBuf_ServGetln(Buf) < 0)
858                                         break;
859                                 if (GetServerStatus(Buf, NULL) != 2) {
860                                         StrBufCutLeft(Buf, 4);
861                                         AppendImportantMessage(SKEY(Buf));
862                                 } else {
863                                         StrBufPrintf(Buf, 
864                                                      _("User '%s' kicked out of room '%s'."), 
865                                                      ChrPtr(User), 
866                                                      ChrPtr(WCC->CurRoom.name)
867                                                 );
868                                         AppendImportantMessage(SKEY(Buf));
869                                 }
870                         }
871                         else if ((StrLength(User) > 0) && (Invite))
872                         {
873                                 serv_printf("INVT %s", ChrPtr(User));
874                                 if (StrBuf_ServGetln(Buf) < 0)
875                                         break;
876                                 if (GetServerStatus(Buf, NULL) != 2) {
877                                         StrBufCutLeft(Buf, 4);
878                                         AppendImportantMessage(SKEY(Buf));
879                                 } else {
880                                         StrBufPrintf(Buf, 
881                                                      _("User '%s' invited to room '%s'."), 
882                                                      ChrPtr(User), 
883                                                      ChrPtr(WCC->CurRoom.name)
884                                                 );
885                                         AppendImportantMessage(SKEY(Buf));
886                                 }
887                         }
888                 }
889         }
890
891         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
892 }
893
894
895 /*
896  * Create a new room
897  */
898 void entroom(void)
899 {
900         char buf[SIZ];
901         const StrBuf *er_name;
902         const StrBuf *er_type;
903         const StrBuf *er_password;
904         int er_floor;
905         int er_num_type;
906         int er_view;
907         wcsession *WCC = WC;
908
909         if (!havebstr("ok_button")) {
910                 strcpy(WC->ImportantMessage,
911                        _("Cancelled.  No new room was created."));
912                 display_main_menu();
913                 return;
914         }
915         er_name = sbstr("er_name");
916         er_type = sbstr("type");
917         er_password = sbstr("er_password");
918         er_floor = ibstr("er_floor");
919         er_view = ibstr("er_view");
920
921         er_num_type = 0;
922         if (!strcmp(ChrPtr(er_type), "hidden"))
923                 er_num_type = 1;
924         else if (!strcmp(ChrPtr(er_type), "passworded"))
925                 er_num_type = 2;
926         else if (!strcmp(ChrPtr(er_type), "invonly"))
927                 er_num_type = 3;
928         else if (!strcmp(ChrPtr(er_type), "personal"))
929                 er_num_type = 4;
930
931         serv_printf("CRE8 1|%s|%d|%s|%d|%d|%d", 
932                     ChrPtr(er_name), 
933                     er_num_type, 
934                     ChrPtr(er_password), 
935                     er_floor, 
936                     0, 
937                     er_view);
938
939         serv_getln(buf, sizeof buf);
940         if (buf[0] != '2') {
941                 strcpy(WCC->ImportantMessage, &buf[4]);
942                 display_main_menu();
943                 return;
944         }
945         /** TODO: Room created, now update the left hand icon bar for this user */
946         gotoroom(er_name);
947
948         serv_printf("VIEW %d", er_view);
949         serv_getln(buf, sizeof buf);
950         WCC->CurRoom.view = er_view;
951
952         if ( (WCC != NULL) && ( (WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) )  {
953                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
954         } else {
955                 smart_goto(WCC->CurRoom.name);
956         }
957
958 }
959
960
961
962
963
964 /*
965  * Change the view for this room
966  */
967 void change_view(void) {
968         int newview;
969         char buf[SIZ];
970
971         newview = lbstr("view");
972         serv_printf("VIEW %d", newview);
973         serv_getln(buf, sizeof buf);
974         WC->CurRoom.view = newview;
975         smart_goto(WC->CurRoom.name);
976 }
977
978
979
980 /**
981  * \brief Set the message expire policy for this room and/or floor
982  */
983 void set_room_policy(void) {
984         char buf[SIZ];
985
986         if (!havebstr("ok_button")) {
987                 strcpy(WC->ImportantMessage,
988                        _("Cancelled.  Changes were not saved."));
989                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
990                 return;
991         }
992
993         serv_printf("SPEX roompolicy|%d|%d", ibstr("roompolicy"), ibstr("roomvalue"));
994         serv_getln(buf, sizeof buf);
995         strcpy(WC->ImportantMessage, &buf[4]);
996
997         if (WC->axlevel >= 6) {
998                 strcat(WC->ImportantMessage, "<br>\n");
999                 serv_printf("SPEX floorpolicy|%d|%d", ibstr("floorpolicy"), ibstr("floorvalue"));
1000                 serv_getln(buf, sizeof buf);
1001                 strcat(WC->ImportantMessage, &buf[4]);
1002         }
1003         ReloadCurrentRoom();
1004         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1005 }
1006
1007
1008
1009 /**
1010  * \brief Perform changes to a room's network configuration
1011  */
1012 void netedit(void) {
1013         FILE *fp;
1014         char buf[SIZ];
1015         char line[SIZ];
1016         char cmpa0[SIZ];
1017         char cmpa1[SIZ];
1018         char cmpb0[SIZ];
1019         char cmpb1[SIZ];
1020         int i, num_addrs;
1021         StrBuf *Line;
1022         int Done;
1023
1024         /*/ TODO: do line dynamic! */
1025         if (havebstr("line_pop3host")) {
1026                 strcpy(line, bstr("prefix"));
1027                 strcat(line, bstr("line_pop3host"));
1028                 strcat(line, "|");
1029                 strcat(line, bstr("line_pop3user"));
1030                 strcat(line, "|");
1031                 strcat(line, bstr("line_pop3pass"));
1032                 strcat(line, "|");
1033                 strcat(line, ibstr("line_pop3keep") ? "1" : "0" );
1034                 strcat(line, "|");
1035                 sprintf(&line[strlen(line)],"%ld", lbstr("line_pop3int"));
1036                 strcat(line, bstr("suffix"));
1037         }
1038         else if (havebstr("line")) {
1039                 strcpy(line, bstr("prefix"));
1040                 strcat(line, bstr("line"));
1041                 strcat(line, bstr("suffix"));
1042         }
1043         else {
1044                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1045                 return;
1046         }
1047
1048
1049         fp = tmpfile();
1050         if (fp == NULL) {
1051                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1052                 return;
1053         }
1054
1055         Line = NewStrBuf();
1056         serv_puts("GNET");
1057         StrBuf_ServGetln(Line);
1058         if  (GetServerStatus(Line, NULL) != 1) {
1059                 fclose(fp);
1060                 AppendImportantMessage(SRV_STATUS_MSG(Line));   
1061                 FreeStrBuf(&Line);
1062                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1063                 return;
1064         }
1065
1066         /** This loop works for add *or* remove.  Spiffy, eh? */
1067         Done = 0;
1068         extract_token(cmpb0, line, 0, '|', sizeof cmpb0);
1069         extract_token(cmpb1, line, 1, '|', sizeof cmpb1);
1070         while (!Done && StrBuf_ServGetln(Line)>=0) {
1071                 if ( (StrLength(Line)==3) && 
1072                      !strcmp(ChrPtr(Line), "000")) 
1073                 {
1074                         Done = 1;
1075                 }
1076                 else
1077                 {
1078                         extract_token(cmpa0, ChrPtr(Line), 0, '|', sizeof cmpa0);
1079                         extract_token(cmpa1, ChrPtr(Line), 1, '|', sizeof cmpa1);
1080                         if ( (strcasecmp(cmpa0, cmpb0)) 
1081                              || (strcasecmp(cmpa1, cmpb1)) ) {
1082                                 StrBufAppendBufPlain(Line, HKEY("\n"), 0);
1083                                 fwrite(SKEY(Line), 1, fp);
1084                         }
1085                 }
1086         }
1087
1088         rewind(fp);
1089         serv_puts("SNET");
1090         StrBuf_ServGetln(Line);
1091         if  (GetServerStatus(Line, NULL) != 4) {
1092                 fclose(fp);
1093                 AppendImportantMessage(SRV_STATUS_MSG(Line));   
1094                 http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1095                 FreeStrBuf(&Line);
1096                 return;
1097         }
1098
1099         while (fgets(buf, sizeof buf, fp) != NULL) {
1100                 buf[strlen(buf)-1] = 0;
1101                 serv_puts(buf);
1102         }
1103
1104         if (havebstr("add_button")) {
1105                 num_addrs = num_tokens(bstr("line"), ',');
1106                 if (num_addrs < 2) {
1107                         /* just adding one node or address */
1108                         serv_puts(line);
1109                 }
1110                 else {
1111                         /* adding multiple addresses separated by commas */
1112                         for (i=0; i<num_addrs; ++i) {
1113                                 strcpy(line, bstr("prefix"));
1114                                 extract_token(buf, bstr("line"), i, ',', sizeof buf);
1115                                 striplt(buf);
1116                                 strcat(line, buf);
1117                                 strcat(line, bstr("suffix"));
1118                                 serv_puts(line);
1119                         }
1120                 }
1121         }
1122
1123         serv_puts("000");
1124         fclose(fp);
1125         FlushIgnetCfgs(&WC->CurRoom);
1126         FreeStrBuf(&Line);
1127
1128         http_transmit_thing(ChrPtr(do_template("room_edit", NULL)), 0);
1129 }
1130
1131 /*
1132  * Known rooms list (box style)
1133  */
1134 void knrooms(void)
1135 {
1136         DeleteHash(&WC->Rooms);
1137         output_headers(1, 1, 1, 0, 0, 0); 
1138         do_template("knrooms", NULL);
1139         wDumpContent(1);
1140 }
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159 /*******************************************************************************
1160  ********************** FLOOR Coomands *****************************************
1161  ******************************************************************************/
1162
1163
1164
1165 /*
1166  * delete the actual floor
1167  */
1168 void delete_floor(void) {
1169         int floornum;
1170         StrBuf *Buf;
1171         const char *Err;
1172                 
1173         floornum = ibstr("floornum");
1174         Buf = NewStrBuf();
1175         serv_printf("KFLR %d|1", floornum);
1176         
1177         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1178
1179         if (GetServerStatus(Buf, NULL) == 2) {
1180                 StrBufPlain(Buf, _("Floor has been deleted."),-1);
1181         }
1182         else {
1183                 StrBufCutLeft(Buf, 4);
1184         }
1185         AppendImportantMessage (SKEY(Buf));
1186
1187         FlushRoomlist();
1188         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1189         FreeStrBuf(&Buf);
1190 }
1191
1192 /*
1193  * start creating a new floor
1194  */
1195 void create_floor(void) {
1196         StrBuf *Buf;
1197         const char *Err;
1198
1199         Buf = NewStrBuf();
1200         serv_printf("CFLR %s|1", bstr("floorname"));
1201         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1202
1203         if (GetServerStatus(Buf, NULL) == 2) {
1204                 StrBufPlain(Buf, _("New floor has been created."),-1);
1205         }
1206         else {
1207                 StrBufCutLeft(Buf, 4);
1208         }
1209         AppendImportantMessage (SKEY(Buf));
1210         FlushRoomlist();
1211         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1212         FreeStrBuf(&Buf);
1213 }
1214
1215
1216 /*
1217  * rename this floor
1218  */
1219 void rename_floor(void) {
1220         StrBuf *Buf;
1221
1222         Buf = NewStrBuf();
1223         FlushRoomlist();
1224
1225         serv_printf("EFLR %d|%s", ibstr("floornum"), bstr("floorname"));
1226         StrBuf_ServGetln(Buf);
1227
1228         StrBufCutLeft(Buf, 4);
1229         AppendImportantMessage (SKEY(Buf));
1230
1231         http_transmit_thing(ChrPtr(do_template("floors", NULL)), 0);
1232         FreeStrBuf(&Buf);
1233 }
1234
1235
1236
1237 void jsonRoomFlr(void) 
1238 {
1239         /* Send as our own (application/json) content type */
1240         hprintf("HTTP/1.1 200 OK\r\n");
1241         hprintf("Content-type: application/json; charset=utf-8\r\n");
1242         hprintf("Server: %s / %s\r\n", PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software));
1243         hprintf("Connection: close\r\n");
1244         hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n");
1245         begin_burst();
1246         DoTemplate(HKEY("json_roomflr"),NULL,&NoCtx);
1247         end_burst(); 
1248 }
1249
1250 void _FlushRoomList(wcsession *WCC)
1251 {
1252         free_march_list(WCC);
1253         DeleteHash(&WCC->Floors);
1254         DeleteHash(&WCC->Rooms);
1255         DeleteHash(&WCC->FloorsByName);
1256         FlushFolder(&WCC->CurRoom);
1257 }
1258
1259 void ReloadCurrentRoom(void)
1260 {
1261         wcsession *WCC = WC;
1262         StrBuf *CurRoom;
1263
1264         CurRoom = WCC->CurRoom.name;
1265         WCC->CurRoom.name = NULL;
1266         _FlushRoomList(WCC);
1267         gotoroom(CurRoom);
1268         FreeStrBuf(&CurRoom);
1269 }
1270
1271 void FlushRoomlist(void)
1272 {
1273         wcsession *WCC = WC;
1274         _FlushRoomList(WCC);
1275 }
1276
1277
1278 void 
1279 InitModule_ROOMOPS
1280 (void)
1281 {
1282         RegisterPreference("roomlistview",
1283                            _("Room list view"),
1284                            PRF_STRING,
1285                            NULL);
1286         RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO, NULL);
1287
1288         
1289         WebcitAddUrlHandler(HKEY("json_roomflr"), "", 0, jsonRoomFlr, 0);
1290
1291         WebcitAddUrlHandler(HKEY("delete_floor"), "", 0, delete_floor, 0);
1292         WebcitAddUrlHandler(HKEY("rename_floor"), "", 0, rename_floor, 0);
1293         WebcitAddUrlHandler(HKEY("create_floor"), "", 0, create_floor, 0);
1294
1295         WebcitAddUrlHandler(HKEY("knrooms"), "", 0, knrooms, ANONYMOUS);
1296         WebcitAddUrlHandler(HKEY("dotgoto"), "", 0, dotgoto, NEED_URL);
1297         WebcitAddUrlHandler(HKEY("dotskip"), "", 0, dotskip, NEED_URL);
1298
1299         WebcitAddUrlHandler(HKEY("goto_private"), "", 0, goto_private, NEED_URL);
1300         WebcitAddUrlHandler(HKEY("zap"), "", 0, zap, 0);
1301         WebcitAddUrlHandler(HKEY("entroom"), "", 0, entroom, 0);
1302         WebcitAddUrlHandler(HKEY("do_invt_kick"), "", 0, do_invt_kick, 0);
1303         
1304         WebcitAddUrlHandler(HKEY("netedit"), "", 0, netedit, 0);
1305         WebcitAddUrlHandler(HKEY("editroom"), "", 0, editroom, 0);
1306         WebcitAddUrlHandler(HKEY("delete_room"), "", 0, delete_room, 0);
1307         WebcitAddUrlHandler(HKEY("set_room_policy"), "", 0, set_room_policy, 0);
1308         WebcitAddUrlHandler(HKEY("changeview"), "", 0, change_view, 0);
1309         WebcitAddUrlHandler(HKEY("toggle_self_service"), "", 0, toggle_self_service, 0);
1310
1311
1312         REGISTERTokenParamDefine(QR_PERMANENT);
1313         REGISTERTokenParamDefine(QR_INUSE);
1314         REGISTERTokenParamDefine(QR_PRIVATE);
1315         REGISTERTokenParamDefine(QR_PASSWORDED);
1316         REGISTERTokenParamDefine(QR_GUESSNAME);
1317         REGISTERTokenParamDefine(QR_DIRECTORY);
1318         REGISTERTokenParamDefine(QR_UPLOAD);
1319         REGISTERTokenParamDefine(QR_DOWNLOAD);
1320         REGISTERTokenParamDefine(QR_VISDIR);
1321         REGISTERTokenParamDefine(QR_ANONONLY);
1322         REGISTERTokenParamDefine(QR_ANONOPT);
1323         REGISTERTokenParamDefine(QR_NETWORK);
1324         REGISTERTokenParamDefine(QR_PREFONLY);
1325         REGISTERTokenParamDefine(QR_READONLY);
1326         REGISTERTokenParamDefine(QR_MAILBOX);
1327         REGISTERTokenParamDefine(QR2_SYSTEM);
1328         REGISTERTokenParamDefine(QR2_SELFLIST);
1329         REGISTERTokenParamDefine(QR2_COLLABDEL);
1330         REGISTERTokenParamDefine(QR2_SUBJECTREQ);
1331         REGISTERTokenParamDefine(QR2_SMTP_PUBLIC);
1332         REGISTERTokenParamDefine(QR2_MODERATED);
1333
1334         REGISTERTokenParamDefine(UA_KNOWN);
1335         REGISTERTokenParamDefine(UA_GOTOALLOWED);
1336         REGISTERTokenParamDefine(UA_HASNEWMSGS);
1337         REGISTERTokenParamDefine(UA_ZAPPED);
1338         REGISTERTokenParamDefine(UA_POSTALLOWED);
1339         REGISTERTokenParamDefine(UA_ADMINALLOWED);
1340         REGISTERTokenParamDefine(UA_DELETEALLOWED);
1341         REGISTERTokenParamDefine(UA_ISTRASH);
1342
1343         REGISTERTokenParamDefine(US_NEEDVALID);
1344         REGISTERTokenParamDefine(US_PERM);
1345         REGISTERTokenParamDefine(US_LASTOLD);
1346         REGISTERTokenParamDefine(US_EXPERT);
1347         REGISTERTokenParamDefine(US_UNLISTED);
1348         REGISTERTokenParamDefine(US_NOPROMPT);
1349         REGISTERTokenParamDefine(US_PROMPTCTL);
1350         REGISTERTokenParamDefine(US_DISAPPEAR);
1351         REGISTERTokenParamDefine(US_REGIS);
1352         REGISTERTokenParamDefine(US_PAGINATOR);
1353         REGISTERTokenParamDefine(US_INTERNET);
1354         REGISTERTokenParamDefine(US_FLOORS);
1355         REGISTERTokenParamDefine(US_COLOR);
1356         REGISTERTokenParamDefine(US_USER_SET);
1357
1358         REGISTERTokenParamDefine(VIEW_BBS);
1359         REGISTERTokenParamDefine(VIEW_MAILBOX); 
1360         REGISTERTokenParamDefine(VIEW_ADDRESSBOOK);
1361         REGISTERTokenParamDefine(VIEW_CALENDAR);        
1362         REGISTERTokenParamDefine(VIEW_TASKS);   
1363         REGISTERTokenParamDefine(VIEW_NOTES);           
1364         REGISTERTokenParamDefine(VIEW_WIKI);            
1365         REGISTERTokenParamDefine(VIEW_CALBRIEF);
1366         REGISTERTokenParamDefine(VIEW_JOURNAL);
1367         REGISTERTokenParamDefine(VIEW_BLOG);
1368
1369         /* GNET types: */
1370         /* server internal, we need to know but ignore them. */
1371         REGISTERTokenParamDefine(subpending);
1372         REGISTERTokenParamDefine(unsubpending);
1373         REGISTERTokenParamDefine(lastsent);
1374
1375         REGISTERTokenParamDefine(ignet_push_share);
1376         { /* these are the parts of an IGNET push config */
1377                 REGISTERTokenParamDefine(GNET_IGNET_NODE);
1378                 REGISTERTokenParamDefine(GNET_IGNET_ROOM);
1379         }
1380         REGISTERTokenParamDefine(listrecp);
1381         REGISTERTokenParamDefine(digestrecp);
1382         REGISTERTokenParamDefine(pop3client);
1383         { /* These are the parts of a pop3 client line... */
1384                 REGISTERTokenParamDefine(GNET_POP3_HOST);
1385                 REGISTERTokenParamDefine(GNET_POP3_USER);
1386                 REGISTERTokenParamDefine(GNET_POP3_DONT_DELETE_REMOTE);
1387                 REGISTERTokenParamDefine(GNET_POP3_INTERVAL);
1388         }
1389         REGISTERTokenParamDefine(rssclient);
1390         REGISTERTokenParamDefine(participate);
1391
1392
1393
1394 }
1395
1396
1397 void 
1398 SessionDestroyModule_ROOMOPS
1399 (wcsession *sess)
1400 {
1401         _FlushRoomList (sess);
1402 }
1403