fe7183db1f28b3ecbfbb78c05dab6b09c80ff471
[citadel.git] / webcit / roomlist.c
1 /*
2  * $Id: roomlist.c 7751 2009-08-28 21:13:28Z dothebart $
3  * room listings and filters.
4  */
5
6 #include "webcit.h"
7 #include "webserver.h"
8
9
10 void DeleteFloor(void *vFloor)
11 {
12         floor *Floor;
13         Floor = (floor*) vFloor;
14         FreeStrBuf(&Floor->Name);
15         free(Floor);
16 }
17
18 int SortFloorsByNameOrder(const void *vfloor1, const void *vfloor2) 
19 {
20         floor *f1 = (floor*) GetSearchPayload(vfloor1);
21         floor *f2 = (floor*) GetSearchPayload(vfloor2);
22         
23         /* prefer My floor over alpabetical sort */
24         if (f1->ID == VIRTUAL_MY_FLOOR)
25                 return 1;
26         if (f2->ID == VIRTUAL_MY_FLOOR)
27                 return -1;
28
29         return strcmp(ChrPtr(f1->Name), ChrPtr(f2->Name));
30 }
31
32 HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) 
33 {
34         int Done = 0;
35         const char *Err;
36         StrBuf *Buf;
37         HashList *floors;
38         HashPos *it;
39         floor *Floor;
40         void *vFloor;
41         const char *Pos;
42         int i;
43         wcsession *WCC = WC;
44         const char *HashKey;
45         long HKLen;
46
47
48         if (WCC->Floors != NULL)
49                 return WCC->Floors;
50         WCC->Floors = floors = NewHash(1, Flathash);
51         Buf = NewStrBuf();
52
53         Floor = malloc(sizeof(floor));
54         Floor->ID = VIRTUAL_MY_FLOOR;
55         Floor->Name = NewStrBufPlain(_("My Folders"), -1);
56         Floor->NRooms = 0;
57         
58         Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
59
60         serv_puts("LFLR"); /* get floors */
61         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */
62         if (GetServerStatus(Buf, NULL) == 1) 
63         {
64                 while(!Done && StrBuf_ServGetln(Buf))
65                         if ( (StrLength(Buf)==3) && 
66                              !strcmp(ChrPtr(Buf), "000")) 
67                         {
68                                 Done = 1;
69                         }
70                         else
71                         {
72                         
73                                 Pos = NULL;
74
75                                 Floor = malloc(sizeof(floor));
76                                 Floor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
77                                 Floor->Name = NewStrBufPlain(NULL, StrLength(Buf));
78                                 StrBufExtract_NextToken(Floor->Name, Buf, &Pos, '|');
79                                 Floor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
80
81                                 Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
82                         }
83         }
84         FreeStrBuf(&Buf);
85         
86         /* now lets pre-sort them alphabeticaly. */
87         i = 1;
88         SortByPayload(floors, SortFloorsByNameOrder);
89         it = GetNewHashPos(floors, 0);
90         while ( GetNextHashPos(floors, it, &HKLen, &HashKey, &vFloor)) 
91                 ((floor*) vFloor)->AlphaN = i++;
92         DeleteHashPos(&it);
93         SortByHashKeyStr(floors);
94
95         return floors;
96 }
97
98 void tmplput_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) 
99 {
100         floor *Floor = (floor *)(TP->Context);
101
102         StrBufAppendPrintf(Target, "%d", Floor->ID);
103 }
104
105 void tmplput_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) 
106 {
107         floor *Floor = (floor *)(TP->Context);
108
109         StrBufAppendTemplate(Target, TP, Floor->Name, 0);
110 }
111
112 void tmplput_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) 
113 {
114         floor *Floor = (floor *)(TP->Context);
115
116         StrBufAppendPrintf(Target, "%d", Floor->NRooms);
117 }
118 HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) 
119 {
120         wcsession *WCC = WC;
121
122         if (WCC->Floors == NULL)
123                 GetFloorListHash(Target, TP);
124         serv_puts("LKRA");
125         return GetRoomListHash(Target, TP);
126 }
127
128 void DeleteFolder(void *vFolder)
129 {
130         int i;
131         folder *room;
132         room = (folder*) vFolder;
133
134         FreeStrBuf(&room->name);
135
136         if (room->RoomNameParts != NULL)
137         {
138                 for (i=0; i < room->nRoomNameParts; i++)
139                         FreeStrBuf(&room->RoomNameParts[i]);
140                 free(room->RoomNameParts);
141         }
142         free(room);
143 }
144
145
146 HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) 
147 {
148         int Done = 0;
149         HashList *rooms;
150         folder *room;
151         StrBuf *Buf;
152         const char *Pos;
153         const char *Err;
154         void *vFloor;
155         wcsession *WCC = WC;
156         CompareFunc SortIt;
157         WCTemplputParams SubTP;
158
159         Buf = NewStrBuf();
160         rooms = NewHash(1, NULL);
161         StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err);
162         if (GetServerStatus(Buf, NULL) == 1) 
163         {
164                 while(!Done && StrBuf_ServGetln(Buf))
165                         if ( (StrLength(Buf)==3) && 
166                              !strcmp(ChrPtr(Buf), "000")) 
167                         {
168                                 Done = 1;
169                         }
170                         else
171                         {                               
172                                 Pos = NULL;
173                                 room = (folder*) malloc (sizeof(folder));
174                                 memset(room, 0, sizeof(folder));
175
176                                 /* Load the base data from the server reply */
177                                 room->name = NewStrBufPlain(NULL, StrLength(Buf));
178                                 StrBufExtract_NextToken(room->name, Buf, &Pos, '|');
179
180                                 room->QRFlags = StrBufExtractNext_long(Buf, &Pos, '|');
181                                 room->floorid = StrBufExtractNext_int(Buf, &Pos, '|');
182                                 room->listorder = StrBufExtractNext_long(Buf, &Pos, '|');
183                                 room->QRFlags2 = StrBufExtractNext_long(Buf, &Pos, '|');
184
185                                 room->RAFlags = StrBufExtractNext_long(Buf, &Pos, '|');
186
187 /*
188   ACWHUT?
189   room->ACL = NewStrBufPlain(NULL, StrLength(Buf));
190   StrBufExtract_NextToken(room->ACL, Buf, &Pos, '|');
191 */
192
193                                 room->view = StrBufExtractNext_long(Buf, &Pos, '|');
194                                 room->defview = StrBufExtractNext_long(Buf, &Pos, '|');
195                                 room->lastchange = StrBufExtractNext_long(Buf, &Pos, '|');
196
197                                 /* Evaluate the Server sent data for later use */
198                                 /* find out, whether we are in a sub-room */
199                                 room->nRoomNameParts = StrBufNum_tokens(room->name, '\\');
200                                 if (room->nRoomNameParts > 1)
201                                 {
202                                         int i;
203
204                                         Pos = NULL;
205                                         room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1));
206                                         memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1));
207                                         for (i=0; i < room->nRoomNameParts; i++)
208                                         {
209                                                 room->RoomNameParts[i] = NewStrBuf();
210                                                 StrBufExtract_NextToken(room->RoomNameParts[i],
211                                                                         room->name, &Pos, '\\');
212                                         }
213                                 }
214
215                                 /* Private mailboxes on the main floor get remapped to the personal folder */
216                                 if ((room->QRFlags & QR_MAILBOX) && 
217                                     (room->floorid == 0))
218                                 {
219                                         room->floorid = VIRTUAL_MY_FLOOR;
220                                         if ((room->nRoomNameParts == 1) && 
221                                             (StrLength(room->name) == 4) && 
222                                             (strcmp(ChrPtr(room->name), "Mail") == 0))
223                                         {
224                                                 room->is_inbox = 1;
225                                         }
226
227                                 }
228                                 /* get a pointer to the floor we're on: */
229                                 GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
230                                 room->Floor = (const floor*) vFloor;
231
232
233
234                                 /* now we know everything, remember it... */
235                                 Put(rooms, SKEY(room->name), room, DeleteFolder);
236                         }
237         }
238
239         SubTP.Filter.ContextType = CTX_ROOMS;
240         SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0);
241         if (SortIt != NULL)
242                 SortByPayload(rooms, SortIt);
243         else 
244                 SortByPayload(rooms, SortRoomsByListOrder);
245         FreeStrBuf(&Buf);
246         return rooms;
247 }
248
249 /** Unused function that orders rooms by the listorder flag */
250 int SortRoomsByListOrder(const void *room1, const void *room2) 
251 {
252         folder *r1 = (folder*) GetSearchPayload(room1);
253         folder *r2 = (folder*) GetSearchPayload(room2);
254   
255         if (r1->listorder == r2->listorder) return 0;
256         if (r1->listorder > r2->listorder) return 1;
257         return -1;
258 }
259
260 int CompareRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) 
261 {
262         folder *r1 = (folder*) GetSearchPayload(room1);
263         folder *r2 = (folder*) GetSearchPayload(room2);
264   
265         if ((r1->Floor == NULL)  ||
266             (r2->Floor == NULL))
267                 return 0;
268                 
269         /**
270          * are we on the same floor? else sort by floor.
271          */
272         if (r1->Floor != r2->Floor)
273         {
274                 /**
275                  * the private rooms are first in any case.
276                  */
277                 if (r1->Floor->ID == VIRTUAL_MY_FLOOR)
278                         return -1;
279                 if (r2->Floor->ID == VIRTUAL_MY_FLOOR)
280                         return 1;
281                 /**
282                  * else decide alpaheticaly by floorname
283                  */
284                 return (r1->Floor->AlphaN > r2->Floor->AlphaN)? 1 : -1;
285         }
286
287         /**
288          * if we have different levels of subdirectories, 
289          * we want the toplevel to be first, regardless of sort
290          * sequence.
291          */
292         if (((r1->nRoomNameParts > 1) || 
293             (r2->nRoomNameParts > 1)    )&&
294             (r1->nRoomNameParts != r2->nRoomNameParts))
295         {
296                 int i, ret;
297                 int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)?
298                         r2->nRoomNameParts : r1->nRoomNameParts;
299
300                 for (i=0; i < nparts; i++)
301                 {
302                         ret = strcmp (ChrPtr(r1->name), 
303                                       ChrPtr(r2->name));
304                         /**
305                          * Deltas in common parts? exit here.
306                          */
307                         if (ret != 0) 
308                                 return ret;
309                 }
310
311                 /**
312                  * who's a subdirectory of whom?
313                  */
314                 if (r1->nRoomNameParts > r2->nRoomNameParts)
315                         return 1;
316                 else
317                         return -1;
318
319         }
320
321         /**
322          * else just sort alphabeticaly.
323          */
324         return strcmp (ChrPtr(r1->name), 
325                        ChrPtr(r2->name));
326 }
327
328 int CompareRoomListByFloorRoomPrivFirstRev(const void *room1, const void *room2) 
329 {
330         folder *r1 = (folder*) GetSearchPayload(room1);
331         folder *r2 = (folder*) GetSearchPayload(room2);
332
333         if ((r1->Floor == NULL)  ||
334             (r2->Floor == NULL))
335                 return 0;
336
337         /**
338          * are we on the same floor? else sort by floor.
339          */
340         if (r2->Floor != r1->Floor)
341         {
342                 /**
343                  * the private rooms are first in any case.
344                  */
345                 if (r1->Floor->ID == VIRTUAL_MY_FLOOR)
346                         return -1;
347                 if (r2->Floor->ID == VIRTUAL_MY_FLOOR)
348                         return 1;
349                 /**
350                  * else decide alpaheticaly by floorname
351                  */
352
353                 return (r1->Floor->AlphaN < r2->Floor->AlphaN)? 1 : -1;
354         }
355
356         /**
357          * if we have different levels of subdirectories, 
358          * we want the toplevel to be first, regardless of sort
359          * sequence.
360          */
361         if (((r1->nRoomNameParts > 1) || 
362             (r2->nRoomNameParts > 1)    )&&
363             (r1->nRoomNameParts != r2->nRoomNameParts))
364         {
365                 int i, ret;
366                 int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)?
367                         r2->nRoomNameParts : r1->nRoomNameParts;
368
369                 for (i=0; i < nparts; i++)
370                 {
371                         /**
372                          * special cases if one room is top-level...
373                          */
374                         if (r2->nRoomNameParts == 1)
375                                 ret = strcmp (ChrPtr(r2->name), 
376                                               ChrPtr(r1->RoomNameParts[i]));
377                         else if (r1->nRoomNameParts == 1)
378                                 ret = strcmp (ChrPtr(r2->RoomNameParts[i]),
379                                               ChrPtr(r1->name));
380                         else 
381                                 ret = strcmp (ChrPtr(r2->RoomNameParts[i]), 
382                                               ChrPtr(r1->RoomNameParts[i]));
383                         /**
384                          * Deltas in common parts? exit here.
385                          */
386                         if (ret != 0) 
387                                 return ret;
388                 }
389
390                 /**
391                  * who's a subdirectory of whom?
392                  */
393                 if (r1->nRoomNameParts > r2->nRoomNameParts)
394                         return 1;
395                 else
396                         return -1;
397         }
398
399         return strcmp (ChrPtr(r2->name), 
400                        ChrPtr(r1->name));
401 }
402
403 int GroupchangeRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) 
404 {
405         folder *r1 = (folder*) room1;
406         folder *r2 = (folder*) room2;
407   
408
409         if ((r1->Floor == NULL)  ||
410             (r2->Floor == NULL))
411                 return 0;
412                 
413         if (r1->Floor == r2->Floor)
414                 return 0;
415         else 
416         {
417                 wcsession *WCC = WC;
418                 static int columns = 3;
419                 int boxes_per_column = 0;
420                 int nf;
421
422                 nf = GetCount(WCC->Floors);
423                 while (nf % columns != 0) ++nf;
424                 boxes_per_column = (nf / columns);
425                 if (boxes_per_column < 1)
426                         boxes_per_column = 1;
427                 if (r1->Floor->AlphaN % boxes_per_column == 0)
428                         return 2;
429                 else 
430                         return 1;
431         }
432 }
433
434
435
436
437
438
439 void tmplput_ROOM_NAME(StrBuf *Target, WCTemplputParams *TP) 
440 {
441         folder *Folder = (folder *)(TP->Context);
442
443         StrBufAppendTemplate(Target, TP, Folder->name, 0);
444 }
445 void tmplput_ROOM_BASENAME(StrBuf *Target, WCTemplputParams *TP) 
446 {
447         folder *room = (folder *)(TP->Context);
448
449         if (room->nRoomNameParts > 1)
450                 StrBufAppendTemplate(Target, TP, 
451                                       room->RoomNameParts[room->nRoomNameParts - 1], 0);
452         else 
453                 StrBufAppendTemplate(Target, TP, room->name, 0);
454 }
455 void tmplput_ROOM_LEVEL_N_TIMES(StrBuf *Target, WCTemplputParams *TP) 
456 {
457         folder *room = (folder *)(TP->Context);
458         int i;
459         const char *AppendMe;
460         long AppendMeLen;
461
462
463         if (room->nRoomNameParts > 1)
464         {
465                 GetTemplateTokenString(Target, TP, 0, &AppendMe, &AppendMeLen);
466                 for (i = 0; i < room->nRoomNameParts; i++)
467                         StrBufAppendBufPlain(Target, AppendMe, AppendMeLen, 0);
468         }
469 }
470
471 void tmplput_ROOM_ACL(StrBuf *Target, WCTemplputParams *TP) 
472 {
473         folder *Folder = (folder *)(TP->Context);
474
475         StrBufAppendPrintf(Target, "%ld", Folder->RAFlags, 0);
476 }
477
478
479 void tmplput_ROOM_QRFLAGS(StrBuf *Target, WCTemplputParams *TP) 
480 {
481         folder *Folder = (folder *)(TP->Context);
482         StrBufAppendPrintf(Target, "%d", Folder->QRFlags);
483 }
484
485 void tmplput_ROOM_RAFLAGS(StrBuf *Target, WCTemplputParams *TP) 
486 {
487         folder *Folder = (folder *)(TP->Context);
488         StrBufAppendPrintf(Target, "%d", Folder->RAFlags);
489 }
490
491
492 void tmplput_ROOM_FLOORID(StrBuf *Target, WCTemplputParams *TP) 
493 {
494         folder *Folder = (folder *)(TP->Context);
495         StrBufAppendPrintf(Target, "%d", Folder->floorid);
496 }
497
498 void tmplput_ROOM_LISTORDER(StrBuf *Target, WCTemplputParams *TP) 
499 {
500         folder *Folder = (folder *)(TP->Context);
501         StrBufAppendPrintf(Target, "%d", Folder->listorder);
502 }
503 void tmplput_ROOM_VIEW(StrBuf *Target, WCTemplputParams *TP) 
504 {
505         folder *Folder = (folder *)(TP->Context);
506         StrBufAppendPrintf(Target, "%d", Folder->view);
507 }
508 void tmplput_ROOM_DEFVIEW(StrBuf *Target, WCTemplputParams *TP) 
509 {
510         folder *Folder = (folder *)(TP->Context);
511         StrBufAppendPrintf(Target, "%d", Folder->defview);
512 }
513 void tmplput_ROOM_LASTCHANGE(StrBuf *Target, WCTemplputParams *TP) 
514 {
515         folder *Folder = (folder *)(TP->Context);
516         StrBufAppendPrintf(Target, "%d", Folder->lastchange);
517 }
518 void tmplput_ROOM_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) 
519 {
520         folder *Folder = (folder *)(TP->Context);
521         const floor *Floor = Folder->Floor;
522
523         if (Floor == NULL)
524                 return;
525
526         StrBufAppendPrintf(Target, "%d", Floor->ID);
527 }
528
529 void tmplput_ROOM_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) 
530 {
531         folder *Folder = (folder *)(TP->Context);
532         const floor *Floor = Folder->Floor;
533
534         if (Floor == NULL)
535                 return;
536
537         StrBufAppendTemplate(Target, TP, Floor->Name, 0);
538 }
539
540 void tmplput_ROOM_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) 
541 {
542         folder *Folder = (folder *)(TP->Context);
543         const floor *Floor = Folder->Floor;
544
545         if (Floor == NULL)
546                 return;
547         StrBufAppendPrintf(Target, "%d", Floor->NRooms);
548 }
549
550
551
552 int ConditionalRoomHas_UA_KNOWN(StrBuf *Target, WCTemplputParams *TP)
553 {
554         folder *Folder = (folder *)(TP->Context);
555         return (Folder->RAFlags & UA_KNOWN) != 0;
556 }
557
558 int ConditionalRoomHas_UA_GOTOALLOWED(StrBuf *Target, WCTemplputParams *TP)
559 {
560         folder *Folder = (folder *)(TP->Context);
561         return (Folder->RAFlags & UA_GOTOALLOWED) != 0;
562 }
563
564 int ConditionalRoomHas_UA_HASNEWMSGS(StrBuf *Target, WCTemplputParams *TP)
565 {
566         folder *Folder = (folder *)(TP->Context);
567         return (Folder->RAFlags & UA_HASNEWMSGS) != 0;
568 }
569
570 int ConditionalRoomHas_UA_ZAPPED(StrBuf *Target, WCTemplputParams *TP)
571 {
572         folder *Folder = (folder *)(TP->Context);
573         return (Folder->RAFlags & UA_ZAPPED) != 0;
574 }
575
576 int ConditionalRoomHas_UA_POSTALLOWED(StrBuf *Target, WCTemplputParams *TP)
577 {
578         folder *Folder = (folder *)(TP->Context);
579         return (Folder->RAFlags & UA_POSTALLOWED) != 0;
580 }
581
582 int ConditionalRoomHas_UA_ADMINALLOWED(StrBuf *Target, WCTemplputParams *TP)
583 {
584         folder *Folder = (folder *)(TP->Context);
585         return (Folder->RAFlags & UA_ADMINALLOWED) != 0;
586 }
587
588 int ConditionalRoomHas_UA_DELETEALLOWED(StrBuf *Target, WCTemplputParams *TP)
589 {
590         folder *Folder = (folder *)(TP->Context);
591         return (Folder->RAFlags & UA_DELETEALLOWED) != 0;
592 }
593
594
595 int ConditionalRoomIsInbox(StrBuf *Target, WCTemplputParams *TP)
596 {
597         folder *Folder = (folder *)(TP->Context);
598         return Folder->is_inbox;
599 }
600
601 void tmplput_ROOM_COLLECTIONTYPE(StrBuf *Target, WCTemplputParams *TP) 
602 {
603         folder *Folder = (folder *)(TP->Context);
604         
605         switch(Folder->view) {
606         case VIEW_CALENDAR:
607                 StrBufAppendBufPlain(Target, HKEY("vevent"), 0);
608                 break;
609         case VIEW_TASKS:
610                 StrBufAppendBufPlain(Target, HKEY("vtodo"), 0);
611                 break;
612         case VIEW_ADDRESSBOOK:
613                 StrBufAppendBufPlain(Target, HKEY("vcard"), 0);
614                 break;
615         case VIEW_NOTES:
616                 StrBufAppendBufPlain(Target, HKEY("vnotes"), 0);
617                 break;
618         case VIEW_JOURNAL:
619                 StrBufAppendBufPlain(Target, HKEY("vjournal"), 0);
620                 break;
621         }
622 }
623
624
625
626
627 int ConditionalRoomHasGroupdavContent(StrBuf *Target, WCTemplputParams *TP)
628 {
629         folder *Folder = (folder *)(TP->Context);
630
631         return ((Folder->view == VIEW_CALENDAR) || 
632                 (Folder->view == VIEW_TASKS) || 
633                 (Folder->view == VIEW_ADDRESSBOOK) ||
634                 (Folder->view == VIEW_NOTES) ||
635                 (Folder->view == VIEW_JOURNAL) );
636 }
637
638
639
640 int ConditionalFloorIsRESTSubFloor(StrBuf *Target, WCTemplputParams *TP)
641 {
642         wcsession  *WCC = WC;
643
644         /** If we have dav_depth the client just wants the _current_ room without subfloors */
645         if (WCC->Hdr->HR.dav_depth == 0)
646                 return 0;
647             
648         return 1;
649 }
650
651
652 int ConditionalRoomIsRESTSubRoom(StrBuf *Target, WCTemplputParams *TP)
653 {
654         wcsession  *WCC = WC;
655         folder     *Folder = (folder *)(TP->Context);
656         HashPos    *it;
657         StrBuf     * Dir;
658         void       *vDir;
659         long        len;
660         const char *Key;
661         int i;
662
663
664
665         if (Folder->Floor != WCC->CurrentFloor)
666                 return 0;
667
668         if (GetCount(WCC->Directory) != Folder->nRoomNameParts)
669                 return 0;
670
671         it = GetNewHashPos(WCC->Directory, 0);
672         for (i = 0; i < Folder->nRoomNameParts; i++)
673         {
674                 if (!GetNextHashPos(WCC->Directory, it, &len, &Key, &vDir) ||
675                     (vDir == NULL))
676                 {
677                         DeleteHashPos(&it);
678                         return 0;
679                 }
680                 Dir = (StrBuf*) vDir;
681                 if (strcmp(ChrPtr(Folder->RoomNameParts[i]), 
682                            ChrPtr(Dir)) != 0)
683                 {
684                         DeleteHashPos(&it);
685                         return 0;
686                 }
687         }
688         DeleteHashPos(&it);
689
690         /** If we have dav_depth the client just wants the _current_ room without subfloors */
691         if ((WCC->Hdr->HR.dav_depth == 0) &&
692             (i != Folder->nRoomNameParts))
693                 return 0;
694
695         return 1;
696 }
697
698
699 void jsonRoomFlr(void) 
700 {
701         /* Send as our own (application/json) content type */
702         hprintf("HTTP/1.1 200 OK\r\n");
703         hprintf("Content-type: application/json; charset=utf-8\r\n");
704         hprintf("Server: %s / %s\r\n", PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software));
705         hprintf("Connection: close\r\n");
706         hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n");
707         begin_burst();
708         DoTemplate(HKEY("json_roomflr"),NULL,&NoCtx);
709         end_burst(); 
710 }
711
712 void 
713 SessionDetachModule_ROOMLIST
714 (wcsession *sess)
715 {
716         DeleteHash(&sess->Floors);
717 }
718
719
720 void 
721 InitModule_ROOMLIST
722 (void)
723 {
724         WebcitAddUrlHandler(HKEY("json_roomflr"), "", 0, jsonRoomFlr, 0);
725
726
727         RegisterNamespace("FLOOR:ID", 0, 0, tmplput_FLOOR_ID, NULL, CTX_FLOORS);
728         RegisterNamespace("FLOOR:NAME", 0, 1, tmplput_FLOOR_NAME, NULL, CTX_FLOORS);
729         RegisterNamespace("FLOOR:NROOMS", 0, 0, tmplput_FLOOR_NROOMS, NULL, CTX_FLOORS);
730         RegisterConditional(HKEY("COND:ROOM:REST:ISSUBFLOOR"), 0, ConditionalFloorIsRESTSubFloor, CTX_FLOORS);
731
732         RegisterIterator("LFLR", 0, NULL, GetFloorListHash, NULL, NULL, CTX_FLOORS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
733
734         RegisterIterator("LKRA", 0, NULL, GetRoomListHashLKRA, NULL, DeleteHash, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
735
736         RegisterNamespace("ROOM:INFO:FLOORID", 0, 1, tmplput_ROOM_FLOORID, NULL, CTX_ROOMS);
737         RegisterNamespace("ROOM:INFO:NAME", 0, 1, tmplput_ROOM_NAME, NULL, CTX_ROOMS);
738         RegisterNamespace("ROOM:INFO:PRINT_NAME", 0, 1, tmplput_ROOM_NAME, NULL, CTX_ROOMS);/// TODO!
739         RegisterNamespace("ROOM:INFO:BASENAME", 0, 1, tmplput_ROOM_BASENAME, NULL, CTX_ROOMS);
740         RegisterNamespace("ROOM:INFO:LEVELNTIMES", 1, 2, tmplput_ROOM_LEVEL_N_TIMES, NULL, CTX_ROOMS);
741
742         RegisterNamespace("ROOM:INFO:ACL", 0, 1, tmplput_ROOM_ACL, NULL, CTX_ROOMS);
743         RegisterNamespace("ROOM:INFO:QRFLAGS", 0, 1, tmplput_ROOM_QRFLAGS, NULL, CTX_ROOMS);
744         RegisterNamespace("ROOM:INFO:RAFLAGS", 0, 1, tmplput_ROOM_RAFLAGS, NULL, CTX_ROOMS);
745         RegisterNamespace("ROOM:INFO:LISTORDER", 0, 1, tmplput_ROOM_LISTORDER, NULL, CTX_ROOMS);
746         RegisterNamespace("ROOM:INFO:VIEW", 0, 1, tmplput_ROOM_VIEW, NULL, CTX_ROOMS);
747         RegisterNamespace("ROOM:INFO:DEFVIEW", 0, 1, tmplput_ROOM_DEFVIEW, NULL, CTX_ROOMS);
748         RegisterNamespace("ROOM:INFO:LASTCHANGE", 0, 1, tmplput_ROOM_LASTCHANGE, NULL, CTX_ROOMS);
749         RegisterNamespace("ROOM:INFO:COLLECTIONTYPE", 0, 1, tmplput_ROOM_COLLECTIONTYPE, NULL, CTX_ROOMS);
750         RegisterNamespace("ROOM:INFO:FLOOR:ID", 0, 0, tmplput_ROOM_FLOOR_ID, NULL, CTX_ROOMS);
751         RegisterNamespace("ROOM:INFO:FLOOR:NAME", 0, 1, tmplput_ROOM_FLOOR_NAME, NULL, CTX_ROOMS);
752         RegisterNamespace("ROOM:INFO:FLOOR:NROOMS", 0, 0, tmplput_ROOM_FLOOR_NROOMS, NULL, CTX_ROOMS);
753
754         RegisterConditional(HKEY("COND:ROOM:REST:ISSUBROOM"), 0, ConditionalRoomIsRESTSubRoom, CTX_ROOMS);
755
756         RegisterConditional(HKEY("COND:ROOM:INFO:IS_INBOX"), 0, ConditionalRoomIsInbox, CTX_ROOMS);
757         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_KNOWN"), 0, ConditionalRoomHas_UA_KNOWN, CTX_ROOMS);
758         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_GOTOALLOWED"), 0, ConditionalRoomHas_UA_GOTOALLOWED, CTX_ROOMS);
759         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_HASNEWMSGS"), 0, ConditionalRoomHas_UA_HASNEWMSGS, CTX_ROOMS);
760         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_ZAPPED"), 0, ConditionalRoomHas_UA_ZAPPED, CTX_ROOMS);
761         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_POSTALLOWED"), 0, ConditionalRoomHas_UA_POSTALLOWED, CTX_ROOMS);
762         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_ADMINALLOWED"), 0, ConditionalRoomHas_UA_ADMINALLOWED, CTX_ROOMS);
763         RegisterConditional(HKEY("COND:ROOM:FLAGS:UA_DELETEALLOWED"), 0, ConditionalRoomHas_UA_DELETEALLOWED, CTX_ROOMS);
764         RegisterConditional(HKEY("COND:ROOM:GROUPDAV_CONTENT"), 0, ConditionalRoomHasGroupdavContent, CTX_ROOMS);
765
766
767
768         RegisterSortFunc(HKEY("byfloorroom"),
769                          NULL, 0,
770                          CompareRoomListByFloorRoomPrivFirst,
771                          CompareRoomListByFloorRoomPrivFirstRev,
772                          GroupchangeRoomListByFloorRoomPrivFirst,
773                          CTX_ROOMS);
774
775 }