Back to index

webcit  8.12-dfsg
roomlist.c
Go to the documentation of this file.
00001 /*
00002  * room listings and filters.
00003  */
00004 
00005 #include "webcit.h"
00006 #include "webserver.h"
00007 
00008 HashList *GetWhoKnowsHash(StrBuf *Target, WCTemplputParams *TP)
00009 {
00010        StrBuf *Line;
00011        StrBuf *Token;
00012        long State;
00013        HashList *Whok = NULL;
00014        int Done = 0;
00015        int n;
00016 
00017        serv_puts("WHOK");
00018        Line = NewStrBuf();
00019        StrBuf_ServGetln(Line);
00020        if (GetServerStatus(Line, &State) == 1) 
00021        {
00022               Whok = NewHash(1, Flathash);
00023               while(!Done && (StrBuf_ServGetln(Line) >= 0) )
00024                      if ( (StrLength(Line)==3) && 
00025                           !strcmp(ChrPtr(Line), "000")) 
00026                      {
00027                             Done = 1;
00028                      }
00029                      else
00030                      {
00031                      
00032                             const char *Pos = NULL;
00033                             Token = NewStrBufPlain (NULL, StrLength(Line));
00034                             StrBufExtract_NextToken(Token, Line, &Pos, '|');
00035 
00036                             Put(Whok, 
00037                                 IKEY(n),
00038                                 Token, 
00039                                 HFreeStrBuf);
00040                             n++;
00041                      }
00042        }
00043        else if (State == 550)
00044               AppendImportantMessage(_("Higher access is required to access this function."), -1);
00045 
00046 
00047        FreeStrBuf(&Line);
00048        return Whok;
00049 }
00050 
00051 
00052 void DeleteFloor(void *vFloor)
00053 {
00054        Floor *pFloor;
00055        pFloor = (Floor*) vFloor;
00056        FreeStrBuf(&pFloor->Name);
00057        free(pFloor);
00058 }
00059 
00060 int SortFloorsByNameOrder(const void *vfloor1, const void *vfloor2) 
00061 {
00062        Floor *f1 = (Floor*) GetSearchPayload(vfloor1);
00063        Floor *f2 = (Floor*) GetSearchPayload(vfloor2);
00064        
00065        /* prefer My floor over alpabetical sort */
00066        if (f1->ID == VIRTUAL_MY_FLOOR)
00067               return 1;
00068        if (f2->ID == VIRTUAL_MY_FLOOR)
00069               return -1;
00070 
00071        return strcmp(ChrPtr(f1->Name), ChrPtr(f2->Name));
00072 }
00073 
00074 HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) 
00075 {
00076        int Done = 0;
00077        const char *Err;
00078        StrBuf *Buf;
00079        HashList *floors;
00080        HashList *floorsbyname;
00081        HashPos *it;
00082        Floor *pFloor;
00083        void *vFloor;
00084        const char *Pos;
00085        int i;
00086        wcsession *WCC = WC;
00087        const char *HashKey;
00088        long HKLen;
00089 
00090 
00091        if (WCC->Floors != NULL)
00092               return WCC->Floors;
00093        WCC->Floors = floors = NewHash(1, Flathash);
00094        WCC->FloorsByName = floorsbyname = NewHash(1, NULL);
00095        Buf = NewStrBuf();
00096 
00097        pFloor = (Floor*) malloc(sizeof(Floor));
00098        pFloor->ID = VIRTUAL_MY_FLOOR;
00099        pFloor->Name = NewStrBufPlain(_("My Folders"), -1);
00100        pFloor->NRooms = 0;
00101        
00102        Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
00103        Put(floorsbyname, SKEY(pFloor->Name), pFloor, reference_free_handler);
00104 
00105        serv_puts("LFLR"); /* get floors */
00106        StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */
00107        if (GetServerStatus(Buf, NULL) == 1) 
00108        {
00109               while(!Done && StrBuf_ServGetln(Buf) >= 0)
00110                      if ( (StrLength(Buf)==3) && 
00111                           !strcmp(ChrPtr(Buf), "000")) 
00112                      {
00113                             Done = 1;
00114                      }
00115                      else
00116                      {
00117                      
00118                             Pos = NULL;
00119 
00120                             pFloor = (Floor*) malloc(sizeof(Floor));
00121                             pFloor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
00122                             pFloor->Name = NewStrBufPlain(NULL, StrLength(Buf));
00123                             StrBufExtract_NextToken(pFloor->Name, Buf, &Pos, '|');
00124                             pFloor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
00125 
00126                             Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
00127                             Put(floorsbyname, SKEY(pFloor->Name), pFloor, reference_free_handler);
00128                      }
00129        }
00130        FreeStrBuf(&Buf);
00131        
00132        /* now lets pre-sort them alphabeticaly. */
00133        i = 1;
00134        SortByPayload(floors, SortFloorsByNameOrder);
00135        it = GetNewHashPos(floors, 0);
00136        while (       GetNextHashPos(floors, it, &HKLen, &HashKey, &vFloor)) 
00137               ((Floor*) vFloor)->AlphaN = i++;
00138        DeleteHashPos(&it);
00139        SortByHashKeyStr(floors);
00140 
00141        return floors;
00142 }
00143 
00144 HashList *GetZappedRoomListHash(StrBuf *Target, WCTemplputParams *TP) 
00145 {
00146        wcsession *WCC = WC;
00147 
00148        if (WCC->Floors == NULL)
00149               GetFloorListHash(Target, TP);
00150        serv_puts("LZRM -1");
00151        return GetRoomListHash(Target, TP);
00152 }
00153 HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) 
00154 {
00155        wcsession *WCC = WC;
00156 
00157        if (WCC->Floors == NULL)
00158               GetFloorListHash(Target, TP);
00159        if (WCC->Rooms == NULL) 
00160        {
00161               serv_puts("LKRA");
00162               WCC->Rooms =  GetRoomListHash(Target, TP);
00163        }
00164        return WCC->Rooms;
00165 }
00166 
00167 HashList *GetRoomListHashLPRM(StrBuf *Target, WCTemplputParams *TP) 
00168 {
00169        serv_puts("LPRM");
00170        return GetRoomListHash(Target, TP);
00171 }
00172 
00173 
00174 void FlushIgnetCfgs(folder *room)
00175 {
00176        int i;
00177        if (room->IgnetCfgs[maxRoomNetCfg] == (HashList*) StrBufNOTNULL)
00178        {
00179               for (i = ignet_push_share; i < maxRoomNetCfg; i++)
00180                      DeleteHash(&room->IgnetCfgs[i]);
00181        }
00182        memset(&room->IgnetCfgs, 0, sizeof(HashList *) * (maxRoomNetCfg + 1));
00183 
00184 }
00185 
00186 void FlushFolder(folder *room)
00187 {
00188        int i;
00189 
00190        FreeStrBuf(&room->XAPass);
00191        FreeStrBuf(&room->Directory);
00192        FreeStrBuf(&room->RoomAide);
00193        FreeStrBuf(&room->XInfoText);
00194        room->XHaveInfoTextLoaded = 0;
00195 
00196        FreeStrBuf(&room->name);
00197 
00198        FlushIgnetCfgs(room);
00199 
00200        if (room->RoomNameParts != NULL)
00201        {
00202               for (i=0; i < room->nRoomNameParts; i++)
00203                      FreeStrBuf(&room->RoomNameParts[i]);
00204               free(room->RoomNameParts);
00205        }
00206        memset(room, 0, sizeof(folder));
00207 }
00208 
00209 void vDeleteFolder(void *vFolder)
00210 {
00211        folder *room;
00212 
00213        room = (folder*) vFolder;
00214        FlushFolder(room);
00215 
00216        free(room);
00217 }
00218 
00219 
00220 HashList *GetRoomListHash(StrBuf *Target, WCTemplputParams *TP) 
00221 {
00222        int Done = 0;
00223        HashList *rooms;
00224        folder *room;
00225        StrBuf *Buf;
00226        const char *Pos;
00227        void *vFloor;
00228        wcsession *WCC = WC;
00229        CompareFunc SortIt;
00230        WCTemplputParams SubTP;
00231 
00232        Buf = NewStrBuf();
00233        rooms = NewHash(1, NULL);
00234        StrBuf_ServGetln(Buf);
00235        if (GetServerStatus(Buf, NULL) == 1) 
00236        {
00237               while(!Done && (StrBuf_ServGetln(Buf) >= 0))
00238                      if ( (StrLength(Buf)==3) && 
00239                           !strcmp(ChrPtr(Buf), "000")) 
00240                      {
00241                             Done = 1;
00242                      }
00243                      else
00244                      {                           
00245                             Pos = NULL;
00246                             room = (folder*) malloc (sizeof(folder));
00247                             memset(room, 0, sizeof(folder));
00248 
00249                             /* Load the base data from the server reply */
00250                             room->name = NewStrBufPlain(NULL, StrLength(Buf));
00251                             StrBufExtract_NextToken(room->name, Buf, &Pos, '|');
00252 
00253                             room->QRFlags = StrBufExtractNext_long(Buf, &Pos, '|');
00254                             room->floorid = StrBufExtractNext_int(Buf, &Pos, '|');
00255                             room->Order = StrBufExtractNext_long(Buf, &Pos, '|');
00256                             room->QRFlags2 = StrBufExtractNext_long(Buf, &Pos, '|');
00257 
00258                             room->RAFlags = StrBufExtractNext_long(Buf, &Pos, '|');
00259 
00260 /*
00261   ACWHUT?
00262   room->ACL = NewStrBufPlain(NULL, StrLength(Buf));
00263   StrBufExtract_NextToken(room->ACL, Buf, &Pos, '|');
00264 */
00265 
00266                             room->view = StrBufExtractNext_long(Buf, &Pos, '|');
00267                             room->defview = StrBufExtractNext_long(Buf, &Pos, '|');
00268                             room->lastchange = StrBufExtractNext_long(Buf, &Pos, '|');
00269 
00270                             /* Evaluate the Server sent data for later use */
00271                             /* find out, whether we are in a sub-room */
00272                             room->nRoomNameParts = StrBufNum_tokens(room->name, '\\');
00273                             if (room->nRoomNameParts > 1)
00274                             {
00275                                    int i;
00276 
00277                                    Pos = NULL;
00278                                    room->RoomNameParts = malloc(sizeof(StrBuf*) * (room->nRoomNameParts + 1));
00279                                    memset(room->RoomNameParts, 0, sizeof(StrBuf*) * (room->nRoomNameParts + 1));
00280                                    for (i=0; i < room->nRoomNameParts; i++)
00281                                    {
00282                                           room->RoomNameParts[i] = NewStrBuf();
00283                                           StrBufExtract_NextToken(room->RoomNameParts[i],
00284                                                                room->name, &Pos, '\\');
00285                                    }
00286                             }
00287 
00288                             /* Private mailboxes on the main floor get remapped to the personal folder */
00289                             if ((room->QRFlags & QR_MAILBOX) && 
00290                                 (room->floorid == 0))
00291                             {
00292                                    room->floorid = VIRTUAL_MY_FLOOR;
00293                                    if ((room->nRoomNameParts == 1) && 
00294                                        (StrLength(room->name) == 4) && 
00295                                        (strcmp(ChrPtr(room->name), "Mail") == 0))
00296                                    {
00297                                           room->is_inbox = 1;
00298                                    }
00299 
00300                             }
00301                             /* get a pointer to the floor we're on: */
00302                             GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
00303                             room->Floor = (const Floor*) vFloor;
00304 
00305 
00306 
00307                             /* now we know everything, remember it... */
00308                             Put(rooms, SKEY(room->name), room, vDeleteFolder);
00309                      }
00310        }
00311 
00312        SubTP.Filter.ContextType = CTX_ROOMS;
00313        SortIt = RetrieveSort(&SubTP, NULL, 0, HKEY("fileunsorted"), 0);
00314        if (SortIt != NULL)
00315               SortByPayload(rooms, SortIt);
00316        else 
00317               SortByPayload(rooms, SortRoomsByListOrder);
00318        FreeStrBuf(&Buf);
00319        return rooms;
00320 }
00321 
00322 HashList *GetNetConfigHash(StrBuf *Target, WCTemplputParams *TP) 
00323 {
00324        wcsession *WCC = WC;
00325        StrBuf *Line;
00326        StrBuf *Token;
00327        StrBuf *Content;
00328        long WantThisOne;
00329        long PutTo;
00330        long State;
00331        
00332        WantThisOne = GetTemplateTokenNumber(Target, TP, 5, -1);
00333        if ((WantThisOne < 0) || (WantThisOne > maxRoomNetCfg))
00334               return NULL;
00335        if (WCC->CurRoom.IgnetCfgs[maxRoomNetCfg] == (HashList*) StrBufNOTNULL)
00336               return WCC->CurRoom.IgnetCfgs[WantThisOne];
00337 
00338        WCC->CurRoom.IgnetCfgs[maxRoomNetCfg] = (HashList*) StrBufNOTNULL;
00339        serv_puts("GNET");
00340        Line = NewStrBuf();
00341        Token = NewStrBuf();
00342        StrBuf_ServGetln(Line);
00343        if (GetServerStatus(Line, &State) == 1) 
00344        {
00345               const char *Pos = NULL;
00346               int Done = 0;
00347 
00348               while(!Done && (StrBuf_ServGetln(Line) >= 0))
00349                      if ( (StrLength(Line)==3) && 
00350                           !strcmp(ChrPtr(Line), "000"))
00351                      {
00352                             Done = 1;
00353                      }
00354                      else
00355                      {
00356                             StrBufExtract_NextToken(Token, Line, &Pos, '|');
00357                             PutTo = GetTokenDefine(SKEY(Token), -1);
00358                             if ((PutTo >= 0) && 
00359                                 (PutTo < maxRoomNetCfg) &&
00360                                 (Pos != StrBufNOTNULL))
00361                             {
00362                                    int n;
00363                                    HashList *SubH;
00364                                    
00365                                    if (WCC->CurRoom.IgnetCfgs[PutTo] == NULL)
00366                                    {
00367                                           n = 0;
00368                                           WCC->CurRoom.IgnetCfgs[PutTo] = NewHash(1, NULL);
00369                                    }
00370                                    else 
00371                                    {
00372                                           n = GetCount(WCC->CurRoom.IgnetCfgs[PutTo]);
00373                                    }
00374                                    SubH = NewHash(1, NULL);
00375                                    Put(WCC->CurRoom.IgnetCfgs[PutTo], 
00376                                        IKEY(n),
00377                                        SubH, 
00378                                        HDeleteHash);
00379                                    n = 1; /* #0 is the type... */
00380                                    while (Pos != StrBufNOTNULL) {
00381                                           Content = NewStrBuf();
00382                                           StrBufExtract_NextToken(Content, Line, &Pos, '|');
00383                                           Put(SubH, 
00384                                               IKEY(n),
00385                                               Content, 
00386                                               HFreeStrBuf);
00387                                           n++;
00388                                    }
00389                             }
00390                             Pos = NULL;
00391                      }
00392        }
00393        else if (State == 550)
00394               AppendImportantMessage(_("Higher access is required to access this function."), -1);
00395 
00396 
00397        return WCC->CurRoom.IgnetCfgs[WantThisOne];
00398 }
00399 
00401 int SortRoomsByListOrder(const void *room1, const void *room2) 
00402 {
00403        folder *r1 = (folder*) GetSearchPayload(room1);
00404        folder *r2 = (folder*) GetSearchPayload(room2);
00405   
00406        if (r1->Order == r2->Order) return 0;
00407        if (r1->Order > r2->Order) return 1;
00408        return -1;
00409 }
00410 
00411 int CompareRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) 
00412 {
00413        folder *r1 = (folder*) GetSearchPayload(room1);
00414        folder *r2 = (folder*) GetSearchPayload(room2);
00415   
00416        if ((r1->Floor == NULL)  ||
00417            (r2->Floor == NULL))
00418               return 0;
00419               
00423        if (r1->Floor != r2->Floor)
00424        {
00428               if (r1->Floor->ID == VIRTUAL_MY_FLOOR)
00429                      return -1;
00430               if (r2->Floor->ID == VIRTUAL_MY_FLOOR)
00431                      return 1;
00435               return (r1->Floor->AlphaN > r2->Floor->AlphaN)? 1 : -1;
00436        }
00437 
00443        if (((r1->nRoomNameParts > 1) || 
00444            (r2->nRoomNameParts > 1)    )&&
00445            (r1->nRoomNameParts != r2->nRoomNameParts))
00446        {
00447               int i, ret;
00448               int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)?
00449                      r2->nRoomNameParts : r1->nRoomNameParts;
00450 
00451               for (i=0; i < nparts; i++)
00452               {
00453                      ret = strcmp (ChrPtr(r1->name), 
00454                                   ChrPtr(r2->name));
00458                      if (ret != 0) 
00459                             return ret;
00460               }
00461 
00465               if (r1->nRoomNameParts > r2->nRoomNameParts)
00466                      return 1;
00467               else
00468                      return -1;
00469 
00470        }
00471 
00475        return strcmp (ChrPtr(r1->name), 
00476                      ChrPtr(r2->name));
00477 }
00478 
00479 int CompareRoomListByFloorRoomPrivFirstRev(const void *room1, const void *room2) 
00480 {
00481        folder *r1 = (folder*) GetSearchPayload(room1);
00482        folder *r2 = (folder*) GetSearchPayload(room2);
00483 
00484        if ((r1->Floor == NULL)  ||
00485            (r2->Floor == NULL))
00486               return 0;
00487 
00491        if (r2->Floor != r1->Floor)
00492        {
00496               if (r1->Floor->ID == VIRTUAL_MY_FLOOR)
00497                      return -1;
00498               if (r2->Floor->ID == VIRTUAL_MY_FLOOR)
00499                      return 1;
00504               return (r1->Floor->AlphaN < r2->Floor->AlphaN)? 1 : -1;
00505        }
00506 
00512        if (((r1->nRoomNameParts > 1) || 
00513            (r2->nRoomNameParts > 1)    )&&
00514            (r1->nRoomNameParts != r2->nRoomNameParts))
00515        {
00516               int i, ret;
00517               int nparts = (r1->nRoomNameParts > r2->nRoomNameParts)?
00518                      r2->nRoomNameParts : r1->nRoomNameParts;
00519 
00520               for (i=0; i < nparts; i++)
00521               {
00525                      if (r2->nRoomNameParts == 1)
00526                             ret = strcmp (ChrPtr(r2->name), 
00527                                          ChrPtr(r1->RoomNameParts[i]));
00528                      else if (r1->nRoomNameParts == 1)
00529                             ret = strcmp (ChrPtr(r2->RoomNameParts[i]),
00530                                          ChrPtr(r1->name));
00531                      else 
00532                             ret = strcmp (ChrPtr(r2->RoomNameParts[i]), 
00533                                          ChrPtr(r1->RoomNameParts[i]));
00537                      if (ret != 0) 
00538                             return ret;
00539               }
00540 
00544               if (r1->nRoomNameParts > r2->nRoomNameParts)
00545                      return 1;
00546               else
00547                      return -1;
00548        }
00549 
00550        return strcmp (ChrPtr(r2->name), 
00551                      ChrPtr(r1->name));
00552 }
00553 
00554 int GroupchangeRoomListByFloorRoomPrivFirst(const void *room1, const void *room2) 
00555 {
00556        folder *r1 = (folder*) room1;
00557        folder *r2 = (folder*) room2;
00558   
00559 
00560        if ((r1->Floor == NULL)  ||
00561            (r2->Floor == NULL))
00562               return 0;
00563               
00564        if (r1->Floor == r2->Floor)
00565               return 0;
00566        else 
00567        {
00568               wcsession *WCC = WC;
00569               static int columns = 3;
00570               int boxes_per_column = 0;
00571               int nf;
00572 
00573               nf = GetCount(WCC->Floors);
00574               while (nf % columns != 0) ++nf;
00575               boxes_per_column = (nf / columns);
00576               if (boxes_per_column < 1)
00577                      boxes_per_column = 1;
00578               if (r1->Floor->AlphaN % boxes_per_column == 0)
00579                      return 2;
00580               else 
00581                      return 1;
00582        }
00583 }
00584 
00585 
00586 int CompareRooms(const folder *room1, const folder *room2) 
00587 {
00588        if ((room1 == NULL) || (room2 == NULL))
00589               return -1;
00590        return CompareRoomListByFloorRoomPrivFirst(room1, room2);
00591 }
00592 
00593 int ConditionalRoomIsRESTSubRoom(StrBuf *Target, WCTemplputParams *TP)
00594 {
00595        wcsession  *WCC = WC;
00596        folder     *Folder = (folder *)CTX;
00597        HashPos    *it;
00598        StrBuf     * Dir;
00599        void       *vDir;
00600        long        len;
00601         const char *Key;
00602        int i, j, urlp;
00603        int delta;
00604 
00605 
00606        /* list only folders relative to the current floor... */
00607        if (Folder->Floor != WCC->CurrentFloor)
00608               return 0;
00609 
00610        urlp = GetCount(WCC->Directory);
00611        delta = Folder->nRoomNameParts - urlp + 1;
00612 
00613        syslog(0, "\n->%s: %d - %ld ", 
00614               ChrPtr(Folder->name), 
00615               urlp, 
00616               Folder->nRoomNameParts);
00617        /* list only the floors which are in relation to the dav_depth header */
00618        if (WCC->Hdr->HR.dav_depth != delta) {
00619               syslog(0, "1\n");
00620               return 0;
00621        }
00622 
00623 
00624        it = GetNewHashPos(WCC->Directory, 0);
00625        /* Fast forward the floorname we checked above... */
00626        GetNextHashPos(WCC->Directory, it, &len, &Key, &vDir);
00627 
00628        if (Folder->nRoomNameParts > 1) {         
00629               for (i = 0, j = 1; 
00630                    (i > Folder->nRoomNameParts) && (j > urlp); 
00631                    i++, j++)
00632               {
00633                      if (!GetNextHashPos(WCC->Directory, 
00634                                        it, &len, &Key, &vDir) ||
00635                          (vDir == NULL))
00636                      {
00637                             DeleteHashPos(&it);
00638 
00639                             syslog(0, "3\n");
00640                             return 0;
00641                      }
00642                      Dir = (StrBuf*) vDir;
00643                      if (strcmp(ChrPtr(Folder->RoomNameParts[i]), 
00644                                ChrPtr(Dir)) != 0)
00645                      {
00646                             DeleteHashPos(&it);
00647                             syslog(0, "4\n");
00648                             return 0;
00649                      }
00650               }
00651               DeleteHashPos(&it);
00652               return 1;
00653        }
00654        else {
00655               if (!GetNextHashPos(WCC->Directory, 
00656                                 it, &len, &Key, &vDir) ||
00657                   (vDir == NULL))
00658               {
00659                      DeleteHashPos(&it);
00660                      
00661                      syslog(0, "5\n");
00662                      return WCC->Hdr->HR.dav_depth == 1;
00663               }
00664               DeleteHashPos(&it);
00665               Dir = (StrBuf*) vDir;
00666               if (WCC->Hdr->HR.dav_depth == 0) {
00667                      return (strcmp(ChrPtr(Folder->name), 
00668                                    ChrPtr(Dir))
00669                             == 0);
00670 
00671               }
00672               return 0;
00673        }
00674 }
00675 
00676 
00677 void 
00678 InitModule_ROOMLIST
00679 (void)
00680 {
00681 
00682        RegisterIterator("ITERATE:THISROOM:WHO_KNOWS", 0, NULL, GetWhoKnowsHash, NULL, DeleteHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
00683        RegisterIterator("ITERATE:THISROOM:GNET", 1, NULL, GetNetConfigHash, NULL, NULL, CTX_STRBUFARR, CTX_NONE, IT_NOFLAG);
00684 
00685        RegisterIterator("LFLR", 0, NULL, GetFloorListHash, NULL, NULL, CTX_FLOORS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
00686        RegisterIterator("LKRA", 0, NULL, GetRoomListHashLKRA, NULL, NULL, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
00687        RegisterIterator("LZRM", 0, NULL, GetZappedRoomListHash, NULL, DeleteHash, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
00688        RegisterIterator("LPRM", 0, NULL, GetRoomListHashLPRM, NULL, DeleteHash, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE);
00689 
00690 
00691 
00692 
00693        RegisterConditional(HKEY("COND:ROOM:REST:ISSUBROOM"), 0, ConditionalRoomIsRESTSubRoom, CTX_ROOMS);
00694 
00695        RegisterSortFunc(HKEY("byfloorroom"),
00696                       NULL, 0,
00697                       CompareRoomListByFloorRoomPrivFirst,
00698                       CompareRoomListByFloorRoomPrivFirstRev,
00699                       GroupchangeRoomListByFloorRoomPrivFirst,
00700                       CTX_ROOMS);
00701 
00702 }