X-Git-Url: https://code.citadel.org/?p=citadel.git;a=blobdiff_plain;f=webcit%2Fpreferences.c;h=ae381cc1e5b45afe68b9246c695f154a51b872a9;hp=64001d7a420a147f44387d15ca47abb6d0f6f3af;hb=HEAD;hpb=c881934110f3c99194fad96c923b7d0ecb24ecdc diff --git a/webcit/preferences.c b/webcit/preferences.c index 64001d7a4..e438b0318 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -1,37 +1,86 @@ /* - * $Id$ - * * 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 "groupdav.h" +#include "dav.h" HashList *PreferenceHooks; +extern HashList *HandlerHash; -typedef struct _Prefs { - long Type; - const char *Setting; +typedef struct _PrefDef { + ePrefType eType; + StrBuf *Setting; const char *PrefStr; -} Prefs; + 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, const char *PrefStr, long Type) +void _RegisterPreference(const char *Setting, long SettingLen, + const char *PrefStr, + ePrefType Type, + PrefEvalFunc OnLoad, + const char *OnLoadName) { - Prefs *Newpref = (Prefs*) malloc(sizeof(Prefs)); - Newpref->Setting = Setting; + PrefDef *Newpref = (PrefDef*) malloc(sizeof(PrefDef)); + Newpref->Setting = NewStrBufPlain(Setting, SettingLen); Newpref->PrefStr = PrefStr; - Newpref->Type = Type; - Put(PreferenceHooks, Setting, strlen(Setting), Newpref, NULL); + 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) { - Prefs *Newpref = (Prefs*) hash_value; + PrefDef *Newpref = (PrefDef*) hash_value; return _(Newpref->PrefStr); } @@ -39,743 +88,960 @@ const char *PrefGetLocalStr(const char *Setting, long len) } #ifdef DBG_PREFS_HASH -inline const char *PrintPref(void *Prefstr) +inline const char *PrintPref(void *vPref) { - return ChrPtr(Prefstr); + 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) { - char buf[SIZ]; - long msgnum = 0L; +void load_preferences(void) +{ + folder Room; + wcsession *WCC = WC; + int Done = 0; StrBuf *ReadBuf; + long msgnum = 0L; - serv_printf("GOTO %s", USERCONFIGROOM); - serv_getln(buf, sizeof buf); - if (buf[0] != '2') return; - + 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"); - serv_getln(buf, sizeof buf); - if (buf[0] == '8') { + StrBuf_ServGetln(ReadBuf); + if (GetServerStatus(ReadBuf, NULL) == 8) { serv_puts("subj|__ WebCit Preferences __"); serv_puts("000"); } - while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { - msgnum = atol(buf); + 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); - serv_getln(buf, sizeof buf); - if (buf[0] == '1') { - ReadBuf = NewStrBuf(); - while (StrBuf_ServGetln(ReadBuf), - (strcmp(ChrPtr(ReadBuf), "text") && - strcmp(ChrPtr(ReadBuf), "000"))) { + 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")) { - StrBuf *Key; - StrBuf *Data = NULL; - StrBuf *LastData = NULL; - - Key = NewStrBuf(); - while (StrBuf_ServGetln(ReadBuf), - strcmp(ChrPtr(ReadBuf), "000")) - { - if ((ChrPtr(ReadBuf)[0] == ' ') && - (Data != NULL)) { - StrBufAppendBuf(Data, ReadBuf, 1); - } - else { - LastData = Data = NewStrBuf(); - StrBufExtract_token(Key, ReadBuf, 0, '|'); - StrBufExtract_token(Data, ReadBuf, 1, '|'); - if (!IsEmptyStr(ChrPtr(Key))) - { - Put(WC->hash_prefs, - ChrPtr(Key), StrLength(Key), - Data, - HFreeStrBuf); - } - else - { - FreeStrBuf(&Data); - LastData = NULL; - } - } - } - FreeStrBuf(&Key); + ParsePref(&WCC->hash_prefs, ReadBuf); } - FreeStrBuf(&ReadBuf); } } /* Go back to the room we're supposed to be in */ - serv_printf("GOTO %s", WC->wc_roomname); - serv_getln(buf, sizeof buf); + if (StrLength(WCC->CurRoom.name) > 0) { + serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name)); + StrBuf_ServGetln(ReadBuf); + GetServerStatus(ReadBuf, NULL); + } + FreeStrBuf(&ReadBuf); + FlushFolder(&Room); } -/** - * \brief Goto the user's configuration room, creating it if necessary. - * \return 0 on success or nonzero upon failure. - */ -int goto_config_room(void) { - char buf[SIZ]; +/* + * 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); - serv_getln(buf, sizeof buf); - if (buf[0] != '2') { /* try to create the config room if not there */ + 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); - serv_getln(buf, sizeof buf); + StrBuf_ServGetln(Buf); + GetServerStatus(Buf, NULL); + serv_printf("GOTO %s", USERCONFIGROOM); - serv_getln(buf, sizeof buf); - if (buf[0] != '2') return(1); + StrBuf_ServGetln(Buf); + if (GetServerStatus(Buf, NULL) != 2) { + return(1); + } } + ParseGoto(Room, Buf); return(0); } -/** - * \brief save the modifications +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) { - char buf[SIZ]; +void save_preferences(void) +{ + folder Room; + wcsession *WCC = WC; + int Done = 0; + StrBuf *ReadBuf; long msgnum = 0L; - if (goto_config_room() != 0) return; /* oh well. */ + 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"); - serv_getln(buf, sizeof buf); - if (buf[0] == '8') { + StrBuf_ServGetln(ReadBuf); + if (GetServerStatus(ReadBuf, NULL) == 8) { serv_puts("subj|__ WebCit Preferences __"); serv_puts("000"); } - while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { - msgnum = atol(buf); + 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); - serv_getln(buf, sizeof buf); + StrBuf_ServGetln(ReadBuf); + GetServerStatus(ReadBuf, NULL); } serv_printf("ENT0 1||0|1|__ WebCit Preferences __|"); - serv_getln(buf, sizeof buf); - if (buf[0] == '4') { - long len; - HashPos *HashPos; - HashList *Hash; - void *Value; - const char *Key; - StrBuf *Buf; - StrBuf *SubBuf = NULL; - - Hash = WC->hash_prefs; -#ifdef DBG_PREFS_HASH - dbg_PrintHash(Hash, PrintPref, NULL); -#endif - HashPos = GetNewHashPos(Hash, 0); - while (GetNextHashPos(Hash, HashPos, &len, &Key, &Value)!=0) - { - size_t nchars; - Buf = (StrBuf*) Value; - if (Buf == NULL) - continue; - nchars = StrLength(Buf); - if (nchars > 80){ - int n = 0; - size_t offset, nchars; - if (SubBuf == NULL) - SubBuf = NewStrBuf(); - nchars = 1; - offset = 0; - while (nchars > 0) { - if (n == 0) - nchars = 70; - else - nchars = 80; - - nchars = StrBufSub(SubBuf, Buf, offset, nchars); - - if (n == 0) - serv_printf("%s|%s", Key, ChrPtr(SubBuf)); - else - serv_printf(" %s", ChrPtr(SubBuf)); - - offset += nchars; - nchars = StrLength(Buf) - offset; - n++; - } - - } - else - serv_printf("%s|%s", Key, ChrPtr(Buf)); - - } - if (SubBuf != NULL) - FreeStrBuf(&SubBuf); + StrBuf_ServGetln(ReadBuf); + if (GetServerStatus(ReadBuf, NULL) == 4) { + + WritePrefsToServer(WCC->hash_prefs); serv_puts(""); serv_puts("000"); - DeleteHashPos(&HashPos); } /** Go back to the room we're supposed to be in */ - serv_printf("GOTO %s", WC->wc_roomname); - serv_getln(buf, sizeof buf); + if (StrLength(WCC->CurRoom.name) > 0) { + serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name)); + StrBuf_ServGetln(ReadBuf); + GetServerStatus(ReadBuf, NULL); + } + FreeStrBuf(&ReadBuf); + FlushFolder(&Room); } -/** - * \brief query the actual setting of key in the citadel database - * \param key config key to query - * \param keylen length of the key string - * \param value StrBuf-value to the key to get - * \returns found? +/* + * 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_PREFERENCE(const char *key, size_t keylen, StrBuf **value) +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) { - *value = NULL; + *Pref = NULL; return 0; } else { - *value = NULL; - *value = (StrBuf*) hash_value; + *Pref = (Preference*) hash_value; return 1; } } -/** - * \brief Write a key into the webcit preferences database for this user - * - * \params key key whichs value is to be modified - * \param keylen length of the key string - * \param value value to set - * \param save_to_server 1 = flush all data to the server, 0 = cache it for now - */ -void set_PREFERENCE(const char *key, size_t keylen, StrBuf *value, int save_to_server) { - - Put(WC->hash_prefs, key, keylen, value, HFreeStrBuf); - - if (save_to_server) save_preferences(); +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; } -int get_PREF_LONG(const char *key, size_t keylen, long *value, long Default) +/* + * 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) { - int ret; - StrBuf *val; - ret = get_PREFERENCE(key, keylen, &val); - if (ret) { - *value = atol(ChrPtr(val)); + ePrefType TypeA, TypeB; + + if (PrefA->Type != NULL) { + TypeA = PrefA->Type->eType; } else { - *value = Default; + TypeA = PrefA->eFlatPrefType; } - return ret; + 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)); + } } -void set_PREF_LONG(const char *key, size_t keylen, long value, int save_to_server) +/* + * 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) { - StrBuf *val; - if (get_PREFERENCE(key, keylen, &val)) { - StrBufPrintf(val, "%ld", value); + 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 { - val = NewStrBuf(); - StrBufPrintf(val, "%ld", value); - set_PREFERENCE(key, keylen, val, save_to_server); + 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; +} -int get_PREF_YESNO(const char *key, size_t keylen, int *value, int Default) +void set_PREFERENCE(const char *key, size_t keylen, StrBuf *value, int save_to_server) { - int ret; - StrBuf *val; - ret = get_PREFERENCE(key, keylen, &val); - if (ret) { - *value = strcmp(ChrPtr(val), "yes") == 0; + 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 = Default; + *value = Pref->lval = atol(ChrPtr(Pref->Val)); + Pref->decoded = 1; } + return Ret; +} - 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); } -void set_PREF_YESNO(const char *key, size_t keylen, int value, int save_to_server) +int get_PREF_YESNO(const char *key, size_t keylen, int *value, int Default) { - StrBuf *val; - if (get_PREFERENCE(key, keylen, &val)) { - StrBufPrintf(val, "%s", (value)?"yes":"no"); + 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 { - val = NewStrBuf(); - StrBufPrintf(val, "%s", (value)?"yes":"no"); - set_PREFERENCE(key, keylen, val, save_to_server); + *value = Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0; + Pref->decoded = 1; } + return Ret; } -StrBuf *get_ROOM_PREFS(const char *key, size_t keylen) +void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_server) { - StrBuf *pref_name, *pref_value; - - pref_name = NewStrBuf (); - StrBufPrintf(pref_name, "%s %s", key, WC->wc_roomname); - get_pref(pref_name, &pref_value); + 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 pref_value; + + return Ret; } -void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_server) +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 = NewStrBuf (); - StrBufPrintf(pref_name, "%s %s", key, WC->wc_roomname); - set_PREFERENCE(ChrPtr(pref_name), StrLength(pref_name), value, save_to_server); + 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; } -/** - * \brief display form for changing your preferences and settings - */ -void display_preferences(void) -{ - output_headers(1, 1, 1, 0, 0, 0); - StrBuf *ebuf = NULL; - int i; - long DayEnd, DayStart, WeekStart; - int UseSig, ShowEmptyFloors; - int time_format; - time_t tt; - struct tm tm; - char daylabel[32]; - StrBuf *Buf; - StrBuf *Signature; - - time_format = get_time_format_cached (); - - wprintf("
\n"); - wprintf("
"); - wprintf(_("Preferences and settings")); - wprintf("
"); - - wprintf("
"); - - /** begin form */ - wprintf("
\n"); - wprintf("\n", WC->nonce); - - /** begin table */ - wprintf("\n"); - - /** - * Room list view - */ - get_preference("roomlistview", &Buf); - wprintf("\n"); - - /** - * Time hour format - */ - - wprintf("\n"); - - /** - * Calendar day view -- day start time - */ - get_pref_long("daystart", &DayStart, 8); - - wprintf("\n"); + set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL); + FreeStrBuf(&pref_name); +} - /** - * Calendar day view -- day end time - */ - get_pref_long("dayend", &DayEnd, 17); - wprintf("\n"); - - /** - * Day of week to begin calendar month view - */ - get_pref_long("weekstart", &WeekStart, 17); - wprintf("\n"); - - /** - * Signature - */ - get_pref_yesno("use_sig", &UseSig, 0); - wprintf("\n"); - - wprintf(" " - ); - - /** Character set to assume is in use for improperly encoded headers */ - if (!get_preference("default_header_charset", &Buf)) { - Buf = NewStrBuf(); - StrBufPrintf(Buf, "%s", "UTF-8"); - set_preference("default_header_charset", Buf, 0); - } - wprintf(""); - - /** - * Show empty floors? - */ - - get_pref_yesno("emptyfloors", &ShowEmptyFloors, 0); - wprintf("\n"); - - /** end table */ - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("roomlistview"))); - wprintf(""); - - wprintf(""); - wprintf(_("Tree (folders) view")); - wprintf("   "); - - wprintf(""); - wprintf(_("Table (rooms) view")); - wprintf("\n"); - - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("calhourformat"))); - wprintf(""); - - wprintf(""); - wprintf(_("12 hour (am/pm)")); - wprintf("   "); - - wprintf(""); - wprintf(_("24 hour")); - wprintf("\n"); - - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("daystart"))); - wprintf(""); - - wprintf("\n"); - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("dayend"))); - wprintf(""); +long get_ROOM_PREFS_LONG(const char *key, size_t keylen, long *value, long Default) +{ + Preference *Pref; + int Ret; - wprintf("\n"); - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("weekstart"))); - wprintf(""); - - wprintf("\n"); - wprintf("
"); - wprintf(_("Attach signature to email messages?")); - wprintf(""); - - wprintf(" " - ); - - wprintf(PrefGetLocalStr(HKEY("use_sig"))); - - wprintf(""); - wprintf(_("No signature")); - wprintf(" ,  \n"); - - wprintf(""); - wprintf(PrefGetLocalStr(HKEY("signature"))); - wprintf("
" - "
" - "
" - ); - - wprintf("\n"); - - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("default_header_charset"))); - wprintf(""); - wprintf(""); - wprintf("
"); - wprintf(PrefGetLocalStr(HKEY("emptyfloors"))); - wprintf(""); - - wprintf(""); - wprintf(_("Yes")); - wprintf("   "); - - wprintf(""); - wprintf(_("No")); - wprintf("\n"); - - wprintf("
\n"); - - /** submit buttons */ - wprintf("
"); - wprintf("" - " " - "\n", - _("Change"), - _("Cancel") - ); - wprintf("
\n"); - - /** end form */ - wprintf("
\n"); - wprintf("
\n"); - wDumpContent(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); -/* - * Offer to make any page the user's "start page." - */ -void offer_start_page(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) { - wprintf("this_page); - wprintf("\">"); - wprintf(_("Make this my start page")); - wprintf(""); -#ifdef TECH_PREVIEW - wprintf("
wc_roomname); - wprintf("\" title=\"RSS 2.0 feed for "); - escputs(WC->wc_roomname); - wprintf("\">\"RSS\"\n"); -#endif + 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); +} -/* - * Change the user's start page - */ -void change_start_page(void) { - if (bstr("startpage") == NULL) { - safestrncpy(WC->ImportantMessage, - _("You no longer have a start page selected."), - sizeof WC->ImportantMessage); - display_main_menu(); - return; +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; + } } - - set_preference("startpage", NewStrBufPlain(bstr("startpage"), -1), 1); - - output_headers(1, 1, 0, 0, 0, 0); - do_template("newstartpage", NULL); - wDumpContent(1); + WCC->hash_prefs = Tmp; + DeleteHashPos(&It); } - -/** - * \brief Commit new preferences and settings +/* + * Commit new preferences and settings */ void set_preferences(void) -{ - long fmt; - StrBuf *buf, *encBuf; - int *time_format_cache; - - time_format_cache = &(WC->time_format_cache); - - if (!havebstr("change_button")) { - safestrncpy(WC->ImportantMessage, - _("Cancelled. No settings were changed."), - sizeof WC->ImportantMessage); - display_main_menu(); - return; - } - - /** - * Set the last argument to 1 only for the final setting, so - * we don't send the prefs file to the server repeatedly - */ - set_preference("roomlistview", NewStrBufPlain(bstr("roomlistview"), -1), 0); - fmt = lbstr("calhourformat"); - set_pref_long("calhourformat", fmt, 0); - if (fmt == 24) - *time_format_cache = WC_TIMEFORMAT_24; - else - *time_format_cache = WC_TIMEFORMAT_AMPM; - - set_pref_long("weekstart", lbstr("weekstart"), 0); - set_pref_yesno("use_sig", yesbstr("use_sig"), 0); - set_pref_long("daystart", lbstr("daystart"), 0); - set_pref_long("dayend", lbstr("dayend"), 0); - set_preference("default_header_charset", NewStrBufPlain(bstr("default_header_charset"), -1), 0); - set_preference("emptyfloors", NewStrBufPlain(bstr("emptyfloors"), -1), 0); - set_preference("defaultfrom", NewStrBufDup(sbstr("defaultfrom")), 0); - set_preference("defaultname", NewStrBufDup(sbstr("defaultname")), 0); - set_preference("defaulthandle", NewStrBufDup(sbstr("defaulthandle")), 0); - - - buf = NewStrBufPlain(bstr("signature"), -1); - encBuf = NewStrBuf(); - StrBufEUid_escapize(encBuf, buf); - set_preference("signature", encBuf, 1); - FreeStrBuf(&buf); - +{ + if (!havebstr("change_button")) { + AppendImportantMessage(_("Cancelled. No settings were changed."), -1); + display_main_menu(); + return; + } + GetPreferences(WC->hash_prefs); display_main_menu(); } -#define PRF_STRING 1 -#define PRF_INT 2 -#define PRF_QP_STRING 3 -#define PRF_YESNO 4 - - -void tmplput_CFG_Value(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +void tmplput_CFG_Value(StrBuf *Target, WCTemplputParams *TP) { - StrBuf *Setting; - if (get_PREFERENCE(Tokens->Params[0]->Start, - Tokens->Params[0]->len, - &Setting)) - StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Setting, 1); + 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, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +void tmplput_CFG_Descr(StrBuf *Target, WCTemplputParams *TP) { const char *SettingStr; - SettingStr = PrefGetLocalStr(Tokens->Params[0]->Start, - Tokens->Params[0]->len); + SettingStr = PrefGetLocalStr(TKEY(0)); if (SettingStr != NULL) StrBufAppendBufPlain(Target, SettingStr, -1, 0); } - - -void CfgZoneTempl(StrBuf *TemplBuffer, void *vContext, WCTemplateToken *Token) +void tmplput_CFG_RoomValueLong(StrBuf *Target, WCTemplputParams *TP) { - StrBuf *Zone = (StrBuf*) vContext; + long lvalue; + long defval = 0; - SVPutBuf("ZONENAME", Zone, 1); + 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(WCTemplateToken *Tokens, void *Context, int ContextType) +int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP) { StrBuf *Pref; - if (!get_PREFERENCE(Tokens->Params[2]->Start, - Tokens->Params[2]->len, - &Pref)) + if (!get_PREFERENCE(TKEY(2), &Pref)) return 0; - if (Tokens->nParameters == 3) { + if (!HAVE_PARAM(3)) { return 1; } - else if (Tokens->Params[3]->Type == TYPE_STR) - return ((Tokens->Params[3]->len == StrLength(Pref)) && - (strcmp(Tokens->Params[3]->Start, ChrPtr(Pref)) == 0)); + 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 (StrTol(Pref) == Tokens->Params[3]->lvalue); + return 1; } -HashList *GetGVEAHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) + +/******************************************************************************** + * 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 (ChrPtr(Rcp)[0] == '1') { + if (GetServerStatus(Rcp, NULL) == 1) { FlushStrBuf(Rcp); List = NewHash(1, NULL); while (!Done && (StrBuf_ServGetln(Rcp)>=0)) { @@ -785,9 +1051,18 @@ HashList *GetGVEAHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void * Done = 1; } else { + VEA = (ValidEmailAddress*) malloc(sizeof(ValidEmailAddress)); i = snprintf(N, sizeof(N), "%d", n); StrBufTrim(Rcp); - Put(List, N, i, Rcp, HFreeStrBuf); + 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++; @@ -801,7 +1076,7 @@ void DeleteGVEAHash(HashList **KillMe) DeleteHash(KillMe); } -HashList *GetGVSNHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +HashList *GetGVSNHash(StrBuf *Target, WCTemplputParams *TP) { StrBuf *Rcp; HashList *List = NULL; @@ -812,7 +1087,7 @@ HashList *GetGVSNHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void * Rcp = NewStrBuf(); serv_puts("GVSN"); StrBuf_ServGetln(Rcp); - if (ChrPtr(Rcp)[0] == '1') { + if (GetServerStatus(Rcp, NULL) == 1) { FlushStrBuf(Rcp); List = NewHash(1, NULL); while (!Done && (StrBuf_ServGetln(Rcp)>=0)) { @@ -839,39 +1114,169 @@ void DeleteGVSNHash(HashList **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("Hdr->this_page)); + wc_printf("\">"); + wc_printf(_("Make this my start page")); + wc_printf(""); + }; +} + + +/* + * 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) { - WebcitAddUrlHandler(HKEY("display_preferences"), display_preferences, 0); - WebcitAddUrlHandler(HKEY("set_preferences"), set_preferences, 0); - WebcitAddUrlHandler(HKEY("change_start_page"), change_start_page, 0); + RegisterCTX(CTX_VEA); - RegisterPreference("roomlistview",_("Room list view"),PRF_STRING); - RegisterPreference("calhourformat",_("Time format"), PRF_INT); - RegisterPreference("daystart", _("Calendar day view begins at:"), PRF_INT); - RegisterPreference("dayend", _("Calendar day view ends at:"), PRF_INT); - RegisterPreference("weekstart",_("Week starts on:"), PRF_INT); + WebcitAddUrlHandler(HKEY("set_preferences"), "", 0, set_preferences, 0); + WebcitAddUrlHandler(HKEY("change_start_page"), "", 0, change_start_page, 0); - RegisterPreference("use_sig",_("Attach signature to email messages?"), PRF_YESNO); - RegisterPreference("signature",_("Use this signature:"),PRF_QP_STRING); - RegisterPreference("default_header_charset", _("Default character set for email headers:") ,PRF_STRING); - RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO); - RegisterPreference("defaultfrom", _("Prefered Email Address"), PRF_STRING); - RegisterPreference("defaultname", _("Prefered Email Sendername"), PRF_STRING); - RegisterPreference("defaulthandle", _("Prefered Name for posting messages"), PRF_STRING); + 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:VALUE", 1, 2, tmplput_CFG_Value, CTX_NONE); - RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_NONE); - RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, CfgZoneTempl, NULL, CTX_PREF, CTX_NONE); + RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, NULL, CTX_NONE); - RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference, 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_STRBUF, CTX_NONE); + 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); + 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); } -/*@}*/