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