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