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