X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fpreferences.c;h=ae381cc1e5b45afe68b9246c695f154a51b872a9;hb=HEAD;hp=ad55f0483296f5e6ba9c28c38f85dc1d9c5987e9;hpb=04cb9dabd731218dfde1e646b0bf44938bbeefb4;p=citadel.git diff --git a/webcit/preferences.c b/webcit/preferences.c index ad55f0483..e438b0318 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -1,37 +1,49 @@ /* - * $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 _PrefDef { - long Type; + ePrefType eType; StrBuf *Setting; const char *PrefStr; PrefEvalFunc OnLoad; + StrBuf *OnLoadName; } PrefDef; typedef struct _Preference { + PrefDef *Type; + ePrefType eFlatPrefType; + StrBuf *Key; StrBuf *Val; - PrefDef *Type; long lval; long decoded; StrBuf *DeQPed; -}Preference; +} Preference; void DestroyPrefDef(void *vPrefDef) { PrefDef *Prefdef = (PrefDef*) vPrefDef; FreeStrBuf(&Prefdef->Setting); + FreeStrBuf(&Prefdef->OnLoadName); free(Prefdef); } @@ -44,16 +56,23 @@ void DestroyPreference(void *vPref) free(Pref); } -void RegisterPreference(const char *Setting, long SettingLen, - const char *PrefStr, - long Type, - PrefEvalFunc OnLoad) + +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->Type = Type; + 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); } @@ -86,43 +105,99 @@ void GetPrefTypes(HashList *List) const char *Key; void *vSetting; void *vPrefDef; - Preference *Setting; + Preference *Pref; PrefDef *PrefType; It = GetNewHashPos(List, 0); while (GetNextHashPos(List, It, &len, &Key, &vSetting)) { - Setting = (Preference*) vSetting; - if (GetHash(PreferenceHooks, SKEY(Setting->Key), &vPrefDef) && + Pref = (Preference*) vSetting; + if (GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && (vPrefDef != NULL)) { PrefType = (PrefDef*) vPrefDef; - Setting->Type = PrefType; - if (PrefType->OnLoad != NULL) - PrefType->OnLoad(Setting->Val, Setting->lval); + 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) { - StrBuf *Key; + int Done = 0; Preference *Data = NULL; Preference *LastData = NULL; - Key = NewStrBuf(); - while (StrBuf_ServGetln(ReadBuf), - strcmp(ChrPtr(ReadBuf), "000")) - { + while (!Done) { + if (StrBuf_ServGetln(ReadBuf) < 0) + break; + if ( (StrLength(ReadBuf)==3) && + !strcmp(ChrPtr(ReadBuf), "000")) { + Done = 1; + break; + } + if ((ChrPtr(ReadBuf)[0] == ' ') && - (Data != NULL)) { - StrBufAppendBuf(Data->Val, ReadBuf, 1); + (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, @@ -133,11 +208,12 @@ void ParsePref(HashList **List, StrBuf *ReadBuf) else { StrBufTrim(ReadBuf); - lprintf(1, "ignoring spurious preference line: [%s]\n", + syslog(LOG_INFO, "ignoring spurious preference line: [%s]\n", ChrPtr(ReadBuf)); DestroyPreference(Data); LastData = NULL; } + Data = NULL; } } GetPrefTypes(*List); @@ -149,66 +225,88 @@ void ParsePref(HashList **List, StrBuf *ReadBuf) */ void load_preferences(void) { + folder Room; + wcsession *WCC = WC; + int Done = 0; StrBuf *ReadBuf; - char buf[SIZ]; long msgnum = 0L; - if (!goto_config_room()) - 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. */ + } - ReadBuf = NewStrBuf(); serv_puts("MSGS ALL|0|1"); 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); StrBuf_ServGetln(ReadBuf); if (GetServerStatus(ReadBuf, NULL) == 1) { - while (StrBuf_ServGetln(ReadBuf), - (strcmp(ChrPtr(ReadBuf), "text") && - strcmp(ChrPtr(ReadBuf), "000"))) { + while ( (StrBuf_ServGetln(ReadBuf) >= 0) + && (strcmp(ChrPtr(ReadBuf), "text") + && strcmp(ChrPtr(ReadBuf), "000")) + ) { + /* flush */ } if (!strcmp(ChrPtr(ReadBuf), "text")) { - ParsePref(&WC->hash_prefs, ReadBuf); + ParsePref(&WCC->hash_prefs, ReadBuf); } } } /* Go back to the room we're supposed to be in */ - serv_printf("GOTO %s", ChrPtr(WC->wc_roomname)); - StrBuf_ServGetln(ReadBuf); - GetServerStatus(ReadBuf, NULL); + 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); } void WritePrefsToServer(HashList *Hash) { + wcsession *WCC = WC; long len; HashPos *HashPos; void *vPref; @@ -216,7 +314,7 @@ void WritePrefsToServer(HashList *Hash) Preference *Pref; StrBuf *SubBuf = NULL; - Hash = WC->hash_prefs; + Hash = WCC->hash_prefs; #ifdef DBG_PREFS_HASH dbg_PrintHash(Hash, PrintPref, NULL); #endif @@ -232,7 +330,7 @@ void WritePrefsToServer(HashList *Hash) int n = 0; size_t offset, nchars; if (SubBuf == NULL) - SubBuf = NewStrBuf(); + SubBuf = NewStrBufPlain(NULL, SIZ); nchars = 1; offset = 0; while (nchars > 0) { @@ -243,10 +341,12 @@ void WritePrefsToServer(HashList *Hash) nchars = StrBufSub(SubBuf, Pref->Val, offset, nchars); - if (n == 0) + if (n == 0) { serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(SubBuf)); - else + } + else { serv_printf(" %s", ChrPtr(SubBuf)); + } offset += nchars; nchars = StrLength(Pref->Val) - offset; @@ -254,58 +354,96 @@ void WritePrefsToServer(HashList *Hash) } } - else + else { serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(Pref->Val)); + } } FreeStrBuf(&SubBuf); DeleteHashPos(&HashPos); } -/** - * \brief save the modifications +/* + * save the modifications */ void save_preferences(void) { - char buf[SIZ]; + 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') { + StrBuf_ServGetln(ReadBuf); + if (GetServerStatus(ReadBuf, NULL) == 4) { - WritePrefsToServer(WC->hash_prefs); + WritePrefsToServer(WCC->hash_prefs); serv_puts(""); serv_puts("000"); } /** Go back to the room we're supposed to be in */ - serv_printf("GOTO %s", ChrPtr(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_pref_backend(const char *key, size_t keylen, Preference **Pref) { @@ -336,13 +474,76 @@ int get_PREFERENCE(const char *key, size_t keylen, StrBuf **value) return Ret; } -/** - * \brief Write a key into the webcit preferences database for this user +/* + * 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 * - * \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 + * 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, @@ -351,7 +552,9 @@ void set_preference_backend(const char *key, size_t keylen, int save_to_server, PrefDef *PrefType) { + wcsession *WCC = WC; void *vPrefDef; + void *vPrefB; Preference *Pref; Pref = (Preference*) malloc(sizeof(Preference)); @@ -366,11 +569,13 @@ void set_preference_backend(const char *key, size_t keylen, if (PrefType != NULL) { Pref->Type = PrefType; - if (Pref->Type->Type != lPrefType) - lprintf(1, "warning: saving preference with wrong type [%s] %ld != %ld \n", - key, Pref->Type->Type, lPrefType); - switch (Pref->Type->Type) + 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; @@ -402,6 +607,7 @@ void set_preference_backend(const char *key, size_t keylen, Pref->Type->OnLoad(Pref->Val, Pref->lval); } else { + Pref->eFlatPrefType = lPrefType; switch (lPrefType) { case PRF_STRING: @@ -432,9 +638,16 @@ void set_preference_backend(const char *key, size_t keylen, break; } } - Put(WC->hash_prefs, key, keylen, Pref, DestroyPreference); + + 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) WC->SavePrefsToServer = 1; + if (save_to_server) WCC->SavePrefsToServer = 1; } void set_PREFERENCE(const char *key, size_t keylen, StrBuf *value, int save_to_server) @@ -493,19 +706,78 @@ void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_serv 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) +int get_room_prefs_backend(const char *key, size_t keylen, + Preference **Pref) { StrBuf *pref_name; int Ret; - pref_name = NewStrBuf (); - StrBufPrintf(pref_name, "%s:%s", key, ChrPtr(WC->wc_roomname)); + 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; @@ -524,8 +796,10 @@ void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_s { StrBuf *pref_name; - pref_name = NewStrBuf (); - StrBufPrintf(pref_name, "%s:%s", key, ChrPtr(WC->wc_roomname)); + 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); } @@ -552,7 +826,8 @@ void GetPreferences(HashList *Setting) if (!HaveBstr(SKEY(PrefType->Setting))) continue; - switch (PrefType->Type) { + switch (PrefType->eType) { + case PRF_UNSET: case PRF_STRING: Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting))); set_preference_backend(SKEY(PrefType->Setting), @@ -592,18 +867,17 @@ void GetPreferences(HashList *Setting) } } WCC->hash_prefs = Tmp; + DeleteHashPos(&It); } -/** - * \brief Commit new preferences and settings +/* + * Commit new preferences and settings */ void set_preferences(void) { if (!havebstr("change_button")) { - safestrncpy(WC->ImportantMessage, - _("Cancelled. No settings were changed."), - sizeof WC->ImportantMessage); + AppendImportantMessage(_("Cancelled. No settings were changed."), -1); display_main_menu(); return; } @@ -620,8 +894,9 @@ void tmplput_CFG_Value(StrBuf *Target, WCTemplputParams *TP) if (Pref->Type == NULL) { StrBufAppendTemplate(Target, TP, Pref->Val, 1); } - switch (Pref->Type->Type) + switch (Pref->Type->eType) { + case PRF_UNSET: /* default to string... */ case PRF_STRING: StrBufAppendTemplate(Target, TP, Pref->Val, 1); break; @@ -662,6 +937,16 @@ void tmplput_CFG_Descr(StrBuf *Target, WCTemplputParams *TP) 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)); @@ -676,12 +961,6 @@ int ConditionalHasRoomPreference(StrBuf *Target, WCTemplputParams *TP) return 0; } -void CfgZoneTempl(StrBuf *TemplBuffer, WCTemplputParams *TP) -{ - StrBuf *Zone = (StrBuf*) CTX; - - SVPutBuf("ZONENAME", Zone, 1); -} int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP) { @@ -690,14 +969,23 @@ int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP) if (!get_PREFERENCE(TKEY(2), &Pref)) return 0; - if (TP->Tokens->nParameters == 3) { + if (!HAVE_PARAM(3)) { return 1; } - else if (TP->Tokens->Params[3]->Type == TYPE_STR) - return ((TP->Tokens->Params[3]->len == StrLength(Pref)) && - (strcmp(TP->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 - return (StrTol(Pref) == TP->Tokens->Params[3]->lvalue); + { + 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) @@ -715,6 +1003,28 @@ int ConditionalHasPreference(StrBuf *Target, WCTemplputParams *TP) /******************************************************************************** * 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; @@ -722,7 +1032,12 @@ HashList *GetGVEAHash(StrBuf *Target, WCTemplputParams *TP) 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); @@ -736,9 +1051,18 @@ HashList *GetGVEAHash(StrBuf *Target, WCTemplputParams *TP) 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++; @@ -793,22 +1117,17 @@ void DeleteGVSNHash(HashList **KillMe) /* - * Offer to make any page the user's "start page." + * Offer to make any page the user's "start page" (only if logged in) */ void offer_start_page(StrBuf *Target, WCTemplputParams *TP) { - 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(ChrPtr(WC->wc_roomname)); - wprintf("\">\"RSS\"\n"); -#endif + if (WC->logged_in) { + wc_printf("Hdr->this_page)); + wc_printf("\">"); + wc_printf(_("Make this my start page")); + wc_printf(""); + }; } @@ -817,55 +1136,147 @@ void offer_start_page(StrBuf *Target, WCTemplputParams *TP) */ void change_start_page(void) { - if (!havebstr("startpage")) { + 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); - safestrncpy(WC->ImportantMessage, - _("You no longer have a start page selected."), - sizeof( WC->ImportantMessage)); + 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(sbstr("startpage")), + NewStrBufDup(pStartPage), PRF_STRING, 1, NULL); output_headers(1, 1, 0, 0, 0, 0); - do_template("newstartpage", NULL); + 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("set_preferences"), set_preferences, 0); - WebcitAddUrlHandler(HKEY("change_start_page"), change_start_page, 0); + 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, CTX_NONE); - RegisterNamespace("PREF:ROOM:VALUE", 1, 2, tmplput_CFG_RoomValue, 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, IT_NOFLAG); + 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(HKEY("COND:PREF"), 4, ConditionalPreference, CTX_NONE); - RegisterConditional(HKEY("COND:PREF:SET"), 4, ConditionalHasPreference, CTX_NONE); - RegisterConditional(HKEY("COND:ROOM:SET"), 4, ConditionalHasRoomPreference, 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, IT_NOFLAG); + 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); +}