ae101adb80031b246c2858a4c9c304323dee44c1
[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(strof(QR2_NOUPLMSG))}, 
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) / 100 == 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("ulmsg")) {
810                 WCC->CurRoom.QRFlags2 |= QR2_NOUPLMSG;
811         } else {
812                 WCC->CurRoom.QRFlags2 &= ~QR2_NOUPLMSG;
813         }
814
815         if (yesbstr("visdir")) {
816                 WCC->CurRoom.QRFlags |= QR_VISDIR;
817         } else {
818                 WCC->CurRoom.QRFlags &= ~QR_VISDIR;
819         }
820
821         Ptr = sbstr("anon");
822
823         WCC->CurRoom.QRFlags &= ~(QR_ANONONLY | QR_ANONOPT);
824         if (!strcmp(ChrPtr(Ptr), "anononly"))
825                 WCC->CurRoom.QRFlags |= QR_ANONONLY;
826         if (!strcmp(ChrPtr(Ptr), "anon2"))
827                 WCC->CurRoom.QRFlags |= QR_ANONOPT;
828
829         er_name     = sbstr("er_name");
830         er_dirname  = sbstr("er_dirname");
831         er_roomaide = sbstr("er_roomaide");
832         er_password = sbstr("er_password");
833
834         FlushStrBuf(WCC->CurRoom.name);
835         StrBufAppendBuf(WCC->CurRoom.name, er_name, 0);
836
837         FlushStrBuf(WCC->CurRoom.Directory);
838         StrBufAppendBuf(WCC->CurRoom.Directory, er_dirname, 0);
839
840         FlushStrBuf(WCC->CurRoom.RoomAide);
841         StrBufAppendBuf(WCC->CurRoom.RoomAide, er_roomaide, 0);
842
843         FlushStrBuf(WCC->CurRoom.XAPass);
844         StrBufAppendBuf(WCC->CurRoom.XAPass, er_password, 0);
845
846         WCC->CurRoom.BumpUsers = yesbstr("bump");
847
848         WCC->CurRoom.floorid = ibstr("er_floor");
849
850         succ1 = SetCurrentRoomFlags(&WCC->CurRoom);
851
852         succ2 = SaveRoomAide (&WCC->CurRoom);
853         
854         if (succ1 + succ2 == 0) {
855                 AppendImportantMessage (_("Your changes have been saved."), -1);
856         }
857         output_headers(1, 1, 1, 0, 0, 0);       
858         do_template("room_edit");
859         wDumpContent(1);
860         return;
861 }
862
863
864
865 /*
866  * Display form for Invite, Kick, and show Who Knows a room
867  */
868 void do_invt_kick(void) 
869 {
870         StrBuf *Buf, *User;
871         const StrBuf *UserNames;
872         int Kick, Invite;
873         wcsession *WCC = WC;
874
875
876         if (GetCurrentRoomFlags(&WCC->CurRoom, 1) == 1)
877         {
878                 const char *Pos;
879                 UserNames = sbstr("username");
880                 Kick = havebstr("kick_button");
881                 Invite = havebstr("invite_button");
882
883                 User = NewStrBufPlain(NULL, StrLength(UserNames));
884                 Buf = NewStrBuf();
885                 
886                 Pos = ChrPtr(UserNames);
887                 while (Pos != StrBufNOTNULL)
888                 {
889                         StrBufExtract_NextToken(User, UserNames, &Pos, ',');
890                         StrBufTrim(User);
891                         if ((StrLength(User) > 0) && (Kick))
892                         {
893                                 serv_printf("KICK %s", ChrPtr(User));
894                                 if (StrBuf_ServGetln(Buf) < 0)
895                                         break;
896                                 if (GetServerStatus(Buf, NULL) != 2) {
897                                         StrBufCutLeft(Buf, 4);
898                                         AppendImportantMessage(SKEY(Buf));
899                                 } else {
900                                         StrBufPrintf(Buf, 
901                                                      _("User '%s' kicked out of room '%s'."), 
902                                                      ChrPtr(User), 
903                                                      ChrPtr(WCC->CurRoom.name)
904                                                 );
905                                         AppendImportantMessage(SKEY(Buf));
906                                 }
907                         }
908                         else if ((StrLength(User) > 0) && (Invite))
909                         {
910                                 serv_printf("INVT %s", ChrPtr(User));
911                                 if (StrBuf_ServGetln(Buf) < 0)
912                                         break;
913                                 if (GetServerStatus(Buf, NULL) != 2) {
914                                         StrBufCutLeft(Buf, 4);
915                                         AppendImportantMessage(SKEY(Buf));
916                                 } else {
917                                         StrBufPrintf(Buf, 
918                                                      _("User '%s' invited to room '%s'."), 
919                                                      ChrPtr(User), 
920                                                      ChrPtr(WCC->CurRoom.name)
921                                                 );
922                                         AppendImportantMessage(SKEY(Buf));
923                                 }
924                         }
925                 }
926         }
927
928         output_headers(1, 1, 1, 0, 0, 0);       
929         do_template("room_edit");
930         wDumpContent(1);
931 }
932
933
934 /*
935  * Create a new room
936  */
937 void entroom(void)
938 {
939         StrBuf *Line;
940         const StrBuf *er_name;
941         const StrBuf *er_type;
942         const StrBuf *er_password;
943         int er_floor;
944         int er_num_type;
945         int er_view;
946         wcsession *WCC = WC;
947
948         if (!havebstr("ok_button")) {
949                 AppendImportantMessage(_("Cancelled.  No new room was created."), -1);
950                 display_main_menu();
951                 return;
952         }
953         er_name = sbstr("er_name");
954         er_type = sbstr("type");
955         er_password = sbstr("er_password");
956         er_floor = ibstr("er_floor");
957         er_view = ibstr("er_view");
958
959         er_num_type = 0;
960         if (!strcmp(ChrPtr(er_type), "hidden"))
961                 er_num_type = 1;
962         else if (!strcmp(ChrPtr(er_type), "passworded"))
963                 er_num_type = 2;
964         else if (!strcmp(ChrPtr(er_type), "invonly"))
965                 er_num_type = 3;
966         else if (!strcmp(ChrPtr(er_type), "personal"))
967                 er_num_type = 4;
968
969         serv_printf("CRE8 1|%s|%d|%s|%d|%d|%d", 
970                     ChrPtr(er_name), 
971                     er_num_type, 
972                     ChrPtr(er_password), 
973                     er_floor, 
974                     0, 
975                     er_view);
976
977         Line = NewStrBuf();
978         StrBuf_ServGetln(Line);
979         if (GetServerStatusMsg(Line, NULL, 1, 2) != 2) {
980                 FreeStrBuf(&Line);
981                 display_main_menu();
982                 return;
983         }
984         /** TODO: Room created, now update the left hand icon bar for this user */
985         gotoroom(er_name);
986
987         serv_printf("VIEW %d", er_view);
988         StrBuf_ServGetln(Line);
989         FreeStrBuf(&Line); /* TODO: should we care about errors? */
990         WCC->CurRoom.view = er_view;
991
992         if ( (WCC != NULL) && ( (WCC->CurRoom.RAFlags & UA_ADMINALLOWED) != 0) )  {
993                 output_headers(1, 1, 1, 0, 0, 0);       
994                 do_template("room_edit");
995                 wDumpContent(1);
996         } else {
997                 smart_goto(WCC->CurRoom.name);
998         }
999         FreeStrBuf(&Line);
1000 }
1001
1002
1003
1004
1005
1006 /*
1007  * Change the view for this room
1008  */
1009 void change_view(void) {
1010         int newview;
1011         char buf[SIZ];
1012
1013         newview = lbstr("view");
1014         serv_printf("VIEW %d", newview);
1015         serv_getln(buf, sizeof buf);
1016         WC->CurRoom.view = newview;
1017         smart_goto(WC->CurRoom.name);
1018 }
1019
1020
1021
1022 /*
1023  * Set the message expire policy for this room and/or floor
1024  */
1025 void set_room_policy(void) {
1026         StrBuf *Line;
1027
1028         if (!havebstr("ok_button")) {
1029                 AppendImportantMessage(_("Cancelled.  Changes were not saved."), -1);
1030                 output_headers(1, 1, 1, 0, 0, 0);       
1031                 do_template("room_edit");
1032                 wDumpContent(1);
1033                 return;
1034         }
1035
1036         Line = NewStrBuf();
1037
1038         serv_printf("SPEX room|%d|%d", ibstr("roompolicy"), ibstr("roomvalue"));
1039         StrBuf_ServGetln(Line);
1040         GetServerStatusMsg(Line, NULL, 1, 0);
1041         if (WC->axlevel >= 6) {
1042                 serv_printf("SPEX floor|%d|%d", ibstr("floorpolicy"), ibstr("floorvalue"));
1043                 StrBuf_ServGetln(Line);
1044                 GetServerStatusMsg(Line, NULL, 1, 0);
1045         }
1046         FreeStrBuf(&Line);
1047         ReloadCurrentRoom();
1048
1049         output_headers(1, 1, 1, 0, 0, 0);       
1050         do_template("room_edit");
1051         wDumpContent(1);
1052 }
1053
1054
1055
1056 /*
1057  * Perform changes to a room's network configuration
1058  */
1059 void netedit(void) {
1060         char buf[SIZ];
1061         char line[SIZ];
1062         char cmpa0[SIZ];
1063         char cmpa1[SIZ];
1064         char cmpb0[SIZ];
1065         char cmpb1[SIZ];
1066         int i, num_addrs;
1067         StrBuf *Line;
1068         StrBuf *TmpBuf;
1069         int malias = 0;
1070         int malias_set_default = 0;
1071         char sepchar = '|';
1072         int Done;
1073
1074         line[0] = '\0';
1075         if (havebstr("force_room")) {
1076                 gotoroom(sbstr("force_room"));
1077         }
1078         /*/ TODO: do line dynamic! */
1079         if (havebstr("line_pop3host")) {
1080                 strcpy(line, bstr("prefix"));
1081                 strcat(line, bstr("line_pop3host"));
1082                 strcat(line, "|");
1083                 strcat(line, bstr("line_pop3user"));
1084                 strcat(line, "|");
1085                 strcat(line, bstr("line_pop3pass"));
1086                 strcat(line, "|");
1087                 strcat(line, ibstr("line_pop3keep") ? "1" : "0" );
1088                 strcat(line, "|");
1089                 sprintf(&line[strlen(line)],"%ld", lbstr("line_pop3int"));
1090                 strcat(line, bstr("suffix"));
1091         }
1092         else if (havebstr("line")) {
1093                 strcpy(line, bstr("prefix"));
1094                 strcat(line, bstr("line"));
1095                 strcat(line, bstr("suffix"));
1096         }
1097         else if (havebstr("alias")) {
1098                 const char *domain;
1099                 domain = bstr("aliasdomain");
1100                 if ((domain == NULL) || IsEmptyStr(domain))
1101                 {
1102                         malias_set_default = 1;
1103                         strcpy(line, bstr("prefix"));
1104                         strcat(line, bstr("default_aliasdomain"));
1105                 }
1106                 else
1107                 {
1108                         malias = 1;
1109                         sepchar = ',';
1110                         strcat(line, bstr("prefix"));
1111                         if (!IsEmptyStr(domain))
1112                         {
1113                                 strcat(line, "@");
1114                                 strcat(line, domain);
1115                         }
1116                         strcat(line, ",");
1117                         strcat(line, "room_");
1118                         strcat(line, ChrPtr(WC->CurRoom.name));
1119                 }
1120         }
1121         else {
1122                 output_headers(1, 1, 1, 0, 0, 0);       
1123                 do_template("room_edit");
1124                 wDumpContent(1);
1125                 return;
1126         }
1127
1128         Line = NewStrBuf();
1129         TmpBuf = NewStrBuf();
1130         if (malias)
1131                 serv_puts("GNET "FILE_MAILALIAS);
1132         else
1133                 serv_puts("GNET");
1134         StrBuf_ServGetln(Line);
1135         if  (GetServerStatus(Line, NULL) != 1) {
1136                 AppendImportantMessage(SRV_STATUS_MSG(Line));   
1137                 FreeStrBuf(&Line);
1138                 output_headers(1, 1, 1, 0, 0, 0);       
1139                 do_template("room_edit");
1140                 wDumpContent(1);
1141                 return;
1142         }
1143
1144         /** This loop works for add *or* remove.  Spiffy, eh? */
1145         Done = 0;
1146         extract_token(cmpb0, line, 0, sepchar, sizeof cmpb0);
1147         extract_token(cmpb1, line, 1, sepchar, sizeof cmpb1);
1148         while (!Done && StrBuf_ServGetln(Line)>=0) {
1149                 if ( (StrLength(Line)==3) && 
1150                      !strcmp(ChrPtr(Line), "000")) 
1151                 {
1152                         Done = 1;
1153                 }
1154                 else
1155                 {
1156                         if (StrLength(Line) == 0)
1157                                 continue;
1158
1159                         if (malias_set_default)
1160                         {
1161                                 if (strncasecmp(ChrPtr(Line), HKEY("roommailalias|")) != 0)
1162                                 {
1163                                         StrBufAppendBufPlain(Line, HKEY("\n"), 0);
1164                                         StrBufAppendBuf(TmpBuf, Line, 0);
1165                                 }
1166                         }
1167                         else
1168                         {
1169                                 extract_token(cmpa0, ChrPtr(Line), 0, sepchar, sizeof cmpa0);
1170                                 extract_token(cmpa1, ChrPtr(Line), 1, sepchar, sizeof cmpa1);
1171                                 if ( (strcasecmp(cmpa0, cmpb0)) || (strcasecmp(cmpa1, cmpb1)) )
1172                                 {
1173                                         StrBufAppendBufPlain(Line, HKEY("\n"), 0);
1174                                         StrBufAppendBuf(TmpBuf, Line, 0);
1175                                 }
1176                         }
1177                 }
1178         }
1179
1180         if (malias)
1181                 serv_puts("SNET "FILE_MAILALIAS);
1182         else
1183                 serv_puts("SNET");
1184         StrBuf_ServGetln(Line);
1185         if  (GetServerStatus(Line, NULL) != 4) {
1186
1187                 AppendImportantMessage(SRV_STATUS_MSG(Line));   
1188                 output_headers(1, 1, 1, 0, 0, 0);       
1189                 do_template("room_edit");
1190                 wDumpContent(1);
1191                 FreeStrBuf(&Line);
1192                 FreeStrBuf(&TmpBuf);
1193                 return;
1194         }
1195
1196         serv_putbuf(TmpBuf);
1197         FreeStrBuf(&TmpBuf);
1198
1199         if (havebstr("add_button")) {
1200                 num_addrs = num_tokens(bstr("line"), ',');
1201                 if (num_addrs < 2) {
1202                         /* just adding one node or address */
1203                         serv_puts(line);
1204                 }
1205                 else {
1206                         /* adding multiple addresses separated by commas */
1207                         for (i=0; i<num_addrs; ++i) {
1208                                 strcpy(line, bstr("prefix"));
1209                                 extract_token(buf, bstr("line"), i, ',', sizeof buf);
1210                                 striplt(buf);
1211                                 strcat(line, buf);
1212                                 strcat(line, bstr("suffix"));
1213                                 serv_puts(line);
1214                         }
1215                 }
1216         }
1217
1218         serv_puts("000");
1219         serv_puts("NOOP");
1220         StrBuf_ServGetln(Line);
1221         if  (GetServerStatus(Line, NULL) != 2) { /* WHOOOPS? ERROR? */
1222                 AppendImportantMessage(SRV_STATUS_MSG(Line));   
1223                 StrBuf_ServGetln(Line); /* resync... */
1224         }
1225
1226
1227         FlushIgnetCfgs(&WC->CurRoom);
1228         FreeStrBuf(&Line);
1229
1230         output_headers(1, 1, 1, 0, 0, 0);       
1231         do_template("room_edit");
1232         wDumpContent(1);
1233 }
1234
1235 /*
1236  * Known rooms list (box style)
1237  */
1238 void knrooms(void)
1239 {
1240         DeleteHash(&WC->Rooms);
1241         output_headers(1, 1, 1, 0, 0, 0); 
1242         do_template("knrooms");
1243         wDumpContent(1);
1244 }
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 /*******************************************************************************
1264  ********************** FLOOR Coomands *****************************************
1265  ******************************************************************************/
1266
1267
1268
1269 /*
1270  * delete the actual floor
1271  */
1272 void delete_floor(void) {
1273         int floornum;
1274         StrBuf *Buf;
1275         const char *Err;
1276                 
1277         floornum = ibstr("floornum");
1278         Buf = NewStrBuf();
1279         serv_printf("KFLR %d|1", floornum);
1280         
1281         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1282
1283         if (GetServerStatus(Buf, NULL) == 2) {
1284                 StrBufPlain(Buf, _("Floor has been deleted."),-1);
1285         }
1286         else {
1287                 StrBufCutLeft(Buf, 4);
1288         }
1289         AppendImportantMessage (SKEY(Buf));
1290
1291         FlushRoomlist();
1292         http_transmit_thing(ChrPtr(do_template("floors")), 0);
1293         FreeStrBuf(&Buf);
1294 }
1295
1296 /*
1297  * start creating a new floor
1298  */
1299 void create_floor(void) {
1300         StrBuf *Buf;
1301         const char *Err;
1302
1303         Buf = NewStrBuf();
1304         serv_printf("CFLR %s|1", bstr("floorname"));
1305         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
1306
1307         if (GetServerStatus(Buf, NULL) == 2) {
1308                 StrBufPlain(Buf, _("New floor has been created."),-1);
1309         }
1310         else {
1311                 StrBufCutLeft(Buf, 4);
1312         }
1313         AppendImportantMessage (SKEY(Buf));
1314         FlushRoomlist();
1315         http_transmit_thing(ChrPtr(do_template("floors")), 0);
1316         FreeStrBuf(&Buf);
1317 }
1318
1319
1320 /*
1321  * rename this floor
1322  */
1323 void rename_floor(void) {
1324         StrBuf *Buf;
1325
1326         Buf = NewStrBuf();
1327         FlushRoomlist();
1328
1329         serv_printf("EFLR %d|%s", ibstr("floornum"), bstr("floorname"));
1330         StrBuf_ServGetln(Buf);
1331
1332         StrBufCutLeft(Buf, 4);
1333         AppendImportantMessage (SKEY(Buf));
1334
1335         http_transmit_thing(ChrPtr(do_template("floors")), 0);
1336         FreeStrBuf(&Buf);
1337 }
1338
1339
1340
1341 void jsonRoomFlr(void) 
1342 {
1343         /* Send as our own (application/json) content type */
1344         hprintf("HTTP/1.1 200 OK\r\n");
1345         hprintf("Content-type: application/json; charset=utf-8\r\n");
1346         hprintf("Server: %s / %s\r\n", PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software));
1347         hprintf("Connection: close\r\n");
1348         hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n");
1349         begin_burst();
1350         DoTemplate(HKEY("json_roomflr"),NULL,&NoCtx);
1351         end_burst(); 
1352 }
1353
1354 void _FlushRoomList(wcsession *WCC)
1355 {
1356         free_march_list(WCC);
1357         DeleteHash(&WCC->Floors);
1358         DeleteHash(&WCC->Rooms);
1359         DeleteHash(&WCC->FloorsByName);
1360         FlushFolder(&WCC->CurRoom);
1361 }
1362
1363 void ReloadCurrentRoom(void)
1364 {
1365         wcsession *WCC = WC;
1366         StrBuf *CurRoom;
1367
1368         CurRoom = WCC->CurRoom.name;
1369         WCC->CurRoom.name = NULL;
1370         _FlushRoomList(WCC);
1371         gotoroom(CurRoom);
1372         FreeStrBuf(&CurRoom);
1373 }
1374
1375 void FlushRoomlist(void)
1376 {
1377         wcsession *WCC = WC;
1378         _FlushRoomList(WCC);
1379 }
1380
1381
1382 void 
1383 InitModule_ROOMOPS
1384 (void)
1385 {
1386         RegisterPreference("roomlistview",
1387                            _("Room list view"),
1388                            PRF_STRING,
1389                            NULL);
1390         RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO, NULL);
1391
1392         WebcitAddUrlHandler(HKEY("json_roomflr"), "", 0, jsonRoomFlr, 0);
1393
1394         WebcitAddUrlHandler(HKEY("delete_floor"), "", 0, delete_floor, 0);
1395         WebcitAddUrlHandler(HKEY("rename_floor"), "", 0, rename_floor, 0);
1396         WebcitAddUrlHandler(HKEY("create_floor"), "", 0, create_floor, 0);
1397
1398         WebcitAddUrlHandler(HKEY("knrooms"), "", 0, knrooms, ANONYMOUS);
1399         WebcitAddUrlHandler(HKEY("dotgoto"), "", 0, dotgoto, NEED_URL);
1400         WebcitAddUrlHandler(HKEY("dotskip"), "", 0, dotskip, NEED_URL);
1401
1402         WebcitAddUrlHandler(HKEY("goto_private"), "", 0, goto_private, NEED_URL);
1403         WebcitAddUrlHandler(HKEY("zap"), "", 0, zap, 0);
1404         WebcitAddUrlHandler(HKEY("entroom"), "", 0, entroom, 0);
1405         WebcitAddUrlHandler(HKEY("do_invt_kick"), "", 0, do_invt_kick, 0);
1406         
1407         WebcitAddUrlHandler(HKEY("netedit"), "", 0, netedit, 0);
1408         WebcitAddUrlHandler(HKEY("editroom"), "", 0, editroom, 0);
1409         WebcitAddUrlHandler(HKEY("delete_room"), "", 0, delete_room, 0);
1410         WebcitAddUrlHandler(HKEY("set_room_policy"), "", 0, set_room_policy, 0);
1411         WebcitAddUrlHandler(HKEY("changeview"), "", 0, change_view, 0);
1412         WebcitAddUrlHandler(HKEY("toggle_self_service"), "", 0, toggle_self_service, 0);
1413
1414
1415         REGISTERTokenParamDefine(QR_PERMANENT);
1416         REGISTERTokenParamDefine(QR_INUSE);
1417         REGISTERTokenParamDefine(QR_PRIVATE);
1418         REGISTERTokenParamDefine(QR_PASSWORDED);
1419         REGISTERTokenParamDefine(QR_GUESSNAME);
1420         REGISTERTokenParamDefine(QR_DIRECTORY);
1421         REGISTERTokenParamDefine(QR_UPLOAD);
1422         REGISTERTokenParamDefine(QR_DOWNLOAD);
1423         REGISTERTokenParamDefine(QR_VISDIR);
1424         REGISTERTokenParamDefine(QR_ANONONLY);
1425         REGISTERTokenParamDefine(QR_ANONOPT);
1426         REGISTERTokenParamDefine(QR_NETWORK);
1427         REGISTERTokenParamDefine(QR_PREFONLY);
1428         REGISTERTokenParamDefine(QR_READONLY);
1429         REGISTERTokenParamDefine(QR_MAILBOX);
1430         REGISTERTokenParamDefine(QR2_SYSTEM);
1431         REGISTERTokenParamDefine(QR2_SELFLIST);
1432         REGISTERTokenParamDefine(QR2_COLLABDEL);
1433         REGISTERTokenParamDefine(QR2_SUBJECTREQ);
1434         REGISTERTokenParamDefine(QR2_SMTP_PUBLIC);
1435         REGISTERTokenParamDefine(QR2_MODERATED);
1436         REGISTERTokenParamDefine(QR2_NOUPLMSG);
1437
1438         REGISTERTokenParamDefine(UA_KNOWN);
1439         REGISTERTokenParamDefine(UA_GOTOALLOWED);
1440         REGISTERTokenParamDefine(UA_HASNEWMSGS);
1441         REGISTERTokenParamDefine(UA_ZAPPED);
1442         REGISTERTokenParamDefine(UA_POSTALLOWED);
1443         REGISTERTokenParamDefine(UA_ADMINALLOWED);
1444         REGISTERTokenParamDefine(UA_DELETEALLOWED);
1445         REGISTERTokenParamDefine(UA_REPLYALLOWED);
1446         REGISTERTokenParamDefine(UA_ISTRASH);
1447
1448         REGISTERTokenParamDefine(US_NEEDVALID);
1449         REGISTERTokenParamDefine(US_PERM);
1450         REGISTERTokenParamDefine(US_LASTOLD);
1451         REGISTERTokenParamDefine(US_EXPERT);
1452         REGISTERTokenParamDefine(US_UNLISTED);
1453         REGISTERTokenParamDefine(US_NOPROMPT);
1454         REGISTERTokenParamDefine(US_PROMPTCTL);
1455         REGISTERTokenParamDefine(US_DISAPPEAR);
1456         REGISTERTokenParamDefine(US_REGIS);
1457         REGISTERTokenParamDefine(US_PAGINATOR);
1458         REGISTERTokenParamDefine(US_INTERNET);
1459         REGISTERTokenParamDefine(US_FLOORS);
1460         REGISTERTokenParamDefine(US_COLOR);
1461         REGISTERTokenParamDefine(US_USER_SET);
1462
1463         REGISTERTokenParamDefine(VIEW_BBS);
1464         REGISTERTokenParamDefine(VIEW_MAILBOX); 
1465         REGISTERTokenParamDefine(VIEW_ADDRESSBOOK);
1466         REGISTERTokenParamDefine(VIEW_CALENDAR);        
1467         REGISTERTokenParamDefine(VIEW_TASKS);   
1468         REGISTERTokenParamDefine(VIEW_NOTES);           
1469         REGISTERTokenParamDefine(VIEW_WIKI);            
1470         REGISTERTokenParamDefine(VIEW_CALBRIEF);
1471         REGISTERTokenParamDefine(VIEW_JOURNAL);
1472         REGISTERTokenParamDefine(VIEW_BLOG);
1473         REGISTERTokenParamDefine(VIEW_QUEUE);
1474         REGISTERTokenParamDefine(VIEW_WIKIMD);          
1475
1476         /* GNET types: */
1477         /* server internal, we need to know but ignore them. */
1478         REGISTERTokenParamDefine(subpending);
1479         REGISTERTokenParamDefine(unsubpending);
1480         REGISTERTokenParamDefine(lastsent);
1481
1482         REGISTERTokenParamDefine(ignet_push_share);
1483         { /* these are the parts of an IGNET push config */
1484                 REGISTERTokenParamDefine(GNET_IGNET_NODE);
1485                 REGISTERTokenParamDefine(GNET_IGNET_ROOM);
1486         }
1487         REGISTERTokenParamDefine(listrecp);
1488         REGISTERTokenParamDefine(digestrecp);
1489         REGISTERTokenParamDefine(pop3client);
1490         { /* These are the parts of a pop3 client line... */
1491                 REGISTERTokenParamDefine(GNET_POP3_HOST);
1492                 REGISTERTokenParamDefine(GNET_POP3_USER);
1493                 REGISTERTokenParamDefine(GNET_POP3_DONT_DELETE_REMOTE);
1494                 REGISTERTokenParamDefine(GNET_POP3_INTERVAL);
1495         }
1496         REGISTERTokenParamDefine(rssclient);
1497         REGISTERTokenParamDefine(participate);
1498         REGISTERTokenParamDefine(roommailalias);
1499
1500
1501
1502 }
1503
1504
1505 void 
1506 SessionDestroyModule_ROOMOPS
1507 (wcsession *sess)
1508 {
1509         _FlushRoomList (sess);
1510 }
1511