3 * Manage user preferences with a little help from the Citadel server.
5 * Copyright (c) 1996-2012 by the citadel.org team
7 * This program is open source software. You can redistribute it and/or
8 * modify it under the terms of the GNU General Public License, version 3.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include "webserver.h"
20 HashList *PreferenceHooks;
21 extern HashList *HandlerHash;
23 typedef struct _PrefDef {
31 typedef struct _Preference {
33 ePrefType eFlatPrefType;
43 void DestroyPrefDef(void *vPrefDef) {
44 PrefDef *Prefdef = (PrefDef *) vPrefDef;
45 FreeStrBuf(&Prefdef->Setting);
46 FreeStrBuf(&Prefdef->OnLoadName);
50 void DestroyPreference(void *vPref) {
51 Preference *Pref = (Preference *) vPref;
52 FreeStrBuf(&Pref->Key);
53 FreeStrBuf(&Pref->Val);
54 FreeStrBuf(&Pref->DeQPed);
59 void _RegisterPreference(const char *Setting, long SettingLen,
60 const char *PrefStr, ePrefType Type, PrefEvalFunc OnLoad, const char *OnLoadName) {
61 PrefDef *Newpref = (PrefDef *) malloc(sizeof(PrefDef));
62 Newpref->Setting = NewStrBufPlain(Setting, SettingLen);
63 Newpref->PrefStr = PrefStr;
64 Newpref->eType = Type;
65 Newpref->OnLoad = OnLoad;
66 if (Newpref->OnLoad != NULL) {
67 Newpref->OnLoadName = NewStrBufPlain(OnLoadName, -1);
70 Newpref->OnLoadName = NULL;
71 Put(PreferenceHooks, Setting, SettingLen, Newpref, DestroyPrefDef);
74 const char *PrefGetLocalStr(const char *Setting, long len) {
76 if (GetHash(PreferenceHooks, Setting, len, &hash_value) != 0) {
77 PrefDef *Newpref = (PrefDef *) hash_value;
78 return _(Newpref->PrefStr);
85 inline const char *PrintPref(void *vPref) {
86 Preference *Pref = (Preference *) vPref;
87 if (Pref->DeQPed != NULL)
88 return ChrPtr(Pref->DeQPed);
90 return ChrPtr(Pref->Val);
94 void GetPrefTypes(HashList * List) {
103 It = GetNewHashPos(List, 0);
104 while (GetNextHashPos(List, It, &len, &Key, &vSetting)) {
105 Pref = (Preference *) vSetting;
106 if (GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && (vPrefDef != NULL)) {
107 PrefType = (PrefDef *) vPrefDef;
108 Pref->Type = PrefType;
109 Pref->eFlatPrefType = Pref->Type->eType;
111 syslog(LOG_DEBUG, "Loading [%s]with type [%d] [\"%s\"]\n",
112 ChrPtr(Pref->Key), Pref->Type->eType, ChrPtr(Pref->Val));
114 switch (Pref->Type->eType) {
115 case PRF_UNSET: /* WHUT? */
120 Pref->lval = StrTol(Pref->Val);
124 Pref->DeQPed = NewStrBufPlain(NULL, StrLength(Pref->Val));
125 StrBufEUid_unescapize(Pref->DeQPed, Pref->Val);
129 Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
134 if (PrefType->OnLoad != NULL) {
136 syslog(LOG_DEBUG, "Loading with: -> %s(\"%s\", %ld)\n",
137 ChrPtr(PrefType->OnLoadName), ChrPtr(Pref->Val), Pref->lval);
138 PrefType->OnLoad(Pref->Val, Pref->lval);
145 void ParsePref(HashList ** List, StrBuf * ReadBuf) {
147 Preference *Data = NULL;
148 Preference *LastData = NULL;
151 if (StrBuf_ServGetln(ReadBuf) < 0)
153 if ((StrLength(ReadBuf) == 3) && !strcmp(ChrPtr(ReadBuf), "000")) {
158 if ((ChrPtr(ReadBuf)[0] == ' ') && (LastData != NULL)) {
159 StrBufAppendBuf(LastData->Val, ReadBuf, 1);
162 LastData = Data = malloc(sizeof(Preference));
163 memset(Data, 0, sizeof(Preference));
164 Data->Key = NewStrBuf();
165 Data->Val = NewStrBuf();
166 StrBufExtract_token(Data->Key, ReadBuf, 0, '|');
167 StrBufExtract_token(Data->Val, ReadBuf, 1, '|');
169 /***************** BEGIN VILE SLEAZY HACK ************************/
171 /* some users might still have this start page configured, which now breaks */
173 if ((!strcasecmp(ChrPtr(Data->Key), "startpage"))
174 && (!strcasecmp(ChrPtr(Data->Val), "/do_template?template=summary_page"))
176 FreeStrBuf(&Data->Val);
177 Data->Val = NewStrBufPlain(HKEY("/summary"));
180 /******************* END VILE SLEAZY HACK ************************/
182 if (!IsEmptyStr(ChrPtr(Data->Key))) {
183 Put(*List, SKEY(Data->Key), Data, DestroyPreference);
187 syslog(LOG_INFO, "ignoring spurious preference line: [%s]\n", ChrPtr(ReadBuf));
188 DestroyPreference(Data);
199 * display preferences dialog
201 void load_preferences(void) {
208 memset(&Room, 0, sizeof(folder));
209 ReadBuf = NewStrBufPlain(NULL, SIZ * 4);
210 if (goto_config_room(ReadBuf, &Room) != 0) {
211 FreeStrBuf(&ReadBuf);
214 return; /* oh well. */
217 serv_puts("MSGS ALL|0|1");
218 StrBuf_ServGetln(ReadBuf);
219 if (GetServerStatus(ReadBuf, NULL) == 8) {
220 serv_puts("subj|__ WebCit Preferences __");
223 while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) {
224 if ((StrLength(ReadBuf) == 3) && !strcmp(ChrPtr(ReadBuf), "000")) {
228 msgnum = StrTol(ReadBuf);
232 serv_printf("MSG0 %ld", msgnum);
233 StrBuf_ServGetln(ReadBuf);
234 if (GetServerStatus(ReadBuf, NULL) == 1) {
235 while ((StrBuf_ServGetln(ReadBuf) >= 0)
236 && (strcmp(ChrPtr(ReadBuf), "text")
237 && strcmp(ChrPtr(ReadBuf), "000"))
241 if (!strcmp(ChrPtr(ReadBuf), "text")) {
242 ParsePref(&WCC->hash_prefs, ReadBuf);
247 /* Go back to the room we're supposed to be in */
248 if (StrLength(WCC->CurRoom.name) > 0) {
249 serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name));
250 StrBuf_ServGetln(ReadBuf);
251 GetServerStatus(ReadBuf, NULL);
253 FreeStrBuf(&ReadBuf);
259 * Go to the user's configuration room, creating it if necessary.
260 * returns 0 on success or nonzero upon failure.
262 int goto_config_room(StrBuf * Buf, folder * Room) {
263 serv_printf("GOTO %s", USERCONFIGROOM);
264 StrBuf_ServGetln(Buf);
265 if (GetServerStatus(Buf, NULL) != 2) { /* try to create the config room if not there */
266 serv_printf("CRE8 1|%s|4|0", USERCONFIGROOM);
267 StrBuf_ServGetln(Buf);
268 GetServerStatus(Buf, NULL);
270 serv_printf("GOTO %s", USERCONFIGROOM);
271 StrBuf_ServGetln(Buf);
272 if (GetServerStatus(Buf, NULL) != 2) {
276 ParseGoto(Room, Buf);
280 void WritePrefsToServer(HashList * Hash) {
287 StrBuf *SubBuf = NULL;
289 Hash = WCC->hash_prefs;
290 #ifdef DBG_PREFS_HASH
291 dbg_PrintHash(Hash, PrintPref, NULL);
293 HashPos = GetNewHashPos(Hash, 0);
294 while (GetNextHashPos(Hash, HashPos, &len, &Key, &vPref) != 0) {
298 Pref = (Preference *) vPref;
299 nchars = StrLength(Pref->Val);
302 size_t offset, nchars;
304 SubBuf = NewStrBufPlain(NULL, SIZ);
313 nchars = StrBufSub(SubBuf, Pref->Val, offset, nchars);
316 serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(SubBuf));
319 serv_printf(" %s", ChrPtr(SubBuf));
323 nchars = StrLength(Pref->Val) - offset;
329 serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(Pref->Val));
334 DeleteHashPos(&HashPos);
338 * save the modifications
340 void save_preferences(void) {
347 ReadBuf = NewStrBuf();
348 memset(&Room, 0, sizeof(folder));
349 if (goto_config_room(ReadBuf, &Room) != 0) {
350 FreeStrBuf(&ReadBuf);
353 return; /* oh well. */
356 /* make shure the config room has the right type, else it might reject our config */
357 if (Room.view != VIEW_BBS) {
358 serv_printf("VIEW %d", VIEW_BBS);
359 StrBuf_ServGetln(ReadBuf);
360 if (GetServerStatus(ReadBuf, NULL) != 2) {
363 else if (goto_config_room(ReadBuf, &Room) != 0) {
364 FreeStrBuf(&ReadBuf);
367 return; /* oh well. */
371 serv_puts("MSGS ALL|0|1");
372 StrBuf_ServGetln(ReadBuf);
373 if (GetServerStatus(ReadBuf, NULL) == 8) {
374 serv_puts("subj|__ WebCit Preferences __");
377 while (!Done && (StrBuf_ServGetln(ReadBuf) >= 0)) {
378 if ((StrLength(ReadBuf) == 3) && !strcmp(ChrPtr(ReadBuf), "000")) {
382 msgnum = StrTol(ReadBuf);
386 serv_printf("DELE %ld", msgnum);
387 StrBuf_ServGetln(ReadBuf);
388 GetServerStatus(ReadBuf, NULL);
391 serv_printf("ENT0 1||0|1|__ WebCit Preferences __|");
392 StrBuf_ServGetln(ReadBuf);
393 if (GetServerStatus(ReadBuf, NULL) == 4) {
395 WritePrefsToServer(WCC->hash_prefs);
400 /** Go back to the room we're supposed to be in */
401 if (StrLength(WCC->CurRoom.name) > 0) {
402 serv_printf("GOTO %s", ChrPtr(WCC->CurRoom.name));
403 StrBuf_ServGetln(ReadBuf);
404 GetServerStatus(ReadBuf, NULL);
406 FreeStrBuf(&ReadBuf);
411 * query the actual setting of key in the citadel database
413 * key config key to query
414 * keylen length of the key string
415 * value StrBuf-value to the key to get
418 int get_pref_backend(const char *key, size_t keylen, Preference ** Pref) {
419 void *hash_value = NULL;
420 #ifdef DBG_PREFS_HASH
421 dbg_PrintHash(WC->hash_prefs, PrintPref, NULL);
423 if (GetHash(WC->hash_prefs, key, keylen, &hash_value) == 0) {
428 *Pref = (Preference *) hash_value;
433 int get_PREFERENCE(const char *key, size_t keylen, StrBuf ** value) {
437 Ret = get_pref_backend(key, keylen, &Pref);
446 * Write a key into the webcit preferences database for this user
448 * key key whichs value is to be modified
449 * keylen length of the key string
451 * save_to_server 1 = flush all data to the server, 0 = cache it for now
453 long compare_preference(const Preference * PrefA, const Preference * PrefB) {
454 ePrefType TypeA, TypeB;
456 if (PrefA->Type != NULL) {
457 TypeA = PrefA->Type->eType;
460 TypeA = PrefA->eFlatPrefType;
463 if (PrefB->Type != NULL) {
464 TypeB = PrefB->Type->eType;
467 TypeB = PrefB->eFlatPrefType;
470 if ((TypeA != PRF_UNSET)
471 && (TypeB != PRF_UNSET)
477 else { /* (PrefA->Type < PrefB->Type) */
482 if (TypeB == PRF_UNSET) {
490 return strcmp(ChrPtr(PrefA->Val), ChrPtr(PrefB->Val));
493 if (PrefA->lval == PrefB->lval)
495 else if (PrefA->lval > PrefB->lval)
500 return strcmp(ChrPtr(PrefA->DeQPed), ChrPtr(PrefB->DeQPed));
506 * Write a key into the webcit preferences database for this user
508 * key key which value is to be modified
509 * keylen length of the key string
511 * save_to_server 1 = flush all data to the server, 0 = cache it for now
513 void set_preference_backend(const char *key, size_t keylen,
514 long lvalue, StrBuf * value, long lPrefType, int save_to_server, PrefDef * PrefType) {
520 Pref = (Preference *) malloc(sizeof(Preference));
521 memset(Pref, 0, sizeof(Preference));
522 Pref->Key = NewStrBufPlain(key, keylen);
524 if ((PrefType == NULL) && GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && (vPrefDef != NULL))
525 PrefType = (PrefDef *) vPrefDef;
527 if (PrefType != NULL) {
528 Pref->Type = PrefType;
529 Pref->eFlatPrefType = PrefType->eType;
530 if (Pref->Type->eType != lPrefType)
531 syslog(LOG_WARNING, "warning: saving preference with wrong type [%s] %d != %ld \n",
532 key, Pref->Type->eType, lPrefType);
533 switch (Pref->Type->eType) {
534 case PRF_UNSET: /* default to string... */
542 if (Pref->Val == NULL)
543 Pref->Val = NewStrBufPlain(NULL, 64);
544 StrBufPrintf(Pref->Val, "%ld", lvalue);
548 Pref->DeQPed = value;
549 Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
550 StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
556 Pref->Val = NewStrBufPlain(HKEY("yes"));
558 Pref->Val = NewStrBufPlain(HKEY("no"));
562 if (Pref->Type->OnLoad != NULL)
563 Pref->Type->OnLoad(Pref->Val, Pref->lval);
566 Pref->eFlatPrefType = lPrefType;
575 if (Pref->Val == NULL)
576 Pref->Val = NewStrBufPlain(NULL, 64);
577 StrBufPrintf(Pref->Val, "%ld", lvalue);
581 Pref->DeQPed = value;
582 Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
583 StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
589 Pref->Val = NewStrBufPlain(HKEY("yes"));
591 Pref->Val = NewStrBufPlain(HKEY("no"));
597 if ((save_to_server != 0) &&
598 GetHash(WCC->hash_prefs, key, keylen, &vPrefB) && (vPrefB != NULL) && (compare_preference(Pref, vPrefB) == 0))
601 Put(WCC->hash_prefs, key, keylen, Pref, DestroyPreference);
604 WCC->SavePrefsToServer = 1;
607 void set_PREFERENCE(const char *key, size_t keylen, StrBuf * value, int save_to_server) {
608 set_preference_backend(key, keylen, 0, value, PRF_STRING, save_to_server, NULL);
611 int get_PREF_LONG(const char *key, size_t keylen, long *value, long Default) {
615 Ret = get_pref_backend(key, keylen, &Pref);
624 *value = Pref->lval = atol(ChrPtr(Pref->Val));
631 void set_PREF_LONG(const char *key, size_t keylen, long value, int save_to_server) {
632 set_preference_backend(key, keylen, value, NULL, PRF_INT, save_to_server, NULL);
635 int get_PREF_YESNO(const char *key, size_t keylen, int *value, int Default) {
639 Ret = get_pref_backend(key, keylen, &Pref);
648 *value = Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
654 void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_server) {
655 set_preference_backend(key, keylen, value, NULL, PRF_YESNO, save_to_server, NULL);
658 int get_room_prefs_backend(const char *key, size_t keylen, Preference ** Pref) {
662 pref_name = NewStrBufPlain(HKEY("ROOM:"));
663 StrBufAppendBuf(pref_name, WC->CurRoom.name, 0);
664 StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
665 StrBufAppendBufPlain(pref_name, key, keylen, 0);
666 Ret = get_pref_backend(SKEY(pref_name), Pref);
667 FreeStrBuf(&pref_name);
672 const StrBuf *get_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen) {
677 pref_name = NewStrBufPlain(HKEY("XPREF:"));
678 StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
679 StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
680 StrBufAppendBufPlain(pref_name, key, keylen, 0);
682 ret = get_pref_backend(SKEY(pref_name), &Prf);
683 FreeStrBuf(&pref_name);
691 void set_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen, StrBuf * value, int save_to_server) {
694 pref_name = NewStrBufPlain(HKEY("XPREF:"));
695 StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
696 StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
697 StrBufAppendBufPlain(pref_name, key, keylen, 0);
699 set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
700 FreeStrBuf(&pref_name);
704 long get_ROOM_PREFS_LONG(const char *key, size_t keylen, long *value, long Default) {
708 Ret = get_room_prefs_backend(key, keylen, &Pref);
718 *value = Pref->lval = atol(ChrPtr(Pref->Val));
725 StrBuf *get_ROOM_PREFS(const char *key, size_t keylen) {
729 Ret = get_room_prefs_backend(key, keylen, &Pref);
738 void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf * value, int save_to_server) {
741 pref_name = NewStrBufPlain(HKEY("ROOM:"));
742 StrBufAppendBuf(pref_name, WC->CurRoom.name, 0);
743 StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
744 StrBufAppendBufPlain(pref_name, key, keylen, 0);
745 set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
746 FreeStrBuf(&pref_name);
750 void GetPreferences(HashList * Setting) {
761 Tmp = WCC->hash_prefs;
762 WCC->hash_prefs = Setting;
764 It = GetNewHashPos(PreferenceHooks, 0);
765 while (GetNextHashPos(PreferenceHooks, It, &len, &Key, &vSetting)) {
766 PrefType = (PrefDef *) vSetting;
768 if (!HaveBstr(SKEY(PrefType->Setting)))
770 switch (PrefType->eType) {
773 Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
774 set_preference_backend(SKEY(PrefType->Setting), 0, Buf, PRF_STRING, 1, PrefType);
777 lval = LBstr(SKEY(PrefType->Setting));
778 set_preference_backend(SKEY(PrefType->Setting), lval, NULL, PRF_INT, 1, PrefType);
781 Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
782 set_preference_backend(SKEY(PrefType->Setting), 0, Buf, PRF_QP_STRING, 1, PrefType);
785 lval = YesBstr(SKEY(PrefType->Setting));
786 set_preference_backend(SKEY(PrefType->Setting), lval, NULL, PRF_YESNO, 1, PrefType);
790 WCC->hash_prefs = Tmp;
796 * Commit new preferences and settings
798 void set_preferences(void) {
799 if (!havebstr("change_button")) {
800 AppendImportantMessage(_("Cancelled. No settings were changed."), -1);
804 GetPreferences(WC->hash_prefs);
809 void tmplput_CFG_Value(StrBuf * Target, WCTemplputParams * TP) {
811 if (get_pref_backend(TKEY(0), &Pref)) {
812 if (Pref->Type == NULL) {
813 StrBufAppendTemplate(Target, TP, Pref->Val, 1);
815 switch (Pref->Type->eType) {
816 case PRF_UNSET: /* default to string... */
818 StrBufAppendTemplate(Target, TP, Pref->Val, 1);
821 if (Pref->decoded != 1) {
822 if (Pref->Val == NULL)
823 Pref->Val = NewStrBufPlain(NULL, 64);
824 StrBufPrintf(Pref->Val, "%ld", Pref->lval);
827 StrBufAppendTemplate(Target, TP, Pref->Val, 1);
830 if (Pref->decoded != 1) {
831 if (Pref->DeQPed == NULL)
832 Pref->DeQPed = NewStrBufPlain(NULL, StrLength(Pref->Val));
834 StrBufEUid_unescapize(Pref->DeQPed, Pref->Val);
837 StrBufAppendTemplate(Target, TP, Pref->DeQPed, 1);
840 if (Pref->decoded != 1) {
841 Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
844 StrBufAppendTemplate(Target, TP, Pref->Val, 1);
850 void tmplput_CFG_Descr(StrBuf * Target, WCTemplputParams * TP) {
851 const char *SettingStr;
852 SettingStr = PrefGetLocalStr(TKEY(0));
853 if (SettingStr != NULL)
854 StrBufAppendBufPlain(Target, SettingStr, -1, 0);
856 void tmplput_CFG_RoomValueLong(StrBuf * Target, WCTemplputParams * TP) {
861 defval = GetTemplateTokenNumber(Target, TP, 1, 0);
862 get_ROOM_PREFS_LONG(TKEY(0), &lvalue, defval);
863 StrBufAppendPrintf(Target, "%ld", lvalue);
865 void tmplput_CFG_RoomValue(StrBuf * Target, WCTemplputParams * TP) {
866 StrBuf *pref = get_ROOM_PREFS(TKEY(0));
868 StrBufAppendBuf(Target, pref, 0);
870 int ConditionalHasRoomPreference(StrBuf * Target, WCTemplputParams * TP) {
871 if (get_ROOM_PREFS(TP->Tokens->Params[0]->Start, TP->Tokens->Params[0]->len) != NULL)
877 int ConditionalPreference(StrBuf * Target, WCTemplputParams * TP) {
880 if (!get_PREFERENCE(TKEY(2), &Pref))
883 if (!HAVE_PARAM(3)) {
886 else if (IS_NUMBER(TP->Tokens->Params[3]->Type)) {
887 return StrTol(Pref) == GetTemplateTokenNumber(Target, TP, 3, 0);
893 GetTemplateTokenString(Target, TP, 3, &pch, &len);
895 return ((len == StrLength(Pref)) && (strcmp(pch, ChrPtr(Pref)) == 0));
899 int ConditionalHasPreference(StrBuf * Target, WCTemplputParams * TP) {
902 if (!get_PREFERENCE(TKEY(2), &Pref) || (Pref == NULL))
909 /********************************************************************************
910 * preferences stored discrete in citserver
911 ********************************************************************************/
912 CtxType CTX_VEA = CTX_NONE;
913 typedef struct __ValidEmailAddress {
918 void DeleteValidEmailAddress(void *v) {
919 ValidEmailAddress *VEA = (ValidEmailAddress *) v;
920 FreeStrBuf(&VEA->Address);
923 void tmplput_VEA(StrBuf * Target, WCTemplputParams * TP) {
924 ValidEmailAddress *VEA = (ValidEmailAddress *) CTX((CTX_VEA));
925 StrBufAppendTemplate(Target, TP, VEA->Address, 0);
927 int ConditionalPreferenceIsDefaulVEA(StrBuf * Target, WCTemplputParams * TP) {
928 ValidEmailAddress *VEA = (ValidEmailAddress *) CTX((CTX_VEA));
929 return VEA->IsDefault;
931 HashList *GetGVEAHash(StrBuf * Target, WCTemplputParams * TP) {
933 HashList *List = NULL;
937 StrBuf *DefaultFrom = NULL;
938 const StrBuf *EnvelopeTo;
939 ValidEmailAddress *VEA;
941 get_preference("defaultfrom", &DefaultFrom);
942 EnvelopeTo = sbstr("nvto");
945 StrBuf_ServGetln(Rcp);
946 if (GetServerStatus(Rcp, NULL) == 1) {
948 List = NewHash(1, NULL);
949 while (!Done && (StrBuf_ServGetln(Rcp) >= 0)) {
950 if ((StrLength(Rcp) == 3) && !strcmp(ChrPtr(Rcp), "000")) {
954 VEA = (ValidEmailAddress *) malloc(sizeof(ValidEmailAddress));
955 i = snprintf(N, sizeof(N), "%d", n);
958 if (StrLength(EnvelopeTo) > 0)
959 VEA->IsDefault = strstr(ChrPtr(EnvelopeTo), ChrPtr(Rcp)) != NULL;
960 else if (StrLength(DefaultFrom) > 0)
961 VEA->IsDefault = !strcmp(ChrPtr(Rcp), ChrPtr(DefaultFrom));
965 Put(List, N, i, VEA, DeleteValidEmailAddress);
974 void DeleteGVEAHash(HashList ** KillMe) {
978 HashList *GetGVSNHash(StrBuf * Target, WCTemplputParams * TP) {
980 HashList *List = NULL;
987 StrBuf_ServGetln(Rcp);
988 if (GetServerStatus(Rcp, NULL) == 1) {
990 List = NewHash(1, NULL);
991 while (!Done && (StrBuf_ServGetln(Rcp) >= 0)) {
992 if ((StrLength(Rcp) == 3) && !strcmp(ChrPtr(Rcp), "000")) {
996 i = snprintf(N, sizeof(N), "%d", n);
998 Put(List, N, i, Rcp, HFreeStrBuf);
1007 void DeleteGVSNHash(HashList ** KillMe) {
1015 * Offer to make any page the user's "start page" (only if logged in)
1017 void offer_start_page(StrBuf * Target, WCTemplputParams * TP) {
1018 if (WC->logged_in) {
1019 wc_printf("<a href=\"change_start_page?startpage=");
1020 urlescputs(ChrPtr(WC->Hdr->this_page));
1022 wc_printf(_("Make this my start page"));
1029 * Change the user's start page
1031 void change_start_page(void) {
1034 int ProhibitSave = 0;
1035 const StrBuf *pStartPage = sbstr("startpage");
1037 if (pStartPage != NULL) {
1038 pch = strchr(ChrPtr(pStartPage), '?');
1040 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. */
1045 if ((pStartPage == NULL) || (ProhibitSave == 1)) {
1046 set_preference_backend(HKEY("startpage"), 0, NewStrBufPlain(HKEY("")), PRF_STRING, 1, NULL);
1047 if (ProhibitSave == 1)
1048 AppendImportantMessage(_("This isn't allowed to become the start page."), -1);
1050 AppendImportantMessage(_("You no longer have a start page selected."), -1);
1051 display_main_menu();
1057 set_preference_backend(HKEY("startpage"), 0, NewStrBufDup(pStartPage), PRF_STRING, 1, NULL);
1059 output_headers(1, 1, 0, 0, 0, 0);
1060 do_template("newstartpage");
1065 void LoadStartpage(StrBuf * URL, long lvalue) {
1068 pch = strchr(ChrPtr(URL), '?');
1070 /* purge the sins of the past... */
1071 pch = strchr(ChrPtr(URL), '&');
1073 StrBufPeek(URL, pch, -1, '?');
1074 WC->SavePrefsToServer = 1;
1077 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. */
1079 WC->SavePrefsToServer = 1;
1084 void InitModule_PREFERENCES(void) {
1085 RegisterCTX(CTX_VEA);
1087 WebcitAddUrlHandler(HKEY("set_preferences"), "", 0, set_preferences, 0);
1088 WebcitAddUrlHandler(HKEY("change_start_page"), "", 0, change_start_page, 0);
1090 RegisterPreference("startpage", _("Prefered startpage"), PRF_STRING, LoadStartpage);
1092 RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, NULL, CTX_NONE);
1093 RegisterNamespace("PREF:ROOM:VALUE", 1, 2, tmplput_CFG_RoomValue, NULL, CTX_NONE);
1094 RegisterNamespace("PREF:ROOM:VALUE:INT", 1, 2, tmplput_CFG_RoomValueLong, NULL, CTX_NONE);
1095 RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, NULL, CTX_NONE);
1097 RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, NULL, CTX_NONE);
1099 RegisterConditional("COND:PREF", 4, ConditionalPreference, CTX_NONE);
1100 RegisterConditional("COND:PREF:SET", 4, ConditionalHasPreference, CTX_NONE);
1101 RegisterConditional("COND:ROOM:SET", 4, ConditionalHasRoomPreference, CTX_NONE);
1103 RegisterIterator("PREF:VALID:EMAIL:ADDR", 0, NULL, GetGVEAHash, NULL, DeleteGVEAHash, CTX_VEA, CTX_NONE, IT_NOFLAG);
1104 RegisterNamespace("PREF:VALID:EMAIL:ADDR:STR", 1, 1, tmplput_VEA, NULL, CTX_VEA);
1105 RegisterConditional("COND:PREF:VALID:EMAIL:ADDR:STR", 4, ConditionalPreferenceIsDefaulVEA, CTX_VEA);
1107 RegisterIterator("PREF:VALID:EMAIL:NAME", 0, NULL, GetGVSNHash, NULL, DeleteGVSNHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
1112 void ServerStartModule_PREFERENCES(void) {
1113 PreferenceHooks = NewHash(1, NULL);
1118 void ServerShutdownModule_PREFERENCES(void) {
1119 DeleteHash(&PreferenceHooks);
1122 void SessionDetachModule__PREFERENCES(wcsession * sess) {
1123 if (sess->SavePrefsToServer) {
1125 sess->SavePrefsToServer = 0;
1129 void SessionNewModule_PREFERENCES(wcsession * sess) {
1130 sess->hash_prefs = NewHash(1, NULL);
1133 void SessionDestroyModule_PREFERENCES(wcsession * sess) {
1134 DeleteHash(&sess->hash_prefs);