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