ea5e3c6a05314a3456fcee64dd2139d93f312b45
[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 inline const char *PrintPref(void *Prefstr)
13 {
14         return Prefstr;
15 }
16
17 /*
18  * display preferences dialog
19  */
20 void load_preferences(void) {
21         char buf[SIZ];
22         long msgnum = 0L;
23         char key[SIZ], value[SIZ];
24         
25         serv_printf("GOTO %s", USERCONFIGROOM);
26         serv_getln(buf, sizeof buf);
27         if (buf[0] != '2') return;
28         
29         serv_puts("MSGS ALL|0|1");
30         serv_getln(buf, sizeof buf);
31         if (buf[0] == '8') {
32                 serv_puts("subj|__ WebCit Preferences __");
33                 serv_puts("000");
34         }
35         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
36                 msgnum = atol(buf);
37         }
38
39         if (msgnum > 0L) {
40                 serv_printf("MSG0 %ld", msgnum);
41                 serv_getln(buf, sizeof buf);
42                 if (buf[0] == '1') {
43                         while (serv_getln(buf, sizeof buf),
44                                 (strcmp(buf, "text") && strcmp(buf, "000"))) {
45                         }
46                         if (!strcmp(buf, "text")) {
47                                 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
48                                         extract_token(key, buf, 0, '|', sizeof key);
49                                         extract_token(value, buf, 1, '|', sizeof value);
50                                         if (!IsEmptyStr(key))
51                                                 Put(WC->hash_prefs, key, strlen(key), strdup(value), free);
52                                 }
53                         }
54                 }
55         }
56
57         /* Go back to the room we're supposed to be in */
58         serv_printf("GOTO %s", WC->wc_roomname);
59         serv_getln(buf, sizeof buf);
60 }
61
62 /**
63  * \brief Goto the user's configuration room, creating it if necessary.
64  * \return 0 on success or nonzero upon failure.
65  */
66 int goto_config_room(void) {
67         char buf[SIZ];
68
69         serv_printf("GOTO %s", USERCONFIGROOM);
70         serv_getln(buf, sizeof buf);
71         if (buf[0] != '2') { /* try to create the config room if not there */
72                 serv_printf("CRE8 1|%s|4|0", USERCONFIGROOM);
73                 serv_getln(buf, sizeof buf);
74                 serv_printf("GOTO %s", USERCONFIGROOM);
75                 serv_getln(buf, sizeof buf);
76                 if (buf[0] != '2') return(1);
77         }
78         return(0);
79 }
80
81 /**
82  * \brief save the modifications
83  */
84 void save_preferences(void) {
85         char buf[SIZ];
86         long msgnum = 0L;
87         
88         if (goto_config_room() != 0) return;    /* oh well. */
89         serv_puts("MSGS ALL|0|1");
90         serv_getln(buf, sizeof buf);
91         if (buf[0] == '8') {
92                 serv_puts("subj|__ WebCit Preferences __");
93                 serv_puts("000");
94         }
95         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
96                 msgnum = atol(buf);
97         }
98
99         if (msgnum > 0L) {
100                 serv_printf("DELE %ld", msgnum);
101                 serv_getln(buf, sizeof buf);
102         }
103
104         serv_printf("ENT0 1||0|1|__ WebCit Preferences __|");
105         serv_getln(buf, sizeof buf);
106         if (buf[0] == '4') {
107                 long len;
108                 HashPos *HashPos;
109                 HashList *Hash;
110                 char *Value;
111                 char *Key;
112                 
113                 Hash = WC->hash_prefs;
114                 PrintHash(Hash, PrintPref, NULL);
115                 HashPos = GetNewHashPos();
116                 while (GetNextHashPos(Hash, HashPos, &len, &Key, (void**)&Value)!=0)
117                 {
118                         serv_printf("%s|%s", Key, Value);
119                 }
120                 serv_puts("");
121                 serv_puts("000");
122                 DeleteHashPos(&HashPos);
123         }
124
125         /** Go back to the room we're supposed to be in */
126         serv_printf("GOTO %s", WC->wc_roomname);
127         serv_getln(buf, sizeof buf);
128 }
129
130 /**
131  * \brief query the actual setting of key in the citadel database
132  * \param key config key to query
133  * \param value value to the key to get
134  * \param value_len length of the value string
135  */
136 void get_preference(char *key, char *value, size_t value_len) {
137         void *hash_value = NULL;
138         
139         strcpy(value, "");
140         PrintHash(WC->hash_prefs, PrintPref, NULL);
141         if (GetHash(WC->hash_prefs, key, strlen(key), &hash_value) == 0)
142                 return;
143         
144         if(hash_value)
145                 safestrncpy(value, hash_value, value_len);
146 }
147
148 /**
149  * \brief       Write a key into the webcit preferences database for this user
150  *
151  * \params      key             key whichs value is to be modified
152  * \param       value           value to set
153  * \param       save_to_server  1 = flush all data to the server, 0 = cache it for now
154  */
155 void set_preference(char *key, char *value, int save_to_server) {
156         
157         Put(WC->hash_prefs, key, strlen(key), strdup(value), free);
158         
159         if (save_to_server) save_preferences();
160 }
161
162
163
164
165 /** 
166  * \brief display form for changing your preferences and settings
167  */
168 void display_preferences(void)
169 {
170         output_headers(1, 1, 1, 0, 0, 0);
171         char ebuf[300];
172         char buf[256];
173         int i;
174         int time_format;
175         time_t tt;
176         struct tm tm;
177         char daylabel[32];
178         
179         time_format = get_time_format_cached ();
180
181         wprintf("<div class=\"box\">\n");
182         wprintf("<div class=\"boxlabel\">");
183         wprintf(_("Preferences and settings"));
184         wprintf("</div>");
185
186         wprintf("<div class=\"boxcontent\">");
187
188         /** begin form */
189         wprintf("<form name=\"prefform\" action=\"set_preferences\" "
190                 "method=\"post\">\n");
191         wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%ld\">\n", WC->nonce);
192
193         /** begin table */
194         wprintf("<table class=\"altern\">\n");
195
196         /**
197          * Room list view
198          */
199         get_preference("roomlistview", buf, sizeof buf);
200         wprintf("<tr class=\"even\"><td>");
201         wprintf(_("Room list view"));
202         wprintf("</td><td>");
203
204         wprintf("<input type=\"radio\" name=\"roomlistview\" VALUE=\"folders\"");
205         if (!strcasecmp(buf, "folders")) wprintf(" checked");
206         wprintf(">");
207         wprintf(_("Tree (folders) view"));
208         wprintf("</input>&nbsp;&nbsp;&nbsp;");
209
210         wprintf("<input type=\"radio\" name=\"roomlistview\" VALUE=\"rooms\"");
211         if (!strcasecmp(buf, "rooms")) wprintf(" checked");
212         wprintf(">");
213         wprintf(_("Table (rooms) view"));
214         wprintf("</input>\n");
215
216         wprintf("</td></tr>\n");
217
218         /**
219          * Time hour format
220          */
221
222         wprintf("<tr class=\"odd\"><td>");
223         wprintf(_("Time format"));
224         wprintf("</td><td>");
225
226         wprintf("<input type=\"radio\" name=\"calhourformat\" VALUE=\"12\"");
227         if (time_format == WC_TIMEFORMAT_AMPM) 
228                 wprintf(" checked");
229         wprintf(">");
230         wprintf(_("12 hour (am/pm)"));
231         wprintf("</input>&nbsp;&nbsp;&nbsp;");
232
233         wprintf("<input type=\"radio\" name=\"calhourformat\" VALUE=\"24\"");
234         if (time_format == WC_TIMEFORMAT_24)
235                 wprintf(" checked");
236         wprintf(">");
237         wprintf(_("24 hour"));
238         wprintf("</input>\n");
239
240         wprintf("</td></tr>\n");
241
242         /**
243          * Calendar day view -- day start time
244          */
245         get_preference("daystart", buf, sizeof buf);
246         if (buf[0] == 0) strcpy(buf, "8");
247         wprintf("<tr class=\"even\"><td>");
248         wprintf(_("Calendar day view begins at:"));
249         wprintf("</td><td>");
250
251         wprintf("<select name=\"daystart\" size=\"1\">\n");
252         for (i=0; i<=23; ++i) {
253
254                 if (time_format == WC_TIMEFORMAT_24) {
255                         wprintf("<option %s value=\"%d\">%d:00</option>\n",
256                                 ((atoi(buf) == i) ? "selected" : ""),
257                                 i, i
258                         );
259                 }
260                 else {
261                         wprintf("<option %s value=\"%d\">%s</option>\n",
262                                 ((atoi(buf) == i) ? "selected" : ""),
263                                 i, hourname[i]
264                         );
265                 }
266
267         }
268         wprintf("</select>\n");
269         wprintf("</td></tr>\n");
270
271         /**
272          * Calendar day view -- day end time
273          */
274         get_preference("dayend", buf, sizeof buf);
275         if (buf[0] == 0) strcpy(buf, "17");
276         wprintf("<tr class=\"odd\"><td>");
277         wprintf(_("Calendar day view ends at:"));
278         wprintf("</td><td>");
279
280         wprintf("<select name=\"dayend\" size=\"1\">\n");
281         for (i=0; i<=23; ++i) {
282
283                 if (time_format == WC_TIMEFORMAT_24) {
284                         wprintf("<option %s value=\"%d\">%d:00</option>\n",
285                                 ((atoi(buf) == i) ? "selected" : ""),
286                                 i, i
287                         );
288                 }
289                 else {
290                         wprintf("<option %s value=\"%d\">%s</option>\n",
291                                 ((atoi(buf) == i) ? "selected" : ""),
292                                 i, hourname[i]
293                         );
294                 }
295
296         }
297         wprintf("</select>\n");
298         wprintf("</td></tr>\n");
299
300         /**
301          * Day of week to begin calendar month view
302          */
303         get_preference("weekstart", buf, sizeof buf);
304         if (buf[0] == 0) strcpy(buf, "17");
305         wprintf("<tr class=\"even\"><td>");
306         wprintf(_("Week starts on:"));
307         wprintf("</td><td>");
308
309         wprintf("<select name=\"weekstart\" size=\"1\">\n");
310
311         for (i=0; i<=1; ++i) {
312                 tt = time(NULL);
313                 localtime_r(&tt, &tm);
314                 tm.tm_wday = i;
315                 wc_strftime(daylabel, sizeof daylabel, "%A", &tm);
316
317                 wprintf("<option %s value=\"%d\">%s</option>\n",
318                         ((atoi(buf) == i) ? "selected" : ""),
319                         i, daylabel
320                 );
321         }
322
323         wprintf("</select>\n");
324         wprintf("</td></tr>\n");
325
326         /**
327          * Signature
328          */
329         get_preference("use_sig", buf, sizeof buf);
330         if (buf[0] == 0) strcpy(buf, "no");
331         wprintf("<tr class=\"odd\"><td>");
332         wprintf(_("Attach signature to email messages?"));
333         wprintf("</td><td>");
334
335         wprintf("       <script type=\"text/javascript\">                                       "
336                 "       function show_or_hide_sigbox() {                                        "
337                 "               if ( $F('yes_sig') ) {                                          "
338                 "                       $('signature_box').style.display = 'inline';            "
339                 "               }                                                               "
340                 "               else {                                                          "
341                 "                       $('signature_box').style.display = 'none';              "
342                 "               }                                                               "
343                 "       }                                                                       "
344                 "       </script>                                                               "
345         );
346
347         wprintf("<input type=\"radio\" id=\"no_sig\" name=\"use_sig\" VALUE=\"no\"");
348         if (!strcasecmp(buf, "no")) wprintf(" checked");
349         wprintf(" onChange=\"show_or_hide_sigbox();\" >");
350         wprintf(_("No signature"));
351         wprintf("</input>&nbsp,&nbsp;&nbsp;\n");
352
353         wprintf("<input type=\"radio\" id=\"yes_sig\" name=\"use_sig\" VALUE=\"yes\"");
354         if (!strcasecmp(buf, "yes")) wprintf(" checked");
355         wprintf(" onChange=\"show_or_hide_sigbox();\" >");
356         wprintf(_("Use this signature:"));
357         wprintf("<div id=\"signature_box\">"
358                 "<br><textarea name=\"signature\" cols=\"40\" rows=\"5\">"
359         );
360         get_preference("signature", ebuf, sizeof ebuf);
361         euid_unescapize(buf, ebuf);
362         escputs(buf);
363         wprintf("</textarea>"
364                 "</div>"
365         );
366
367         wprintf("</input>\n");
368
369         wprintf("</td></tr>\n");
370
371         wprintf("       <script type=\"text/javascript\">       "
372                 "       show_or_hide_sigbox();                  "
373                 "       </script>                               "
374         );
375
376         /** Character set to assume is in use for improperly encoded headers */
377         get_preference("default_header_charset", buf, sizeof buf);
378         if (buf[0] == 0) strcpy(buf, "UTF-8");
379         wprintf("<tr class=\"even\"><td>");
380         wprintf(_("Default character set for email headers:"));
381         wprintf("</td><td>");
382         wprintf("<input type=\"text\" NAME=\"default_header_charset\" MAXLENGTH=\"32\" VALUE=\"");
383         escputs(buf);
384         wprintf("\">");
385         wprintf("</td></tr>");
386
387         /**
388          * Show empty floors?
389          */
390
391         get_preference("emptyfloors", buf, sizeof buf);
392         if (buf[0] == 0) strcpy(buf, "no");
393         wprintf("<tr class=\"odd\"><td>");
394         wprintf(_("Show empty floors"));
395         wprintf("</td><td>");
396
397         wprintf("<input type=\"radio\" name=\"emptyfloors\" VALUE=\"yes\"");
398         if (!strcasecmp(buf, "yes")) wprintf(" checked");
399         wprintf(">");
400         wprintf(_("Yes"));
401         wprintf("</input>&nbsp;&nbsp;&nbsp;");
402
403         wprintf("<input type=\"radio\" name=\"emptyfloors\" VALUE=\"no\"");
404         if (!strcasecmp(buf, "no")) wprintf(" checked");
405         wprintf(">");
406         wprintf(_("No"));
407         wprintf("</input>\n");
408
409         wprintf("</td></tr>\n");
410
411         /** end table */
412         wprintf("</table>\n");
413
414         /** submit buttons */
415         wprintf("<div class=\"buttons\"> ");
416         wprintf("<input type=\"submit\" name=\"change_button\" value=\"%s\">"
417                 "&nbsp;"
418                 "<INPUT type=\"submit\" name=\"cancel_button\" value=\"%s\">\n",
419                 _("Change"),
420                 _("Cancel")
421         );
422         wprintf("</div>\n");
423
424         /** end form */
425         wprintf("</form>\n");
426         wprintf("</div>\n");
427         wDumpContent(1);
428 }
429
430 /**
431  * \brief Commit new preferences and settings
432  */
433 void set_preferences(void)
434 {
435         char *fmt;
436         char ebuf[300];
437         int *time_format_cache;
438         
439         time_format_cache = &(WC->time_format_cache);
440
441         if (IsEmptyStr(bstr("change_button"))) {
442                 safestrncpy(WC->ImportantMessage, 
443                         _("Cancelled.  No settings were changed."),
444                         sizeof WC->ImportantMessage);
445                 display_main_menu();
446                 return;
447         }
448
449         /**
450          * Set the last argument to 1 only for the final setting, so
451          * we don't send the prefs file to the server repeatedly
452          */
453         set_preference("roomlistview", bstr("roomlistview"), 0);
454         fmt = bstr("calhourformat");
455         set_preference("calhourformat", fmt, 0);
456         if (!strcasecmp(fmt, "24")) 
457                 *time_format_cache = WC_TIMEFORMAT_24;
458         else
459                 *time_format_cache = WC_TIMEFORMAT_AMPM;
460
461         set_preference("weekstart", bstr("weekstart"), 0);
462         set_preference("use_sig", bstr("use_sig"), 0);
463         set_preference("daystart", bstr("daystart"), 0);
464         set_preference("dayend", bstr("dayend"), 0);
465         set_preference("default_header_charset", bstr("default_header_charset"), 0);
466         set_preference("emptyfloors", bstr("emptyfloors"), 0);
467
468         euid_escapize(ebuf, bstr("signature"));
469         set_preference("signature", ebuf, 1);
470
471         display_main_menu();
472 }
473
474
475 /*@}*/