X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fpreferences.c;h=ae381cc1e5b45afe68b9246c695f154a51b872a9;hb=HEAD;hp=aeca0028a1ee73567dd0e473e72d48f909d9a555;hpb=a3ba94ad306d781296c53012f732f3a910015263;p=citadel.git diff --git a/webcit/preferences.c b/webcit/preferences.c index aeca0028a..e438b0318 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -1,18 +1,26 @@ /* - * $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; @@ -20,14 +28,16 @@ typedef struct _PrefDef { } 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) { @@ -46,16 +56,17 @@ void DestroyPreference(void *vPref) free(Pref); } + void _RegisterPreference(const char *Setting, long SettingLen, const char *PrefStr, - long Type, + 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); @@ -106,15 +117,17 @@ void GetPrefTypes(HashList *List) { PrefType = (PrefDef*) vPrefDef; Pref->Type = PrefType; + Pref->eFlatPrefType = Pref->Type->eType; - lprintf(1, "Loading [%s]with type [%ld] [\"%s\"]\n", + syslog(LOG_DEBUG, "Loading [%s]with type [%d] [\"%s\"]\n", ChrPtr(Pref->Key), - Pref->Type->Type, + Pref->Type->eType, ChrPtr(Pref->Val)); - switch (Pref->Type->Type) + switch (Pref->Type->eType) { - + case PRF_UNSET: /* WHUT? */ + break; case PRF_STRING: break; case PRF_INT: @@ -134,7 +147,7 @@ void GetPrefTypes(HashList *List) if (PrefType->OnLoad != NULL){ - lprintf(1, "Loading with: -> %s(\"%s\", %ld)\n", + syslog(LOG_DEBUG, "Loading with: -> %s(\"%s\", %ld)\n", ChrPtr(PrefType->OnLoadName), ChrPtr(Pref->Val), Pref->lval); @@ -152,7 +165,8 @@ void ParsePref(HashList **List, StrBuf *ReadBuf) Preference *LastData = NULL; while (!Done) { - StrBuf_ServGetln(ReadBuf); + if (StrBuf_ServGetln(ReadBuf) < 0) + break; if ( (StrLength(ReadBuf)==3) && !strcmp(ChrPtr(ReadBuf), "000")) { Done = 1; @@ -170,6 +184,20 @@ void ParsePref(HashList **List, StrBuf *ReadBuf) 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, @@ -180,7 +208,7 @@ 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; @@ -218,10 +246,8 @@ void load_preferences(void) serv_puts("subj|__ WebCit Preferences __"); serv_puts("000"); } - while (!Done && - StrBuf_ServGetln(ReadBuf)) { - if ( (StrLength(ReadBuf)==3) && - !strcmp(ChrPtr(ReadBuf), "000")) { + while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) { + if ( (StrLength(ReadBuf)==3) && !strcmp(ChrPtr(ReadBuf), "000")) { Done = 1; break; } @@ -232,9 +258,11 @@ void load_preferences(void) 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(&WCC->hash_prefs, ReadBuf); @@ -252,8 +280,9 @@ void load_preferences(void) FlushFolder(&Room); } + /* - * Goto the user's configuration room, creating it if necessary. + * 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) @@ -312,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; @@ -323,16 +354,17 @@ 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) { @@ -350,8 +382,21 @@ void save_preferences(void) return; /* oh well. */ } -//void do_change_view(int newview) { + /* 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); @@ -359,10 +404,8 @@ void save_preferences(void) serv_puts("subj|__ WebCit Preferences __"); serv_puts("000"); } - while (!Done && - StrBuf_ServGetln(ReadBuf)) { - if ( (StrLength(ReadBuf)==3) && - !strcmp(ChrPtr(ReadBuf), "000")) { + while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) { + if ( (StrLength(ReadBuf)==3) && !strcmp(ChrPtr(ReadBuf), "000")) { Done = 1; break; } @@ -394,12 +437,13 @@ void save_preferences(void) 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) { @@ -430,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, @@ -447,6 +554,7 @@ void set_preference_backend(const char *key, size_t keylen, { wcsession *WCC = WC; void *vPrefDef; + void *vPrefB; Preference *Pref; Pref = (Preference*) malloc(sizeof(Preference)); @@ -461,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; @@ -497,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: @@ -527,6 +638,13 @@ void set_preference_backend(const char *key, size_t keylen, 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; @@ -708,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), @@ -752,15 +871,13 @@ void GetPreferences(HashList *Setting) } -/** - * \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; } @@ -777,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; @@ -854,11 +972,20 @@ int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP) 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) @@ -876,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; @@ -883,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); @@ -897,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++; @@ -954,15 +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) { - wc_printf("Hdr->this_page)); - wc_printf("\">"); - wc_printf(_("Make this my start page")); - wc_printf(""); + if (WC->logged_in) { + wc_printf("Hdr->this_page)); + wc_printf("\">"); + wc_printf(_("Make this my start page")); + wc_printf(""); + }; } @@ -971,29 +1136,51 @@ 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); } @@ -1001,6 +1188,7 @@ void change_start_page(void) void LoadStartpage(StrBuf *URL, long lvalue) { const char *pch; + void *vHandler; pch = strchr(ChrPtr(URL), '?'); if (pch == NULL) { /* purge the sins of the past... */ @@ -1010,6 +1198,13 @@ void LoadStartpage(StrBuf *URL, long lvalue) 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; + } } @@ -1017,6 +1212,8 @@ 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); @@ -1029,12 +1226,15 @@ InitModule_PREFERENCES 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); @@ -1080,7 +1280,3 @@ SessionDestroyModule_PREFERENCES { DeleteHash(&sess->hash_prefs); } - - - -/*@}*/