serv_rssclient.c: style update
[citadel.git] / webcit / preferences.c
diff --git a/webcit/preferences.c b/webcit/preferences.c
deleted file mode 100644 (file)
index ae381cc..0000000
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * Manage user preferences with a little help from the Citadel server.
- *
- * Copyright (c) 1996-2012 by the citadel.org team
- *
- * This program is open source software.  You can redistribute it and/or
- * modify it under the terms of the GNU General Public License, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "dav.h"
-
-HashList *PreferenceHooks;
-extern HashList *HandlerHash;
-
-typedef struct _PrefDef {
-       ePrefType eType;
-       StrBuf *Setting;
-       const char *PrefStr;
-       PrefEvalFunc OnLoad;
-       StrBuf *OnLoadName;
-} PrefDef;
-
-typedef struct _Preference {
-       PrefDef *Type;
-       ePrefType eFlatPrefType;
-
-       StrBuf *Key;
-       StrBuf *Val;
-
-       long lval;
-       long decoded;
-       StrBuf *DeQPed;
-} Preference;
-
-void DestroyPrefDef(void *vPrefDef)
-{
-       PrefDef *Prefdef = (PrefDef*) vPrefDef;
-       FreeStrBuf(&Prefdef->Setting);
-       FreeStrBuf(&Prefdef->OnLoadName);
-       free(Prefdef);
-}
-
-void DestroyPreference(void *vPref)
-{
-       Preference *Pref = (Preference*) vPref;
-       FreeStrBuf(&Pref->Key);
-       FreeStrBuf(&Pref->Val);
-       FreeStrBuf(&Pref->DeQPed);
-       free(Pref);
-
-}
-
-void _RegisterPreference(const char *Setting, long SettingLen, 
-                        const char *PrefStr, 
-                        ePrefType Type, 
-                        PrefEvalFunc OnLoad, 
-                        const char *OnLoadName)
-{
-       PrefDef *Newpref = (PrefDef*) malloc(sizeof(PrefDef));
-       Newpref->Setting = NewStrBufPlain(Setting, SettingLen);
-       Newpref->PrefStr = PrefStr;
-       Newpref->eType = Type;
-       Newpref->OnLoad = OnLoad;
-       if (Newpref->OnLoad != NULL) {
-               Newpref->OnLoadName = NewStrBufPlain(OnLoadName, -1);
-       }
-       else
-               Newpref->OnLoadName = NULL;
-       Put(PreferenceHooks, Setting, SettingLen, Newpref, DestroyPrefDef);
-}
-
-const char *PrefGetLocalStr(const char *Setting, long len)
-{
-       void *hash_value;
-       if (GetHash(PreferenceHooks, Setting, len, &hash_value) != 0) {
-               PrefDef *Newpref = (PrefDef*) hash_value;
-               return _(Newpref->PrefStr);
-
-       }
-       return "";
-}
-
-#ifdef DBG_PREFS_HASH
-inline const char *PrintPref(void *vPref)
-{
-       Preference *Pref = (Preference*) vPref;
-       if (Pref->DeQPed != NULL)
-               return ChrPtr(Pref->DeQPed);
-       else 
-               return ChrPtr(Pref->Val);
-}
-#endif
-
-void GetPrefTypes(HashList *List)
-{
-       HashPos *It;
-       long len;
-       const char *Key;
-       void *vSetting;
-       void *vPrefDef;
-       Preference *Pref;
-       PrefDef *PrefType;
-
-       It = GetNewHashPos(List, 0);
-       while (GetNextHashPos(List, It, &len, &Key, &vSetting)) 
-       {
-               Pref = (Preference*) vSetting;
-               if (GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && 
-                   (vPrefDef != NULL)) 
-               {
-                       PrefType = (PrefDef*) vPrefDef;
-                       Pref->Type = PrefType;
-                       Pref->eFlatPrefType = Pref->Type->eType;
-
-                       syslog(LOG_DEBUG, "Loading [%s]with type [%d] [\"%s\"]\n",
-                               ChrPtr(Pref->Key),
-                               Pref->Type->eType,
-                               ChrPtr(Pref->Val));
-
-                       switch (Pref->Type->eType)
-                       {
-                       case PRF_UNSET: /* WHUT? */
-                               break;
-                       case PRF_STRING:
-                               break;
-                       case PRF_INT:
-                               Pref->lval = StrTol(Pref->Val);
-                               Pref->decoded = 1;
-                               break;
-                       case PRF_QP_STRING:
-                               Pref->DeQPed = NewStrBufPlain(NULL, StrLength(Pref->Val));
-                               StrBufEUid_unescapize(Pref->DeQPed, Pref->Val);
-                               Pref->decoded = 1;
-                               break;
-                       case PRF_YESNO:
-                               Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
-                               Pref->decoded = 1;
-                               break;
-                       }
-
-                       if (PrefType->OnLoad != NULL){
-
-                               syslog(LOG_DEBUG, "Loading with: -> %s(\"%s\", %ld)\n",
-                                       ChrPtr(PrefType->OnLoadName),
-                                       ChrPtr(Pref->Val),
-                                       Pref->lval);
-                               PrefType->OnLoad(Pref->Val, Pref->lval);
-                       }
-               }
-       }
-       DeleteHashPos(&It);
-}
-
-void ParsePref(HashList **List, StrBuf *ReadBuf)
-{
-       int Done = 0;
-       Preference *Data = NULL;
-       Preference *LastData = NULL;
-                               
-       while (!Done) {
-               if (StrBuf_ServGetln(ReadBuf) < 0)
-                       break;
-               if ( (StrLength(ReadBuf)==3) && 
-                    !strcmp(ChrPtr(ReadBuf), "000")) {
-                       Done = 1;
-                       break;
-               }
-
-               if ((ChrPtr(ReadBuf)[0] == ' ') &&
-                   (LastData != NULL)) {
-                       StrBufAppendBuf(LastData->Val, ReadBuf, 1);
-               }
-               else {
-                       LastData = Data = malloc(sizeof(Preference));
-                       memset(Data, 0, sizeof(Preference));
-                       Data->Key = NewStrBuf();
-                       Data->Val = NewStrBuf();
-                       StrBufExtract_token(Data->Key, ReadBuf, 0, '|');
-                       StrBufExtract_token(Data->Val, ReadBuf, 1, '|');
-
-                       /***************** BEGIN VILE SLEAZY HACK ************************/
-
-                       /* some users might still have this start page configured, which now breaks */
-
-                       if (    (!strcasecmp(ChrPtr(Data->Key), "startpage"))
-                               && (!strcasecmp(ChrPtr(Data->Val), "/do_template?template=summary_page"))
-                       ) {
-                               FreeStrBuf(&Data->Val);
-                               Data->Val = NewStrBufPlain(HKEY("/summary"));
-                       }
-
-                       /******************* END VILE SLEAZY HACK ************************/
-
-                       if (!IsEmptyStr(ChrPtr(Data->Key)))
-                       {
-                               Put(*List, 
-                                   SKEY(Data->Key),
-                                   Data, 
-                                   DestroyPreference);
-                       }
-                       else 
-                       {
-                               StrBufTrim(ReadBuf);
-                               syslog(LOG_INFO, "ignoring spurious preference line: [%s]\n", 
-                                       ChrPtr(ReadBuf));
-                               DestroyPreference(Data);
-                               LastData = NULL;
-                       }
-                       Data = NULL;
-               }
-       }
-       GetPrefTypes(*List);
-}
-
-
-/*
- * display preferences dialog
- */
-void load_preferences(void) 
-{
-       folder Room;
-       wcsession *WCC = WC;
-       int Done = 0;
-       StrBuf *ReadBuf;
-       long msgnum = 0L;
-       
-       memset(&Room, 0, sizeof(folder));
-       ReadBuf = NewStrBufPlain(NULL, SIZ * 4);
-       if (goto_config_room(ReadBuf, &Room) != 0) {
-               FreeStrBuf(&ReadBuf);
-               FlushFolder(&Room);
-
-               return; /* oh well. */
-       }
-
-       serv_puts("MSGS ALL|0|1");
-       StrBuf_ServGetln(ReadBuf);
-       if (GetServerStatus(ReadBuf, NULL) == 8) {
-               serv_puts("subj|__ WebCit Preferences __");
-               serv_puts("000");
-       }
-       while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) {
-               if ( (StrLength(ReadBuf)==3) && !strcmp(ChrPtr(ReadBuf), "000")) {
-                       Done = 1;
-                       break;
-               }
-               msgnum = StrTol(ReadBuf);
-       }
-
-       if (msgnum > 0L) {
-               serv_printf("MSG0 %ld", msgnum);
-               StrBuf_ServGetln(ReadBuf);
-               if (GetServerStatus(ReadBuf, NULL) == 1) {
-                       while ( (StrBuf_ServGetln(ReadBuf) >= 0)
-                               && (strcmp(ChrPtr(ReadBuf), "text")
-                               && strcmp(ChrPtr(ReadBuf), "000"))
-                       ) {
-                               /* flush */
-                       }
-                       if (!strcmp(ChrPtr(ReadBuf), "text")) {
-                               ParsePref(&WCC->hash_prefs, ReadBuf);
-                       }
-               }
-       }
-
-       /* Go back to the room we're supposed to be in */
-       if (StrLength(WCC->CurRoom.name) > 0) {
-               serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name));
-               StrBuf_ServGetln(ReadBuf);
-               GetServerStatus(ReadBuf, NULL);
-       }
-       FreeStrBuf(&ReadBuf);
-       FlushFolder(&Room);
-}
-
-
-/*
- * Go to the user's configuration room, creating it if necessary.
- * returns 0 on success or nonzero upon failure.
- */
-int goto_config_room(StrBuf *Buf, folder *Room) 
-{
-       serv_printf("GOTO %s", USERCONFIGROOM);
-       StrBuf_ServGetln(Buf);
-       if (GetServerStatus(Buf, NULL) != 2) {  /* try to create the config room if not there */
-               serv_printf("CRE8 1|%s|4|0", USERCONFIGROOM);
-               StrBuf_ServGetln(Buf);
-               GetServerStatus(Buf, NULL);
-
-               serv_printf("GOTO %s", USERCONFIGROOM);
-               StrBuf_ServGetln(Buf);
-               if (GetServerStatus(Buf, NULL) != 2) {
-                       return(1);
-               }
-       }
-       ParseGoto(Room, Buf);
-       return(0);
-}
-
-void WritePrefsToServer(HashList *Hash)
-{
-       wcsession *WCC = WC;
-       long len;
-       HashPos *HashPos;
-       void *vPref;
-       const char *Key;
-       Preference *Pref;
-       StrBuf *SubBuf = NULL;
-       
-       Hash = WCC->hash_prefs;
-#ifdef DBG_PREFS_HASH
-       dbg_PrintHash(Hash, PrintPref, NULL);
-#endif
-       HashPos = GetNewHashPos(Hash, 0);
-       while (GetNextHashPos(Hash, HashPos, &len, &Key, &vPref)!=0)
-       {
-               size_t nchars;
-               if (vPref == NULL)
-                       continue;
-               Pref = (Preference*) vPref;
-               nchars = StrLength(Pref->Val);
-               if (nchars > 80){
-                       int n = 0;
-                       size_t offset, nchars;
-                       if (SubBuf == NULL)
-                               SubBuf = NewStrBufPlain(NULL, SIZ);
-                       nchars = 1;
-                       offset = 0;
-                       while (nchars > 0) {
-                               if (n == 0)
-                                       nchars = 70;
-                               else 
-                                       nchars = 80;
-                               
-                               nchars = StrBufSub(SubBuf, Pref->Val, offset, nchars);
-                               
-                               if (n == 0) {
-                                       serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(SubBuf));
-                               }
-                               else {
-                                       serv_printf(" %s", ChrPtr(SubBuf));
-                               }
-                               
-                               offset += nchars;
-                               nchars = StrLength(Pref->Val) - offset;
-                               n++;
-                       }
-                       
-               }
-               else {
-                       serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(Pref->Val));
-               }
-               
-       }
-       FreeStrBuf(&SubBuf);
-       DeleteHashPos(&HashPos);
-}
-
-/*
- * save the modifications
- */
-void save_preferences(void) 
-{
-       folder Room;
-       wcsession *WCC = WC;
-       int Done = 0;
-       StrBuf *ReadBuf;
-       long msgnum = 0L;
-       
-       ReadBuf = NewStrBuf();
-       memset(&Room, 0, sizeof(folder));
-       if (goto_config_room(ReadBuf, &Room) != 0) {
-               FreeStrBuf(&ReadBuf);
-               FlushFolder(&Room);
-
-               return; /* oh well. */
-       }
-
-       /* make shure the config room has the right type, else it might reject our config */
-       if (Room.view != VIEW_BBS) {
-               serv_printf("VIEW %d", VIEW_BBS);
-               StrBuf_ServGetln(ReadBuf);
-               if (GetServerStatus(ReadBuf, NULL) != 2) {
-                       /* UPS? */
-               }
-               else if (goto_config_room(ReadBuf, &Room) != 0) {
-                       FreeStrBuf(&ReadBuf);
-                       FlushFolder(&Room);
-                       
-                       return; /* oh well. */
-               }
-       }
-
-       serv_puts("MSGS ALL|0|1");
-       StrBuf_ServGetln(ReadBuf);
-       if (GetServerStatus(ReadBuf, NULL) == 8) {
-               serv_puts("subj|__ WebCit Preferences __");
-               serv_puts("000");
-       }
-       while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) {
-               if ( (StrLength(ReadBuf)==3) && !strcmp(ChrPtr(ReadBuf), "000")) {
-                       Done = 1;
-                       break;
-               }
-               msgnum = StrTol(ReadBuf);
-       }
-
-       if (msgnum > 0L) {
-               serv_printf("DELE %ld", msgnum);
-               StrBuf_ServGetln(ReadBuf);
-               GetServerStatus(ReadBuf, NULL);
-       }
-
-       serv_printf("ENT0 1||0|1|__ WebCit Preferences __|");
-       StrBuf_ServGetln(ReadBuf);
-       if (GetServerStatus(ReadBuf, NULL) == 4) {
-
-               WritePrefsToServer(WCC->hash_prefs);
-               serv_puts("");
-               serv_puts("000");
-       }
-
-       /** Go back to the room we're supposed to be in */
-       if (StrLength(WCC->CurRoom.name) > 0) {
-               serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name));
-               StrBuf_ServGetln(ReadBuf);
-               GetServerStatus(ReadBuf, NULL);
-       }
-       FreeStrBuf(&ReadBuf);
-       FlushFolder(&Room);
-}
-
-/*
- * query the actual setting of key in the citadel database
- *
- * key         config key to query
- * keylen      length of the key string
- * value       StrBuf-value to the key to get
- * returns:    found?
- */
-int get_pref_backend(const char *key, size_t keylen, Preference **Pref)
-{
-       void *hash_value = NULL;
-#ifdef DBG_PREFS_HASH
-       dbg_PrintHash(WC->hash_prefs, PrintPref, NULL);
-#endif
-       if (GetHash(WC->hash_prefs, key, keylen, &hash_value) == 0) {
-               *Pref = NULL;
-               return 0;
-       }
-       else {
-               *Pref = (Preference*) hash_value;
-               return 1;
-       }
-}
-
-int get_PREFERENCE(const char *key, size_t keylen, StrBuf **value)
-{
-       Preference *Pref;
-       int Ret;
-
-       Ret = get_pref_backend(key, keylen, &Pref);
-       if (Ret != 0)
-               *value = Pref->Val;
-       else
-               *value = NULL;
-       return Ret;
-}
-
-/*
- * Write a key into the webcit preferences database for this user
- *
- * key                 key whichs value is to be modified
- * keylen              length of the key string
- * value               value to set
- * save_to_server      1 = flush all data to the server, 0 = cache it for now
- */
-long compare_preference(const Preference *PrefA, const Preference *PrefB)
-{
-       ePrefType TypeA, TypeB;
-
-       if (PrefA->Type != NULL) {
-               TypeA = PrefA->Type->eType;
-       }
-       else {
-               TypeA = PrefA->eFlatPrefType;
-       }
-
-       if (PrefB->Type != NULL) {
-               TypeB = PrefB->Type->eType;
-       }
-       else {
-               TypeB = PrefB->eFlatPrefType;
-       }
-
-       if (    (TypeA != PRF_UNSET)
-               && (TypeB != PRF_UNSET)
-               && (TypeA != TypeB)
-       ) {
-               if (TypeA > TypeB) {
-                       return 1;
-               }
-               else {  /* (PrefA->Type < PrefB->Type) */
-                       return -1;
-               }
-       }
-
-       if (TypeB == PRF_UNSET) {
-               TypeA = PRF_UNSET;
-       }
-                   
-       switch (TypeA)
-       {
-       default:
-       case PRF_UNSET:
-       case PRF_STRING:
-               return strcmp(ChrPtr(PrefA->Val), ChrPtr(PrefB->Val));
-       case PRF_YESNO:
-       case PRF_INT:
-               if (PrefA->lval == PrefB->lval)
-                       return 0;
-               else if (PrefA->lval > PrefB->lval)
-                       return 1;
-               else
-                       return -1;
-       case PRF_QP_STRING:
-               return strcmp(ChrPtr(PrefA->DeQPed), 
-                             ChrPtr(PrefB->DeQPed));
-       }
-}
-
-
-/*
- * Write a key into the webcit preferences database for this user
- *
- * key                 key which value is to be modified
- * keylen              length of the key string
- * value               value to set
- * save_to_server      1 = flush all data to the server, 0 = cache it for now
- */
-void set_preference_backend(const char *key, size_t keylen, 
-                           long lvalue, 
-                           StrBuf *value, 
-                           long lPrefType,
-                           int save_to_server, 
-                           PrefDef *PrefType) 
-{
-       wcsession *WCC = WC;
-       void *vPrefDef;
-       void *vPrefB;
-       Preference *Pref;
-
-       Pref = (Preference*) malloc(sizeof(Preference));
-       memset(Pref, 0, sizeof(Preference));
-       Pref->Key = NewStrBufPlain(key, keylen);
-
-       if ((PrefType == NULL) &&
-           GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && 
-           (vPrefDef != NULL))
-               PrefType = (PrefDef*) vPrefDef;
-
-       if (PrefType != NULL)
-       {
-               Pref->Type = PrefType;
-               Pref->eFlatPrefType = PrefType->eType;
-               if (Pref->Type->eType != lPrefType)
-                       syslog(LOG_WARNING, "warning: saving preference with wrong type [%s] %d != %ld \n",
-                               key, Pref->Type->eType, lPrefType);
-               switch (Pref->Type->eType)
-               {
-               case PRF_UNSET: /* default to string... */
-               case PRF_STRING:
-                       Pref->Val = value;
-                       Pref->decoded = 1;
-                       break;
-               case PRF_INT:
-                       Pref->lval = lvalue;
-                       Pref->Val = value;
-                       if (Pref->Val == NULL)
-                               Pref->Val = NewStrBufPlain(NULL, 64);
-                       StrBufPrintf(Pref->Val, "%ld", lvalue);
-                       Pref->decoded = 1;
-                       break;
-               case PRF_QP_STRING:
-                       Pref->DeQPed = value;
-                       Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
-                       StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
-                       Pref->decoded = 1;
-                       break;
-               case PRF_YESNO:
-                       Pref->lval = lvalue;
-                       if (lvalue) 
-                               Pref->Val = NewStrBufPlain(HKEY("yes"));
-                       else
-                               Pref->Val = NewStrBufPlain(HKEY("no"));
-                       Pref->decoded = 1;
-                       break;
-               }
-               if (Pref->Type->OnLoad != NULL)
-                       Pref->Type->OnLoad(Pref->Val, Pref->lval);
-       }
-       else {
-               Pref->eFlatPrefType = lPrefType;
-               switch (lPrefType)
-               {
-               case PRF_STRING:
-                       Pref->Val = value;
-                       Pref->decoded = 1;
-                       break;
-               case PRF_INT:
-                       Pref->lval = lvalue;
-                       Pref->Val = value;
-                       if (Pref->Val == NULL)
-                               Pref->Val = NewStrBufPlain(NULL, 64);
-                       StrBufPrintf(Pref->Val, "%ld", lvalue);
-                       Pref->decoded = 1;
-                       break;
-               case PRF_QP_STRING:
-                       Pref->DeQPed = value;
-                       Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
-                       StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
-                       Pref->decoded = 1;
-                       break;
-               case PRF_YESNO:
-                       Pref->lval = lvalue;
-                       if (lvalue) 
-                               Pref->Val = NewStrBufPlain(HKEY("yes"));
-                       else
-                               Pref->Val = NewStrBufPlain(HKEY("no"));
-                       Pref->decoded = 1;
-                       break;
-               }
-       }
-
-       if ((save_to_server != 0) && 
-           GetHash(WCC->hash_prefs, key, keylen, &vPrefB) && 
-           (vPrefB != NULL) && 
-           (compare_preference (Pref, vPrefB) == 0))
-               save_to_server = 0;
-
-       Put(WCC->hash_prefs, key, keylen, Pref, DestroyPreference);
-       
-       if (save_to_server) WCC->SavePrefsToServer = 1;
-}
-
-void set_PREFERENCE(const char *key, size_t keylen, StrBuf *value, int save_to_server) 
-{
-       set_preference_backend(key, keylen, 0, value, PRF_STRING, save_to_server, NULL);
-}
-
-int get_PREF_LONG(const char *key, size_t keylen, long *value, long Default)
-{
-       Preference *Pref;
-       int Ret;
-
-       Ret = get_pref_backend(key, keylen, &Pref);
-       if (Ret == 0) {
-               *value = Default;
-               return 0;
-       }
-
-       if (Pref->decoded)
-               *value = Pref->lval;
-       else {
-               *value = Pref->lval = atol(ChrPtr(Pref->Val));
-               Pref->decoded = 1;
-       }
-       return Ret;
-}
-
-
-void set_PREF_LONG(const char *key, size_t keylen, long value, int save_to_server)
-{
-       set_preference_backend(key, keylen, value, NULL, PRF_INT, save_to_server, NULL);
-}
-
-int get_PREF_YESNO(const char *key, size_t keylen, int *value, int Default)
-{
-       Preference *Pref;
-       int Ret;
-
-       Ret = get_pref_backend(key, keylen, &Pref);
-       if (Ret == 0) {
-               *value = Default;
-               return 0;
-       }
-
-       if (Pref->decoded)
-               *value = Pref->lval;
-       else {
-               *value = Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
-               Pref->decoded = 1;
-       }
-       return Ret;
-}
-
-void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_server)
-{
-       set_preference_backend(key, keylen, value, NULL, PRF_YESNO, save_to_server, NULL);
-}
-
-int get_room_prefs_backend(const char *key, size_t keylen, 
-                          Preference **Pref)
-{
-       StrBuf *pref_name;
-       int Ret;
-
-       pref_name = NewStrBufPlain (HKEY("ROOM:"));
-       StrBufAppendBuf(pref_name, WC->CurRoom.name, 0);
-       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
-       StrBufAppendBufPlain(pref_name, key, keylen, 0);
-       Ret = get_pref_backend(SKEY(pref_name), Pref);
-       FreeStrBuf(&pref_name);
-
-       return Ret;
-}
-
-const StrBuf *get_X_PREFS(const char *key, size_t keylen, 
-                         const char *xkey, size_t xkeylen)
-{
-       int ret;
-       StrBuf *pref_name;
-       Preference *Prf;
-       
-       pref_name = NewStrBufPlain (HKEY("XPREF:"));
-       StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
-       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
-       StrBufAppendBufPlain(pref_name, key, keylen, 0);
-
-       ret = get_pref_backend(SKEY(pref_name), &Prf);
-       FreeStrBuf(&pref_name);
-
-       if (ret)
-               return Prf->Val;
-       else return NULL;
-}
-
-void set_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen, StrBuf *value, int save_to_server)
-{
-       StrBuf *pref_name;
-       
-       pref_name = NewStrBufPlain (HKEY("XPREF:"));
-       StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
-       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
-       StrBufAppendBufPlain(pref_name, key, keylen, 0);
-
-       set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
-       FreeStrBuf(&pref_name);
-}
-
-
-long get_ROOM_PREFS_LONG(const char *key, size_t keylen, long *value, long Default)
-{
-       Preference *Pref;
-       int Ret;
-
-       Ret = get_room_prefs_backend(key, keylen, &Pref);
-
-       if (Ret == 0) {
-               *value = Default;
-               return 0;
-       }
-
-       if (Pref->decoded)
-               *value = Pref->lval;
-       else {
-               *value = Pref->lval = atol(ChrPtr(Pref->Val));
-               Pref->decoded = 1;
-       }
-       return Ret;
-}
-
-
-StrBuf *get_ROOM_PREFS(const char *key, size_t keylen)
-{
-       Preference *Pref;
-       int Ret;
-
-       Ret = get_room_prefs_backend(key, keylen, &Pref);
-
-       if (Ret == 0) {
-               return NULL;
-       }
-       else 
-               return Pref->Val;
-}
-
-void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_server)
-{
-       StrBuf *pref_name;
-       
-       pref_name = NewStrBufPlain (HKEY("ROOM:"));
-       StrBufAppendBuf(pref_name, WC->CurRoom.name, 0);
-       StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
-       StrBufAppendBufPlain(pref_name, key, keylen, 0);
-       set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
-       FreeStrBuf(&pref_name);
-}
-
-
-void GetPreferences(HashList *Setting)
-{
-        wcsession *WCC = WC;
-       HashPos *It;
-       long len;
-       const char *Key;
-       void *vSetting;
-       PrefDef *PrefType;
-       StrBuf *Buf;
-       long lval;
-       HashList *Tmp;
-
-       Tmp = WCC->hash_prefs;
-       WCC->hash_prefs = Setting;
-
-       It = GetNewHashPos(PreferenceHooks, 0);
-       while (GetNextHashPos(PreferenceHooks, It, &len, &Key, &vSetting)) {
-               PrefType = (PrefDef*) vSetting;
-
-               if (!HaveBstr(SKEY(PrefType->Setting)))
-                       continue;
-               switch (PrefType->eType) {
-               case PRF_UNSET:
-               case PRF_STRING:
-                       Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
-                       set_preference_backend(SKEY(PrefType->Setting),
-                                              0, 
-                                              Buf, 
-                                              PRF_STRING,
-                                              1, 
-                                              PrefType);
-                       break;
-               case PRF_INT:
-                       lval = LBstr(SKEY(PrefType->Setting));
-                       set_preference_backend(SKEY(PrefType->Setting),
-                                              lval, 
-                                              NULL, 
-                                              PRF_INT,
-                                              1, 
-                                              PrefType);
-                       break;
-               case PRF_QP_STRING:
-                       Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
-                       set_preference_backend(SKEY(PrefType->Setting),
-                                              0, 
-                                              Buf, 
-                                              PRF_QP_STRING,
-                                              1, 
-                                              PrefType);
-                       break;
-               case PRF_YESNO:
-                       lval = YesBstr(SKEY(PrefType->Setting));
-                       set_preference_backend(SKEY(PrefType->Setting),
-                                              lval, 
-                                              NULL, 
-                                              PRF_YESNO,
-                                              1, 
-                                              PrefType);
-                       break;
-               }
-       }
-       WCC->hash_prefs = Tmp;
-       DeleteHashPos(&It);
-}
-
-
-/*
- * Commit new preferences and settings
- */
-void set_preferences(void)
-{      
-       if (!havebstr("change_button")) {
-               AppendImportantMessage(_("Cancelled.  No settings were changed."), -1);
-               display_main_menu();
-               return;
-       }
-       GetPreferences(WC->hash_prefs);
-       display_main_menu();
-}
-
-
-void tmplput_CFG_Value(StrBuf *Target, WCTemplputParams *TP)
-{
-       Preference *Pref;
-       if (get_pref_backend(TKEY(0), &Pref))
-       {
-               if (Pref->Type == NULL) {
-                       StrBufAppendTemplate(Target, TP, Pref->Val, 1);
-               }
-               switch (Pref->Type->eType)
-               {
-               case PRF_UNSET: /* default to string... */
-               case PRF_STRING:
-                       StrBufAppendTemplate(Target, TP, Pref->Val, 1);
-                       break;
-               case PRF_INT:
-                       if (Pref->decoded != 1) {
-                               if (Pref->Val == NULL)
-                                       Pref->Val = NewStrBufPlain(NULL, 64);
-                               StrBufPrintf(Pref->Val, "%ld", Pref->lval);
-                               Pref->decoded = 1;
-                       }
-                       StrBufAppendTemplate(Target, TP, Pref->Val, 1);
-                       break;
-               case PRF_QP_STRING:
-                       if (Pref->decoded != 1) {
-                               if (Pref->DeQPed == NULL)
-                                       Pref->DeQPed = NewStrBufPlain(NULL, StrLength(Pref->Val));
-                                       
-                               StrBufEUid_unescapize(Pref->DeQPed, Pref->Val);
-                               Pref->decoded = 1;
-                       }
-                       StrBufAppendTemplate(Target, TP, Pref->DeQPed, 1);
-                       break;
-               case PRF_YESNO:
-                       if (Pref->decoded != 1) {
-                               Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
-                               Pref->decoded = 1;
-                       }
-                       StrBufAppendTemplate(Target, TP, Pref->Val, 1);
-                       break;
-               }
-       }
-}
-
-void tmplput_CFG_Descr(StrBuf *Target, WCTemplputParams *TP)
-{
-       const char *SettingStr;
-       SettingStr = PrefGetLocalStr(TKEY(0));
-       if (SettingStr != NULL) 
-               StrBufAppendBufPlain(Target, SettingStr, -1, 0);
-}
-void tmplput_CFG_RoomValueLong(StrBuf *Target, WCTemplputParams *TP)
-{
-       long lvalue;
-       long defval = 0;
-
-       if (HAVE_PARAM(1))
-               defval = GetTemplateTokenNumber(Target, TP, 1, 0);
-       get_ROOM_PREFS_LONG(TKEY(0), &lvalue, defval);
-       StrBufAppendPrintf(Target, "%ld", lvalue);
-}
-void tmplput_CFG_RoomValue(StrBuf *Target, WCTemplputParams *TP)
-{
-       StrBuf *pref = get_ROOM_PREFS(TKEY(0));
-       if (pref != NULL) 
-               StrBufAppendBuf(Target, pref, 0);
-}
-int ConditionalHasRoomPreference(StrBuf *Target, WCTemplputParams *TP) 
-{
-       if (get_ROOM_PREFS(TP->Tokens->Params[0]->Start, 
-                          TP->Tokens->Params[0]->len) != NULL) 
-               return 1;
-  
-       return 0;
-}
-
-int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP)
-{
-       StrBuf *Pref;
-
-       if (!get_PREFERENCE(TKEY(2), &Pref)) 
-               return 0;
-       
-       if (!HAVE_PARAM(3)) {
-               return 1;
-       }
-       else if (IS_NUMBER(TP->Tokens->Params[3]->Type))
-       {
-               return StrTol(Pref) == GetTemplateTokenNumber (Target, TP, 3, 0);
-       }
-       else 
-       {
-               const char *pch;
-               long len;
-               
-               GetTemplateTokenString(Target, TP, 3, &pch, &len);
-               
-               return ((len == StrLength(Pref)) &&
-                       (strcmp(pch, ChrPtr(Pref)) == 0));
-       }
-}
-
-int ConditionalHasPreference(StrBuf *Target, WCTemplputParams *TP)
-{
-       StrBuf *Pref;
-
-       if (!get_PREFERENCE(TKEY(2), &Pref) || 
-           (Pref == NULL)) 
-               return 0;
-       else 
-               return 1;
-}
-
-
-/********************************************************************************
- *                 preferences stored discrete in citserver
- ********************************************************************************/
-CtxType CTX_VEA = CTX_NONE;
-typedef struct __ValidEmailAddress {
-       StrBuf *Address;
-       int IsDefault;
-}ValidEmailAddress;
-
-void DeleteValidEmailAddress(void *v)
-{
-       ValidEmailAddress *VEA = (ValidEmailAddress*)v;
-       FreeStrBuf(&VEA->Address);
-       free(VEA);
-}
-void tmplput_VEA(StrBuf *Target, WCTemplputParams *TP)
-{
-       ValidEmailAddress* VEA = (ValidEmailAddress*) CTX((CTX_VEA));
-       StrBufAppendTemplate(Target, TP, VEA->Address, 0);
-}
-int ConditionalPreferenceIsDefaulVEA(StrBuf *Target, WCTemplputParams *TP)
-{
-       ValidEmailAddress* VEA = (ValidEmailAddress*) CTX((CTX_VEA));
-       return VEA->IsDefault;
-}
-HashList *GetGVEAHash(StrBuf *Target, WCTemplputParams *TP)
-{
-       StrBuf *Rcp;
-       HashList *List = NULL;
-       int Done = 0;
-       int i, n = 1;
-       char N[64];
-       StrBuf *DefaultFrom = NULL;
-       const StrBuf *EnvelopeTo;
-       ValidEmailAddress *VEA;
-
-       get_preference("defaultfrom", &DefaultFrom);
-       EnvelopeTo = sbstr("nvto");
-       Rcp = NewStrBuf();
-       serv_puts("GVEA");
-       StrBuf_ServGetln(Rcp);
-       if (GetServerStatus(Rcp, NULL) == 1) {
-               FlushStrBuf(Rcp);
-               List = NewHash(1, NULL);
-               while (!Done && (StrBuf_ServGetln(Rcp)>=0)) {
-                       if ( (StrLength(Rcp)==3) && 
-                            !strcmp(ChrPtr(Rcp), "000")) 
-                       {
-                               Done = 1;
-                       }
-                       else {
-                               VEA = (ValidEmailAddress*) malloc(sizeof(ValidEmailAddress));
-                               i = snprintf(N, sizeof(N), "%d", n);
-                               StrBufTrim(Rcp);
-                               VEA->Address = Rcp;
-                               if (StrLength(EnvelopeTo) > 0)
-                                       VEA->IsDefault = strstr(ChrPtr(EnvelopeTo), ChrPtr(Rcp)) != NULL;
-                               else if (StrLength(DefaultFrom) > 0)
-                                       VEA->IsDefault = !strcmp(ChrPtr(Rcp), ChrPtr(DefaultFrom));
-                               else
-                                       VEA->IsDefault = 0;
-
-                               Put(List, N, i, VEA, DeleteValidEmailAddress);
-                               Rcp = NewStrBuf();
-                       }
-                       n++;
-               }
-       }
-       FreeStrBuf(&Rcp);
-       return List;
-}
-void DeleteGVEAHash(HashList **KillMe)
-{
-       DeleteHash(KillMe);
-}
-
-HashList *GetGVSNHash(StrBuf *Target, WCTemplputParams *TP)
-{
-       StrBuf *Rcp;
-       HashList *List = NULL;
-       int Done = 0;
-       int i, n = 1;
-       char N[64];
-
-       Rcp = NewStrBuf();
-       serv_puts("GVSN");
-       StrBuf_ServGetln(Rcp);
-       if (GetServerStatus(Rcp, NULL) == 1) {
-               FlushStrBuf(Rcp);
-               List = NewHash(1, NULL);
-               while (!Done && (StrBuf_ServGetln(Rcp)>=0)) {
-                       if ( (StrLength(Rcp)==3) && 
-                            !strcmp(ChrPtr(Rcp), "000")) 
-                       {
-                               Done = 1;
-                       }
-                       else {
-                               i = snprintf(N, sizeof(N), "%d", n);
-                               StrBufTrim(Rcp);
-                               Put(List, N, i, Rcp, HFreeStrBuf);
-                               Rcp = NewStrBuf();
-                       }
-                       n++;
-               }
-       }
-       FreeStrBuf(&Rcp);
-       return List;
-}
-void DeleteGVSNHash(HashList **KillMe)
-{
-       DeleteHash(KillMe);
-}
-
-
-
-
-/*
- * Offer to make any page the user's "start page" (only if logged in)
- */
-void offer_start_page(StrBuf *Target, WCTemplputParams *TP)
-{
-       if (WC->logged_in) {
-               wc_printf("<a href=\"change_start_page?startpage=");
-               urlescputs(ChrPtr(WC->Hdr->this_page));
-               wc_printf("\">");
-               wc_printf(_("Make this my start page"));
-               wc_printf("</a>");
-       };
-}
-
-
-/*
- * Change the user's start page
- */
-void change_start_page(void) 
-{
-       const char *pch;
-       void *vHandler;
-       int ProhibitSave = 0;
-       const StrBuf *pStartPage = sbstr("startpage");
-
-       if (pStartPage != NULL) {
-               pch = strchr(ChrPtr(pStartPage), '?');
-
-               if ((pch != NULL) && (
-                           GetHash(HandlerHash, ChrPtr(pStartPage), pch - ChrPtr(pStartPage), &vHandler), 
-                           (vHandler != NULL) &&
-                           ((((WebcitHandler*)vHandler)->Flags & PROHIBIT_STARTPAGE) != 0)))
-               { /* OK, This handler doesn't want to be set as start page, prune it. */
-                       ProhibitSave = 1;
-               }
-       }
-
-       if ((pStartPage == NULL) || 
-           (ProhibitSave == 1))
-       {
-               set_preference_backend(HKEY("startpage"), 
-                                      0, 
-                                      NewStrBufPlain(HKEY("")),
-                                      PRF_STRING,
-                                      1, 
-                                      NULL);
-               if (ProhibitSave == 1)
-                       AppendImportantMessage(_("This isn't allowed to become the start page."), -1);
-               else
-                       AppendImportantMessage(_("You no longer have a start page selected."), -1);
-               display_main_menu();
-               return;
-       }
-
-
-
-       set_preference_backend(HKEY("startpage"), 
-                              0, 
-                              NewStrBufDup(pStartPage),
-                              PRF_STRING,
-                              1, 
-                              NULL);
-
-       output_headers(1, 1, 0, 0, 0, 0);
-       do_template("newstartpage");
-       wDumpContent(1);
-}
-
-
-void LoadStartpage(StrBuf *URL, long lvalue)
-{
-       const char *pch;
-       void *vHandler;
-       pch = strchr(ChrPtr(URL), '?');
-       if (pch == NULL) {
-               /* purge the sins of the past... */
-               pch = strchr(ChrPtr(URL), '&');
-               if (pch != NULL) {
-                       StrBufPeek(URL, pch, -1, '?');
-                       WC->SavePrefsToServer = 1;
-               }
-       }
-       else if (GetHash(HandlerHash, ChrPtr(URL), pch - ChrPtr(URL), &vHandler), 
-                (vHandler != NULL) &&
-                ((((WebcitHandler*)vHandler)->Flags & PROHIBIT_STARTPAGE) != 0))
-       { /* OK, This handler doesn't want to be set as start page, prune it. */
-               FlushStrBuf(URL);
-               WC->SavePrefsToServer = 1;
-       }
-}
-
-
-void 
-InitModule_PREFERENCES
-(void)
-{
-       RegisterCTX(CTX_VEA);
-
-       WebcitAddUrlHandler(HKEY("set_preferences"), "", 0, set_preferences, 0);
-       WebcitAddUrlHandler(HKEY("change_start_page"), "", 0, change_start_page, 0);
-
-       RegisterPreference("startpage", _("Prefered startpage"), PRF_STRING, LoadStartpage);
-
-       RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, NULL, CTX_NONE);
-       RegisterNamespace("PREF:ROOM:VALUE", 1, 2, tmplput_CFG_RoomValue,  NULL, CTX_NONE);
-       RegisterNamespace("PREF:ROOM:VALUE:INT", 1, 2, tmplput_CFG_RoomValueLong,  NULL, CTX_NONE);
-       RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, NULL, CTX_NONE);
-       
-       RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, NULL, CTX_NONE);
-
-       RegisterConditional("COND:PREF", 4, ConditionalPreference, CTX_NONE);
-       RegisterConditional("COND:PREF:SET", 4, ConditionalHasPreference, CTX_NONE);
-       RegisterConditional("COND:ROOM:SET", 4, ConditionalHasRoomPreference, CTX_NONE);
-       
-       RegisterIterator("PREF:VALID:EMAIL:ADDR", 0, NULL, 
-                        GetGVEAHash, NULL, DeleteGVEAHash, CTX_VEA, CTX_NONE, IT_NOFLAG);
-       RegisterNamespace("PREF:VALID:EMAIL:ADDR:STR", 1, 1, tmplput_VEA, NULL, CTX_VEA);
-       RegisterConditional("COND:PREF:VALID:EMAIL:ADDR:STR", 4, ConditionalPreferenceIsDefaulVEA, CTX_VEA);
-
-       RegisterIterator("PREF:VALID:EMAIL:NAME", 0, NULL, 
-                        GetGVSNHash, NULL, DeleteGVSNHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
-
-}
-
-
-void 
-ServerStartModule_PREFERENCES
-(void)
-{
-       PreferenceHooks = NewHash(1, NULL);
-}
-
-
-
-void 
-ServerShutdownModule_PREFERENCES
-(void)
-{
-       DeleteHash(&PreferenceHooks);
-}
-
-void
-SessionDetachModule__PREFERENCES
-(wcsession *sess)
-{
-       if (sess->SavePrefsToServer) {
-               save_preferences();
-               sess->SavePrefsToServer = 0;
-       }
-}
-
-void
-SessionNewModule_PREFERENCES
-(wcsession *sess)
-{
-       sess->hash_prefs = NewHash(1,NULL);
-}
-
-void 
-SessionDestroyModule_PREFERENCES
-(wcsession *sess)
-{
-       DeleteHash(&sess->hash_prefs);
-}