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