* ParsePref() was passing NULL values to the target buffer of the string tokenizer...
[citadel.git] / webcit / preferences.c
1 /*
2  * $Id$
3  *
4  * Manage user preferences with a little help from the Citadel server.
5  *
6  */
7
8 #include "webcit.h"
9 #include "webserver.h"
10 #include "groupdav.h"
11
12 HashList *PreferenceHooks;
13
14 typedef struct _PrefDef {
15         long Type;
16         StrBuf *Setting;
17         const char *PrefStr;
18         PrefEvalFunc OnLoad;
19 } PrefDef;
20
21 typedef struct _Preference {
22         StrBuf *Key;
23         StrBuf *Val;
24         PrefDef *Type;
25
26         long lval;
27         long decoded;
28         StrBuf *DeQPed;
29 }Preference;
30
31 void DestroyPrefDef(void *vPrefDef)
32 {
33         PrefDef *Prefdef = (PrefDef*) vPrefDef;
34         FreeStrBuf(&Prefdef->Setting);
35         free(Prefdef);
36 }
37
38 void DestroyPreference(void *vPref)
39 {
40         Preference *Pref = (Preference*) vPref;
41         FreeStrBuf(&Pref->Key);
42         FreeStrBuf(&Pref->Val);
43         FreeStrBuf(&Pref->DeQPed);
44         free(Pref);
45
46 }
47 void RegisterPreference(const char *Setting, long SettingLen, 
48                         const char *PrefStr, 
49                         long Type, 
50                         PrefEvalFunc OnLoad)
51 {
52         PrefDef *Newpref = (PrefDef*) malloc(sizeof(PrefDef));
53         Newpref->Setting = NewStrBufPlain(Setting, SettingLen);
54         Newpref->PrefStr = PrefStr;
55         Newpref->Type = Type;
56         Newpref->OnLoad = OnLoad;
57         Put(PreferenceHooks, Setting, SettingLen, Newpref, DestroyPrefDef);
58 }
59
60 const char *PrefGetLocalStr(const char *Setting, long len)
61 {
62         void *hash_value;
63         if (GetHash(PreferenceHooks, Setting, len, &hash_value) != 0) {
64                 PrefDef *Newpref = (PrefDef*) hash_value;
65                 return _(Newpref->PrefStr);
66
67         }
68         return "";
69 }
70
71 #ifdef DBG_PREFS_HASH
72 inline const char *PrintPref(void *vPref)
73 {
74         Preference *Pref = (Preference*) vPref;
75         if (Pref->DeQPed != NULL)
76                 return ChrPtr(Pref->DeQPed);
77         else 
78                 return ChrPtr(Pref->Val);
79 }
80 #endif
81
82 void GetPrefTypes(HashList *List)
83 {
84         HashPos *It;
85         long len;
86         const char *Key;
87         void *vSetting;
88         void *vPrefDef;
89         Preference *Setting;
90         PrefDef *PrefType;
91
92         It = GetNewHashPos(List, 0);
93         while (GetNextHashPos(List, It, &len, &Key, &vSetting)) 
94         {
95                 Setting = (Preference*) vSetting;
96                 if (GetHash(PreferenceHooks, SKEY(Setting->Key), &vPrefDef) && 
97                     (vPrefDef != NULL)) 
98                 {
99                         PrefType = (PrefDef*) vPrefDef;
100                         Setting->Type = PrefType;
101                         if (PrefType->OnLoad != NULL)
102                                 PrefType->OnLoad(Setting->Val, Setting->lval);
103                 }
104         }
105 }
106
107 void ParsePref(HashList **List, StrBuf *ReadBuf)
108 {
109         StrBuf *Key;
110         Preference *Data = NULL;
111         Preference *LastData = NULL;
112                                 
113         Key = NewStrBuf();
114         while (StrBuf_ServGetln(ReadBuf), 
115                strcmp(ChrPtr(ReadBuf), "000")) 
116         {
117                 if ((ChrPtr(ReadBuf)[0] == ' ') &&
118                     (Data != NULL)) {
119                         StrBufAppendBuf(Data->Val, ReadBuf, 1);
120                 }
121                 else {
122                         LastData = Data = malloc(sizeof(Preference));
123                         memset(Data, 0, sizeof(Preference));
124                         Data->Key = NewStrBuf();
125                         Data->Val = NewStrBuf();
126                         StrBufExtract_token(Data->Key, ReadBuf, 0, '|');
127                         StrBufExtract_token(Data->Val, ReadBuf, 1, '|');
128                         if (!IsEmptyStr(ChrPtr(Data->Key)))
129                         {
130                                 Put(*List, 
131                                     SKEY(Data->Key),
132                                     Data, 
133                                     DestroyPreference);
134                         }
135                         else 
136                         {
137                                 StrBufTrim(ReadBuf);
138                                 lprintf(1, "ignoring spurious preference line: [%s]\n", 
139                                         ChrPtr(ReadBuf));
140                                 DestroyPreference(Data);
141                                 LastData = NULL;
142                         }
143                 }
144         }
145         GetPrefTypes(*List);
146 }
147
148
149 /*
150  * display preferences dialog
151  */
152 void load_preferences(void) 
153 {
154         StrBuf *ReadBuf;
155         char buf[SIZ];
156         long msgnum = 0L;
157         
158         if (goto_config_room() != 0) return;    /* oh well. */
159
160         ReadBuf = NewStrBuf();
161         serv_puts("MSGS ALL|0|1");
162         StrBuf_ServGetln(ReadBuf);
163         if (GetServerStatus(ReadBuf, NULL) == 8) {
164                 serv_puts("subj|__ WebCit Preferences __");
165                 serv_puts("000");
166         }
167         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
168                 msgnum = atol(buf);
169         }
170
171         if (msgnum > 0L) {
172                 serv_printf("MSG0 %ld", msgnum);
173                 StrBuf_ServGetln(ReadBuf);
174                 if (GetServerStatus(ReadBuf, NULL) == 1) {
175                         while (StrBuf_ServGetln(ReadBuf),
176                                (strcmp(ChrPtr(ReadBuf), "text") && 
177                                 strcmp(ChrPtr(ReadBuf), "000"))) {
178                         }
179                         if (!strcmp(ChrPtr(ReadBuf), "text")) {
180                                 ParsePref(&WC->hash_prefs, ReadBuf);
181                         }
182                 }
183         }
184
185         /* Go back to the room we're supposed to be in */
186         serv_printf("GOTO %s", ChrPtr(WC->wc_roomname));
187         StrBuf_ServGetln(ReadBuf);
188         GetServerStatus(ReadBuf, NULL);
189         FreeStrBuf(&ReadBuf);
190 }
191
192 /**
193  * \brief Goto the user's configuration room, creating it if necessary.
194  * \return 0 on success or nonzero upon failure.
195  */
196 int goto_config_room(void) {
197         char buf[SIZ];
198
199         serv_printf("GOTO %s", USERCONFIGROOM);
200         serv_getln(buf, sizeof buf);
201         if (buf[0] != '2') { /* try to create the config room if not there */
202                 serv_printf("CRE8 1|%s|4|0", USERCONFIGROOM);
203                 serv_getln(buf, sizeof buf);
204                 serv_printf("GOTO %s", USERCONFIGROOM);
205                 serv_getln(buf, sizeof buf);
206                 if (buf[0] != '2') return(1);
207         }
208         return(0);
209 }
210
211 void WritePrefsToServer(HashList *Hash)
212 {
213         long len;
214         HashPos *HashPos;
215         void *vPref;
216         const char *Key;
217         Preference *Pref;
218         StrBuf *SubBuf = NULL;
219         
220         Hash = WC->hash_prefs;
221 #ifdef DBG_PREFS_HASH
222         dbg_PrintHash(Hash, PrintPref, NULL);
223 #endif
224         HashPos = GetNewHashPos(Hash, 0);
225         while (GetNextHashPos(Hash, HashPos, &len, &Key, &vPref)!=0)
226         {
227                 size_t nchars;
228                 if (vPref == NULL)
229                         continue;
230                 Pref = (Preference*) vPref;
231                 nchars = StrLength(Pref->Val);
232                 if (nchars > 80){
233                         int n = 0;
234                         size_t offset, nchars;
235                         if (SubBuf == NULL)
236                                 SubBuf = NewStrBuf();
237                         nchars = 1;
238                         offset = 0;
239                         while (nchars > 0) {
240                                 if (n == 0)
241                                         nchars = 70;
242                                 else 
243                                         nchars = 80;
244                                 
245                                 nchars = StrBufSub(SubBuf, Pref->Val, offset, nchars);
246                                 
247                                 if (n == 0)
248                                         serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(SubBuf));
249                                 else
250                                         serv_printf(" %s", ChrPtr(SubBuf));
251                                 
252                                 offset += nchars;
253                                 nchars = StrLength(Pref->Val) - offset;
254                                 n++;
255                         }
256                         
257                 }
258                 else
259                         serv_printf("%s|%s", ChrPtr(Pref->Key), ChrPtr(Pref->Val));
260                 
261         }
262         FreeStrBuf(&SubBuf);
263         DeleteHashPos(&HashPos);
264 }
265
266 /**
267  * \brief save the modifications
268  */
269 void save_preferences(void) 
270 {
271         char buf[SIZ];
272         long msgnum = 0L;
273         
274         if (goto_config_room() != 0) return;    /* oh well. */
275         serv_puts("MSGS ALL|0|1");
276         serv_getln(buf, sizeof buf);
277         if (buf[0] == '8') {
278                 serv_puts("subj|__ WebCit Preferences __");
279                 serv_puts("000");
280         }
281         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
282                 msgnum = atol(buf);
283         }
284
285         if (msgnum > 0L) {
286                 serv_printf("DELE %ld", msgnum);
287                 serv_getln(buf, sizeof buf);
288         }
289
290         serv_printf("ENT0 1||0|1|__ WebCit Preferences __|");
291         serv_getln(buf, sizeof buf);
292         if (buf[0] == '4') {
293
294                 WritePrefsToServer(WC->hash_prefs);
295                 serv_puts("");
296                 serv_puts("000");
297         }
298
299         /** Go back to the room we're supposed to be in */
300         serv_printf("GOTO %s", ChrPtr(WC->wc_roomname));
301         serv_getln(buf, sizeof buf);
302 }
303
304 /**
305  * \brief query the actual setting of key in the citadel database
306  * \param key config key to query
307  * \param keylen length of the key string
308  * \param value StrBuf-value to the key to get
309  * \returns found?
310  */
311 int get_pref_backend(const char *key, size_t keylen, Preference **Pref)
312 {
313         void *hash_value = NULL;
314 #ifdef DBG_PREFS_HASH
315         dbg_PrintHash(WC->hash_prefs, PrintPref, NULL);
316 #endif
317         if (GetHash(WC->hash_prefs, key, keylen, &hash_value) == 0) {
318                 *Pref = NULL;
319                 return 0;
320         }
321         else {
322                 *Pref = (Preference*) hash_value;
323                 return 1;
324         }
325 }
326
327 int get_PREFERENCE(const char *key, size_t keylen, StrBuf **value)
328 {
329         Preference *Pref;
330         int Ret;
331
332         Ret = get_pref_backend(key, keylen, &Pref);
333         if (Ret != 0)
334                 *value = Pref->Val;
335         else
336                 *value = NULL;
337         return Ret;
338 }
339
340 /**
341  * \brief       Write a key into the webcit preferences database for this user
342  *
343  * \params      key             key whichs value is to be modified
344  * \param keylen length of the key string
345  * \param       value           value to set
346  * \param       save_to_server  1 = flush all data to the server, 0 = cache it for now
347  */
348 void set_preference_backend(const char *key, size_t keylen, 
349                             long lvalue, 
350                             StrBuf *value, 
351                             long lPrefType,
352                             int save_to_server, 
353                             PrefDef *PrefType) 
354 {
355         void *vPrefDef;
356         Preference *Pref;
357
358         Pref = (Preference*) malloc(sizeof(Preference));
359         memset(Pref, 0, sizeof(Preference));
360         Pref->Key = NewStrBufPlain(key, keylen);
361
362         if ((PrefType == NULL) &&
363             GetHash(PreferenceHooks, SKEY(Pref->Key), &vPrefDef) && 
364             (vPrefDef != NULL))
365                 PrefType = (PrefDef*) vPrefDef;
366
367         if (PrefType != NULL)
368         {
369                 Pref->Type = PrefType;
370                 if (Pref->Type->Type != lPrefType)
371                         lprintf(1, "warning: saving preference with wrong type [%s] %ld != %ld \n",
372                                 key, Pref->Type->Type, lPrefType);
373                 switch (Pref->Type->Type)
374                 {
375                 case PRF_STRING:
376                         Pref->Val = value;
377                         Pref->decoded = 1;
378                         break;
379                 case PRF_INT:
380                         Pref->lval = lvalue;
381                         Pref->Val = value;
382                         if (Pref->Val == NULL)
383                                 Pref->Val = NewStrBufPlain(NULL, 64);
384                         StrBufPrintf(Pref->Val, "%ld", lvalue);
385                         Pref->decoded = 1;
386                         break;
387                 case PRF_QP_STRING:
388                         Pref->DeQPed = value;
389                         Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
390                         StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
391                         Pref->decoded = 1;
392                         break;
393                 case PRF_YESNO:
394                         Pref->lval = lvalue;
395                         if (lvalue) 
396                                 Pref->Val = NewStrBufPlain(HKEY("yes"));
397                         else
398                                 Pref->Val = NewStrBufPlain(HKEY("no"));
399                         Pref->decoded = 1;
400                         break;
401                 }
402                 if (Pref->Type->OnLoad != NULL)
403                         Pref->Type->OnLoad(Pref->Val, Pref->lval);
404         }
405         else {
406                 switch (lPrefType)
407                 {
408                 case PRF_STRING:
409                         Pref->Val = value;
410                         Pref->decoded = 1;
411                         break;
412                 case PRF_INT:
413                         Pref->lval = lvalue;
414                         Pref->Val = value;
415                         if (Pref->Val == NULL)
416                                 Pref->Val = NewStrBufPlain(NULL, 64);
417                         StrBufPrintf(Pref->Val, "%ld", lvalue);
418                         Pref->decoded = 1;
419                         break;
420                 case PRF_QP_STRING:
421                         Pref->DeQPed = value;
422                         Pref->Val = NewStrBufPlain(NULL, StrLength(Pref->DeQPed) * 3);
423                         StrBufEUid_escapize(Pref->Val, Pref->DeQPed);
424                         Pref->decoded = 1;
425                         break;
426                 case PRF_YESNO:
427                         Pref->lval = lvalue;
428                         if (lvalue) 
429                                 Pref->Val = NewStrBufPlain(HKEY("yes"));
430                         else
431                                 Pref->Val = NewStrBufPlain(HKEY("no"));
432                         Pref->decoded = 1;
433                         break;
434                 }
435         }
436         Put(WC->hash_prefs, key, keylen, Pref, DestroyPreference);
437         
438         if (save_to_server) WC->SavePrefsToServer = 1;
439 }
440
441 void set_PREFERENCE(const char *key, size_t keylen, StrBuf *value, int save_to_server) 
442 {
443         set_preference_backend(key, keylen, 0, value, PRF_STRING, save_to_server, NULL);
444 }
445
446 int get_PREF_LONG(const char *key, size_t keylen, long *value, long Default)
447 {
448         Preference *Pref;
449         int Ret;
450
451         Ret = get_pref_backend(key, keylen, &Pref);
452         if (Ret == 0) {
453                 *value = Default;
454                 return 0;
455         }
456
457         if (Pref->decoded)
458                 *value = Pref->lval;
459         else {
460                 *value = Pref->lval = atol(ChrPtr(Pref->Val));
461                 Pref->decoded = 1;
462         }
463         return Ret;
464 }
465
466
467 void set_PREF_LONG(const char *key, size_t keylen, long value, int save_to_server)
468 {
469         set_preference_backend(key, keylen, value, NULL, PRF_INT, save_to_server, NULL);
470 }
471
472 int get_PREF_YESNO(const char *key, size_t keylen, int *value, int Default)
473 {
474         Preference *Pref;
475         int Ret;
476
477         Ret = get_pref_backend(key, keylen, &Pref);
478         if (Ret == 0) {
479                 *value = Default;
480                 return 0;
481         }
482
483         if (Pref->decoded)
484                 *value = Pref->lval;
485         else {
486                 *value = Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
487                 Pref->decoded = 1;
488         }
489         return Ret;
490 }
491
492 void set_PREF_YESNO(const char *key, size_t keylen, long value, int save_to_server)
493 {
494         set_preference_backend(key, keylen, value, NULL, PRF_YESNO, save_to_server, NULL);
495 }
496
497 int get_room_prefs_backend(const char *key, size_t keylen, 
498                            Preference **Pref)
499 {
500         StrBuf *pref_name;
501         int Ret;
502
503         pref_name = NewStrBufPlain (HKEY("ROOM:"));
504         StrBufAppendBuf(pref_name, WC->wc_roomname, 0);
505         StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
506         StrBufAppendBufPlain(pref_name, key, keylen, 0);
507         Ret = get_pref_backend(SKEY(pref_name), Pref);
508         FreeStrBuf(&pref_name);
509
510         return Ret;
511 }
512
513 const StrBuf *get_X_PREFS(const char *key, size_t keylen, 
514                           const char *xkey, size_t xkeylen)
515 {
516         int ret;
517         StrBuf *pref_name;
518         Preference *Prf;
519         
520         pref_name = NewStrBufPlain (HKEY("XPREF:"));
521         StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
522         StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
523         StrBufAppendBufPlain(pref_name, key, keylen, 0);
524
525         ret = get_pref_backend(SKEY(pref_name), &Prf);
526         FreeStrBuf(&pref_name);
527
528         if (ret)
529                 return Prf->Val;
530         else return NULL;
531 }
532
533 void set_X_PREFS(const char *key, size_t keylen, const char *xkey, size_t xkeylen, StrBuf *value, int save_to_server)
534 {
535         StrBuf *pref_name;
536         
537         pref_name = NewStrBufPlain (HKEY("XPREF:"));
538         StrBufAppendBufPlain(pref_name, xkey, xkeylen, 0);
539         StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
540         StrBufAppendBufPlain(pref_name, key, keylen, 0);
541
542         set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
543         FreeStrBuf(&pref_name);
544 }
545
546
547 StrBuf *get_ROOM_PREFS(const char *key, size_t keylen)
548 {
549         Preference *Pref;
550         int Ret;
551
552         Ret = get_room_prefs_backend(key, keylen, &Pref);
553
554         if (Ret == 0) {
555                 return NULL;
556         }
557         else 
558                 return Pref->Val;
559 }
560
561 void set_ROOM_PREFS(const char *key, size_t keylen, StrBuf *value, int save_to_server)
562 {
563         StrBuf *pref_name;
564         
565         pref_name = NewStrBufPlain (HKEY("ROOM:"));
566         StrBufAppendBuf(pref_name, WC->wc_roomname, 0);
567         StrBufAppendBufPlain(pref_name, HKEY(":"), 0);
568         StrBufAppendBufPlain(pref_name, key, keylen, 0);
569         set_preference_backend(SKEY(pref_name), 0, value, PRF_STRING, save_to_server, NULL);
570         FreeStrBuf(&pref_name);
571 }
572
573
574 void GetPreferences(HashList *Setting)
575 {
576         wcsession *WCC = WC;
577         HashPos *It;
578         long len;
579         const char *Key;
580         void *vSetting;
581         PrefDef *PrefType;
582         StrBuf *Buf;
583         long lval;
584         HashList *Tmp;
585
586         Tmp = WCC->hash_prefs;
587         WCC->hash_prefs = Setting;
588
589         It = GetNewHashPos(PreferenceHooks, 0);
590         while (GetNextHashPos(PreferenceHooks, It, &len, &Key, &vSetting)) {
591                 PrefType = (PrefDef*) vSetting;
592
593                 if (!HaveBstr(SKEY(PrefType->Setting)))
594                         continue;
595                 switch (PrefType->Type) {
596                 case PRF_STRING:
597                         Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
598                         set_preference_backend(SKEY(PrefType->Setting),
599                                                0, 
600                                                Buf, 
601                                                PRF_STRING,
602                                                1, 
603                                                PrefType);
604                         break;
605                 case PRF_INT:
606                         lval = LBstr(SKEY(PrefType->Setting));
607                         set_preference_backend(SKEY(PrefType->Setting),
608                                                lval, 
609                                                NULL, 
610                                                PRF_INT,
611                                                1, 
612                                                PrefType);
613                         break;
614                 case PRF_QP_STRING:
615                         Buf = NewStrBufDup(SBstr(SKEY(PrefType->Setting)));
616                         set_preference_backend(SKEY(PrefType->Setting),
617                                                0, 
618                                                Buf, 
619                                                PRF_QP_STRING,
620                                                1, 
621                                                PrefType);
622                         break;
623                 case PRF_YESNO:
624                         lval = YesBstr(SKEY(PrefType->Setting));
625                         set_preference_backend(SKEY(PrefType->Setting),
626                                                lval, 
627                                                NULL, 
628                                                PRF_YESNO,
629                                                1, 
630                                                PrefType);
631                         break;
632                 }
633         }
634         WCC->hash_prefs = Tmp;
635 }
636
637
638 /**
639  * \brief Commit new preferences and settings
640  */
641 void set_preferences(void)
642 {       
643         if (!havebstr("change_button")) {
644                 safestrncpy(WC->ImportantMessage, 
645                             _("Cancelled.  No settings were changed."),
646                             sizeof WC->ImportantMessage);
647                 display_main_menu();
648                 return;
649         }
650         GetPreferences(WC->hash_prefs);
651         display_main_menu();
652 }
653
654
655 void tmplput_CFG_Value(StrBuf *Target, WCTemplputParams *TP)
656 {
657         Preference *Pref;
658         if (get_pref_backend(TKEY(0), &Pref))
659         {
660                 if (Pref->Type == NULL) {
661                         StrBufAppendTemplate(Target, TP, Pref->Val, 1);
662                 }
663                 switch (Pref->Type->Type)
664                 {
665                 case PRF_STRING:
666                         StrBufAppendTemplate(Target, TP, Pref->Val, 1);
667                         break;
668                 case PRF_INT:
669                         if (Pref->decoded != 1) {
670                                 if (Pref->Val == NULL)
671                                         Pref->Val = NewStrBufPlain(NULL, 64);
672                                 StrBufPrintf(Pref->Val, "%ld", Pref->lval);
673                                 Pref->decoded = 1;
674                         }
675                         StrBufAppendTemplate(Target, TP, Pref->Val, 1);
676                         break;
677                 case PRF_QP_STRING:
678                         if (Pref->decoded != 1) {
679                                 if (Pref->DeQPed == NULL)
680                                         Pref->DeQPed = NewStrBufPlain(NULL, StrLength(Pref->Val));
681                                         
682                                 StrBufEUid_unescapize(Pref->DeQPed, Pref->Val);
683                                 Pref->decoded = 1;
684                         }
685                         StrBufAppendTemplate(Target, TP, Pref->DeQPed, 1);
686                         break;
687                 case PRF_YESNO:
688                         if (Pref->decoded != 1) {
689                                 Pref->lval = strcmp(ChrPtr(Pref->Val), "yes") == 0;
690                                 Pref->decoded = 1;
691                         }
692                         StrBufAppendTemplate(Target, TP, Pref->Val, 1);
693                         break;
694                 }
695         }
696 }
697
698 void tmplput_CFG_Descr(StrBuf *Target, WCTemplputParams *TP)
699 {
700         const char *SettingStr;
701         SettingStr = PrefGetLocalStr(TKEY(0));
702         if (SettingStr != NULL) 
703                 StrBufAppendBufPlain(Target, SettingStr, -1, 0);
704 }
705 void tmplput_CFG_RoomValue(StrBuf *Target, WCTemplputParams *TP)
706 {
707         StrBuf *pref = get_ROOM_PREFS(TKEY(0));
708         if (pref != NULL) 
709                 StrBufAppendBuf(Target, pref, 0);
710 }
711 int ConditionalHasRoomPreference(StrBuf *Target, WCTemplputParams *TP) 
712 {
713         if (get_ROOM_PREFS(TP->Tokens->Params[0]->Start, 
714                            TP->Tokens->Params[0]->len) != NULL) 
715                 return 1;
716   
717         return 0;
718 }
719 void CfgZoneTempl(StrBuf *TemplBuffer, WCTemplputParams *TP)
720 {
721         StrBuf *Zone = (StrBuf*) CTX;
722
723         SVPutBuf("ZONENAME", Zone, 1);
724 }
725
726 int ConditionalPreference(StrBuf *Target, WCTemplputParams *TP)
727 {
728         StrBuf *Pref;
729
730         if (!get_PREFERENCE(TKEY(2), &Pref)) 
731                 return 0;
732         
733         if (TP->Tokens->nParameters == 3) {
734                 return 1;
735         }
736         else if (TP->Tokens->Params[3]->Type == TYPE_STR)
737                 return ((TP->Tokens->Params[3]->len == StrLength(Pref)) &&
738                         (strcmp(TP->Tokens->Params[3]->Start, ChrPtr(Pref)) == 0));
739         else 
740                 return (StrTol(Pref) == TP->Tokens->Params[3]->lvalue);
741 }
742
743 int ConditionalHasPreference(StrBuf *Target, WCTemplputParams *TP)
744 {
745         StrBuf *Pref;
746
747         if (!get_PREFERENCE(TKEY(2), &Pref) || 
748             (Pref == NULL)) 
749                 return 0;
750         else 
751                 return 1;
752 }
753
754
755 /********************************************************************************
756  *                 preferences stored discrete in citserver
757  ********************************************************************************/
758 HashList *GetGVEAHash(StrBuf *Target, WCTemplputParams *TP)
759 {
760         StrBuf *Rcp;
761         HashList *List = NULL;
762         int Done = 0;
763         int i, n = 1;
764         char N[64];
765
766         Rcp = NewStrBuf();
767         serv_puts("GVEA");
768         StrBuf_ServGetln(Rcp);
769         if (GetServerStatus(Rcp, NULL) == 1) {
770                 FlushStrBuf(Rcp);
771                 List = NewHash(1, NULL);
772                 while (!Done && (StrBuf_ServGetln(Rcp)>=0)) {
773                         if ( (StrLength(Rcp)==3) && 
774                              !strcmp(ChrPtr(Rcp), "000")) 
775                         {
776                                 Done = 1;
777                         }
778                         else {
779                                 i = snprintf(N, sizeof(N), "%d", n);
780                                 StrBufTrim(Rcp);
781                                 Put(List, N, i, Rcp, HFreeStrBuf);
782                                 Rcp = NewStrBuf();
783                         }
784                         n++;
785                 }
786         }
787         FreeStrBuf(&Rcp);
788         return List;
789 }
790 void DeleteGVEAHash(HashList **KillMe)
791 {
792         DeleteHash(KillMe);
793 }
794
795 HashList *GetGVSNHash(StrBuf *Target, WCTemplputParams *TP)
796 {
797         StrBuf *Rcp;
798         HashList *List = NULL;
799         int Done = 0;
800         int i, n = 1;
801         char N[64];
802
803         Rcp = NewStrBuf();
804         serv_puts("GVSN");
805         StrBuf_ServGetln(Rcp);
806         if (GetServerStatus(Rcp, NULL) == 1) {
807                 FlushStrBuf(Rcp);
808                 List = NewHash(1, NULL);
809                 while (!Done && (StrBuf_ServGetln(Rcp)>=0)) {
810                         if ( (StrLength(Rcp)==3) && 
811                              !strcmp(ChrPtr(Rcp), "000")) 
812                         {
813                                 Done = 1;
814                         }
815                         else {
816                                 i = snprintf(N, sizeof(N), "%d", n);
817                                 StrBufTrim(Rcp);
818                                 Put(List, N, i, Rcp, HFreeStrBuf);
819                                 Rcp = NewStrBuf();
820                         }
821                         n++;
822                 }
823         }
824         FreeStrBuf(&Rcp);
825         return List;
826 }
827 void DeleteGVSNHash(HashList **KillMe)
828 {
829         DeleteHash(KillMe);
830 }
831
832
833
834
835 /*
836  * Offer to make any page the user's "start page."
837  */
838 void offer_start_page(StrBuf *Target, WCTemplputParams *TP)
839 {
840         wprintf("<a href=\"change_start_page?startpage=");
841         urlescputs(WC->this_page);
842         wprintf("\">");
843         wprintf(_("Make this my start page"));
844         wprintf("</a>");
845 #ifdef TECH_PREVIEW
846         wprintf("<br/><a href=\"rss?room=");
847         urlescputs(ChrPtr(WC->wc_roomname));
848         wprintf("\" title=\"RSS 2.0 feed for ");
849         escputs(ChrPtr(WC->wc_roomname));
850         wprintf("\"><img alt=\"RSS\" border=\"0\" src=\"static/xml_button.gif\"/></a>\n");
851 #endif
852 }
853
854
855 /*
856  * Change the user's start page
857  */
858 void change_start_page(void) 
859 {
860         if (!havebstr("startpage")) {
861                 set_preference_backend(HKEY("startpage"), 
862                                        0, 
863                                        NewStrBufPlain(HKEY("")),
864                                        PRF_STRING,
865                                        1, 
866                                        NULL);
867                 safestrncpy(WC->ImportantMessage,
868                             _("You no longer have a start page selected."),
869                             sizeof( WC->ImportantMessage));
870                 display_main_menu();
871                 return;
872         }
873
874         set_preference_backend(HKEY("startpage"), 
875                                0, 
876                                NewStrBufDup(sbstr("startpage")),
877                                PRF_STRING,
878                                1, 
879                                NULL);
880
881         output_headers(1, 1, 0, 0, 0, 0);
882         do_template("newstartpage", NULL);
883         wDumpContent(1);
884 }
885
886
887 void 
888 InitModule_PREFERENCES
889 (void)
890 {
891         WebcitAddUrlHandler(HKEY("set_preferences"), set_preferences, 0);
892         WebcitAddUrlHandler(HKEY("change_start_page"), change_start_page, 0);
893
894
895         RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, CTX_NONE);
896         RegisterNamespace("PREF:ROOM:VALUE", 1, 2, tmplput_CFG_RoomValue,  CTX_NONE);
897         RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, CTX_NONE);
898         RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_NONE);
899         RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, CfgZoneTempl, NULL, CTX_PREF, CTX_NONE, IT_NOFLAG);
900
901         RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference, CTX_NONE);
902         RegisterConditional(HKEY("COND:PREF:SET"), 4, ConditionalHasPreference, CTX_NONE);
903         RegisterConditional(HKEY("COND:ROOM:SET"), 4, ConditionalHasRoomPreference, CTX_NONE);
904         
905         RegisterIterator("PREF:VALID:EMAIL:ADDR", 0, NULL, 
906                          GetGVEAHash, NULL, DeleteGVEAHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
907         RegisterIterator("PREF:VALID:EMAIL:NAME", 0, NULL, 
908                          GetGVSNHash, NULL, DeleteGVSNHash, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
909
910 }
911 /*@}*/