7a93d44af096e10b43b155c49a502584d88cc3bc
[citadel.git] / webcit / siteconfig.c
1 /*
2  * Administrative screen for site-wide configuration
3  *
4  * Copyright (c) 1996-2012 by the citadel.org team
5  *
6  * This program is open source software.  You can redistribute it and/or
7  * modify it under the terms of the GNU General Public License, version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include "webcit.h"
16 #include "webserver.h"
17
18 HashList *ZoneHash = NULL;
19
20 ConstStr ExpirePolicyString = {CStrOf(roompolicy)     };
21
22 ConstStr ExpirePolicyStrings[][2] = {
23         { { CStrOf(roompolicy)     } , { strof(roompolicy)     "_value", sizeof(strof(roompolicy)     "_value") - 1 } },
24         { { CStrOf(floorpolicy)    } , { strof(floorpolicy)    "_value", sizeof(strof(floorpolicy)    "_value") - 1 } },
25         { { CStrOf(sitepolicy)     } , { strof(sitepolicy)     "_value", sizeof(strof(sitepolicy)     "_value") - 1 } },
26         { { CStrOf(mailboxespolicy)} , { strof(mailboxespolicy)"_value", sizeof(strof(mailboxespolicy)"_value") - 1 } }
27 };
28
29 void LoadExpirePolicy(GPEXWhichPolicy which)
30 {
31         StrBuf *Buf;
32         wcsession *WCC = WC;
33         long State;
34         const char *Pos = NULL;
35
36         serv_printf("GPEX %s", ExpirePolicyStrings[which][0].Key);
37         Buf = NewStrBuf();
38         StrBuf_ServGetln(Buf);
39         WCC->Policy[which].loaded = 1;
40         if (GetServerStatus(Buf, &State) == 2) {
41                 Pos = ChrPtr(Buf) + 4;
42                 WCC->Policy[which].expire_mode = StrBufExtractNext_long(Buf, &Pos, '|');
43                 WCC->Policy[which].expire_value = StrBufExtractNext_long(Buf, &Pos, '|');
44         }
45         else if (State == 550)
46                 AppendImportantMessage(_("Higher access is required to access this function."), -1);
47         FreeStrBuf(&Buf);
48 }
49
50 void SaveExpirePolicyFromHTTP(GPEXWhichPolicy which)
51 {
52         StrBuf *Buf;
53         long State;
54
55         serv_printf("SPEX %s|%d|%d", 
56                             ExpirePolicyStrings[which][0].Key,
57                     ibcstr( ExpirePolicyStrings[which][1] ),
58                     ibcstr( ExpirePolicyStrings[which][1] )  );
59
60         Buf = NewStrBuf();
61         StrBuf_ServGetln(Buf);
62         GetServerStatus(Buf, &State);
63         if (State == 550)
64                 AppendImportantMessage(_("Higher access is required to access this function."), -1);
65         FreeStrBuf(&Buf);
66 }
67
68 int ConditionalExpire(StrBuf *Target, WCTemplputParams *TP)
69 {
70         wcsession *WCC = WC;
71         GPEXWhichPolicy which;
72         int CompareWith;
73
74         which = GetTemplateTokenNumber(Target, TP, 2, 0);
75         CompareWith = GetTemplateTokenNumber(Target, TP, 3, 0);
76
77         LoadExpirePolicy(which);
78         
79         return WCC->Policy[which].expire_mode == CompareWith;
80 }
81
82 void tmplput_ExpireValue(StrBuf *Target, WCTemplputParams *TP)
83 {
84         GPEXWhichPolicy which;
85         wcsession *WCC = WC;
86                 
87         which = GetTemplateTokenNumber(Target, TP, 0, 0);
88         LoadExpirePolicy(which);
89         StrBufAppendPrintf(Target, "%d", WCC->Policy[which].expire_value);
90 }
91
92
93 void tmplput_ExpireMode(StrBuf *Target, WCTemplputParams *TP)
94 {
95         GPEXWhichPolicy which;
96         wcsession *WCC = WC;
97                 
98         which = GetTemplateTokenNumber(Target, TP, 2, 0);
99         LoadExpirePolicy(which);
100         StrBufAppendPrintf(Target, "%d", WCC->Policy[which].expire_mode);
101 }
102
103
104 void LoadZoneFiles(void)
105 {
106         icalarray *zones;
107         int z;
108         long len;
109         const char *this_zone;
110         StrBuf *ZName;
111         
112         ZoneHash = NewHash(1, NULL);
113         ZName = NewStrBufPlain(HKEY("UTC"));
114         Put(ZoneHash, HKEY("UTC"), ZName, HFreeStrBuf);
115         zones = icaltimezone_get_builtin_timezones();
116         for (z = 0; z < zones->num_elements; ++z) {
117                 /* syslog(9, "Location: %-40s tzid: %s\n",
118                         icaltimezone_get_location(icalarray_element_at(zones, z)),
119                         icaltimezone_get_tzid(icalarray_element_at(zones, z))
120                 ); */
121                 this_zone = icaltimezone_get_location(icalarray_element_at(zones, z));
122                 len = strlen(this_zone);
123                 ZName = NewStrBufPlain(this_zone, len);
124                 Put(ZoneHash, this_zone, len, ZName, HFreeStrBuf);
125         }
126         SortByHashKey(ZoneHash, 0);
127 }
128
129
130 typedef struct _CfgMapping {
131         int type;
132         const char *Key;
133         long len;
134 } CfgMapping;
135
136 #define CFG_STR 1
137 #define CFG_YES 2
138 #define CFG_NO 3
139
140 CfgMapping ServerConfig[] = {
141         {CFG_STR, HKEY("c_nodename")},
142         {CFG_STR, HKEY("c_fqdn")},
143         {CFG_STR, HKEY("c_humannode")},
144         {CFG_STR, HKEY("c_phonenum")},
145         {CFG_YES, HKEY("c_creataide")},
146         {CFG_STR, HKEY("c_sleeping")},
147         {CFG_STR, HKEY("c_initax")},
148         {CFG_YES, HKEY("c_regiscall")},
149         {CFG_YES, HKEY("c_twitdetect")},
150         {CFG_STR, HKEY("c_twitroom")},
151         {CFG_STR, HKEY("c_moreprompt")},
152         {CFG_YES, HKEY("c_restrict")},
153         {CFG_STR, HKEY("c_bbs_city")},
154         {CFG_STR, HKEY("c_sysadm")},
155         {CFG_STR, HKEY("c_maxsessions")},
156         {CFG_STR, HKEY("reserved1")},
157         {CFG_STR, HKEY("c_userpurge")},
158         {CFG_STR, HKEY("c_roompurge")},
159         {CFG_STR, HKEY("c_logpages")},
160         {CFG_STR, HKEY("c_createax")},
161         {CFG_STR, HKEY("c_maxmsglen")},
162         {CFG_STR, HKEY("c_min_workers")},
163         {CFG_STR, HKEY("c_max_workers")},
164         {CFG_STR, HKEY("c_pop3_port")},
165         {CFG_STR, HKEY("c_smtp_port")},
166         {CFG_NO , HKEY("c_rfc822_strict_from")},        /* note: reverse bool */
167         {CFG_YES, HKEY("c_aide_zap")},
168         {CFG_STR, HKEY("c_imap_port")},
169         {CFG_STR, HKEY("c_net_freq")},
170         {CFG_YES, HKEY("c_disable_newu")},
171         {CFG_STR, HKEY("reserved2")},
172         {CFG_STR, HKEY("c_purge_hour")},
173         {CFG_STR, HKEY("c_ldap_host")},
174         {CFG_STR, HKEY("c_ldap_port")},
175         {CFG_STR, HKEY("c_ldap_base_dn")},
176         {CFG_STR, HKEY("c_ldap_bind_dn")},
177         {CFG_STR, HKEY("c_ldap_bind_pw")},
178         {CFG_STR, HKEY("c_ip_addr")},
179         {CFG_STR, HKEY("c_msa_port")},
180         {CFG_STR, HKEY("c_imaps_port")},
181         {CFG_STR, HKEY("c_pop3s_port")},
182         {CFG_STR, HKEY("c_smtps_port")},
183         {CFG_YES, HKEY("c_enable_fulltext")},
184         {CFG_YES, HKEY("c_auto_cull")},
185         {CFG_YES, HKEY("c_instant_expunge")},
186         {CFG_YES, HKEY("c_allow_spoofing")},
187         {CFG_YES, HKEY("c_journal_email")},
188         {CFG_YES, HKEY("c_journal_pubmsgs")},
189         {CFG_STR, HKEY("c_journal_dest")},
190         {CFG_STR, HKEY("c_default_cal_zone")},
191         {CFG_STR, HKEY("c_pftcpdict_port")},
192         {CFG_STR, HKEY("c_mgesve_port")},
193         {CFG_STR, HKEY("c_auth_mode")},
194         {CFG_STR, HKEY("c_funambol_host")},
195         {CFG_STR, HKEY("c_funambol_port")},
196         {CFG_STR, HKEY("c_funambol_source")},
197         {CFG_STR, HKEY("c_funambol_auth")},
198         {CFG_YES, HKEY("c_rbl_at_greeting")},
199         {CFG_STR, HKEY("c_master_user")},
200         {CFG_STR, HKEY("c_master_pass")},
201         {CFG_STR, HKEY("c_pager_program")},
202         {CFG_YES, HKEY("c_imap_keep_from")},
203         {CFG_STR, HKEY("c_xmpp_c2s_port")},
204         {CFG_STR, HKEY("c_xmpp_s2s_port")},
205         {CFG_STR, HKEY("c_pop3_fetch")},
206         {CFG_STR, HKEY("c_pop3_fastest")},
207         {CFG_YES, HKEY("c_spam_flag_only")},
208         {CFG_YES, HKEY("c_guest_logins")}
209 };
210
211
212
213 /*
214  *  display all configuration items
215  */
216 void load_siteconfig(void)
217 {
218         wcsession *WCC = WC;
219         StrBuf *Buf;
220         HashList *Cfg;
221         long len;
222         int i, j;
223         
224         if (WCC->ServCfg == NULL)
225                 WCC->ServCfg = NewHash(1, NULL);
226         Cfg = WCC->ServCfg;
227
228         Buf = NewStrBuf();
229
230         serv_printf("CONF get");
231         StrBuf_ServGetln(Buf);
232         if (GetServerStatus(Buf, NULL) != 1) {
233                 StrBufCutLeft(Buf, 4);
234                 AppendImportantMessage(SKEY(Buf));
235                 FreeStrBuf(&Buf);
236                 return;
237                 
238         }
239         j = i = 0;
240         while (len = StrBuf_ServGetln(Buf),
241                (len >= 0) && 
242                ((len != 3) || strcmp(ChrPtr(Buf), "000")))
243         {
244                 if (i < (sizeof(ServerConfig) / sizeof(CfgMapping)))
245                 {
246                         Put(Cfg,
247                             ServerConfig[i].Key, 
248                             ServerConfig[i].len, 
249                             Buf, 
250                             HFreeStrBuf);
251                         i++;
252                         Buf = NewStrBuf();
253                 }
254                 else {
255                         if (j == 0)
256                                 AppendImportantMessage(_("WARNING: Failed to parse Server Config; do you run a to new citserver?"), -1);
257                         j++;
258                 }
259         }
260         FreeStrBuf(&Buf);
261
262         LoadExpirePolicy(roompolicy);
263         LoadExpirePolicy(floorpolicy);
264         LoadExpirePolicy(mailboxespolicy);
265         LoadExpirePolicy(sitepolicy);
266 }
267
268
269
270 /*
271  * parse siteconfig changes 
272  */
273 void siteconfig(void)
274 {
275         wcsession *WCC = WC;
276         int i;
277         StrBuf *Line;
278
279         if (strlen(bstr("ok_button")) == 0) {
280                 display_aide_menu();
281                 return;
282         }
283         Line = NewStrBuf();
284         serv_printf("CONF set");
285         StrBuf_ServGetln(Line);
286         if (GetServerStatusMsg(Line, NULL, 1, 4) != 4) {
287                 display_aide_menu();
288                 FreeStrBuf(&Line);
289                 return;
290         }
291
292         FreeStrBuf(&Line);
293
294         for (i=0; i < (sizeof(ServerConfig) / sizeof(CfgMapping)); i ++)
295         {
296                 switch (ServerConfig[i].type) {
297                 default:
298                 case CFG_STR:
299                         serv_putbuf(SBstr(ServerConfig[i].Key, ServerConfig[i].len));
300                         break;
301                 case CFG_YES:
302                         serv_puts(YesBstr(ServerConfig[i].Key, 
303                                           ServerConfig[i].len) ?
304                                   "1" : "0");
305                         break;
306                 case CFG_NO:
307                         serv_puts(YesBstr(ServerConfig[i].Key, 
308                                           ServerConfig[i].len) ?
309                                   "0" : "1");
310                         break;
311                 }
312         }
313         serv_puts("000");
314
315         SaveExpirePolicyFromHTTP(sitepolicy);
316         SaveExpirePolicyFromHTTP(mailboxespolicy);
317
318         FreeStrBuf(&WCC->serv_info->serv_default_cal_zone);
319         WCC->serv_info->serv_default_cal_zone = NewStrBufDup(sbstr("c_default_cal_zone"));
320
321         AppendImportantMessage(_("Your system configuration has been updated."), -1);
322         DeleteHash(&WCC->ServCfg);
323         display_aide_menu();
324 }
325
326 void tmplput_servcfg(StrBuf *Target, WCTemplputParams *TP)
327 {
328         wcsession *WCC = WC;
329         void *vBuf;
330         StrBuf *Buf;
331
332         if (WCC->is_aide) {
333                 if (WCC->ServCfg == NULL)
334                         load_siteconfig();
335                 GetHash(WCC->ServCfg, TKEY(0), &vBuf);
336                 Buf = (StrBuf*) vBuf;
337                 StrBufAppendTemplate(Target, TP, Buf, 1);
338         }
339 }
340
341 int ConditionalServCfg(StrBuf *Target, WCTemplputParams *TP)
342 {
343         wcsession *WCC = WC;
344         void *vBuf;
345         StrBuf *Buf;
346
347         if (WCC->is_aide) {
348                 if (WCC->ServCfg == NULL)
349                         load_siteconfig();
350                 GetHash(WCC->ServCfg, TKEY(2), &vBuf);
351                 if (vBuf == NULL) return 0;
352                 Buf = (StrBuf*) vBuf;
353                 if (TP->Tokens->nParameters == 3) {
354                         return 1;
355                 }
356                 else if (IS_NUMBER(TP->Tokens->Params[3]->Type))
357                         return (StrTol(Buf) == GetTemplateTokenNumber (Target, TP, 3, 0));
358                 else
359                 {
360                         const char *pch;
361                         long len;
362                         
363                         GetTemplateTokenString(Target, TP, 3, &pch, &len);
364                 
365                         return ((len == StrLength(Buf)) &&
366                                 (strcmp(pch, ChrPtr(Buf)) == 0));
367                 }
368
369         }
370         else return 0;
371 }
372
373 int ConditionalServCfgCTXStrBuf(StrBuf *Target, WCTemplputParams *TP)
374 {
375         wcsession *WCC = WC;
376         void *vBuf;
377         StrBuf *Buf;
378         StrBuf *ZoneToCheck = (StrBuf*) CTX;
379
380         if ((WCC->is_aide) || (ZoneToCheck == NULL)) {
381                 if (WCC->ServCfg == NULL)
382                         load_siteconfig();
383                 GetHash(WCC->ServCfg, TKEY(2), &vBuf);
384                 if (vBuf == NULL) return 0;
385                 Buf = (StrBuf*) vBuf;
386
387                 return strcmp(ChrPtr(Buf), ChrPtr(ZoneToCheck)) == 0;
388         }
389         else return 0;
390 }
391
392 /*----------------------------------------------------------------------------*
393  *              Displaying Logging                                            *
394  *----------------------------------------------------------------------------*/
395 typedef struct __LogStatusStruct {
396         int Enable;
397         StrBuf *Name;
398 }LogStatusStruct;
399
400 void DeleteLogStatusStruct(void *v)
401 {
402         LogStatusStruct *Stat = (LogStatusStruct*)v;
403
404         FreeStrBuf(&Stat->Name);
405         free(Stat);
406 }
407
408 void tmplput_servcfg_LogName(StrBuf *Target, WCTemplputParams *TP)
409 {
410         LogStatusStruct *Stat = (LogStatusStruct*) CTX;
411         StrBufAppendTemplate(Target, TP, Stat->Name, 1);
412 }
413
414 int ConditionalServCfgThisLogEnabled(StrBuf *Target, WCTemplputParams *TP)
415 {
416         LogStatusStruct *Stat = (LogStatusStruct*) CTX;
417         return Stat->Enable;
418 }
419
420 HashList *iterate_GetSrvLogEnable(StrBuf *Target, WCTemplputParams *TP)
421 {
422         HashList *Hash = NULL;
423         StrBuf *Buf;
424         LogStatusStruct *Stat;
425         const char *Pos;
426         int Done = 0;
427         long len;
428         int num_logs = 0;
429
430         serv_puts("LOGP");
431         Buf = NewStrBuf();
432         StrBuf_ServGetln(Buf);
433         if (GetServerStatus(Buf, NULL) == 1) {
434                 Hash = NewHash(1, Flathash);
435                 while (!Done) {
436                         len = StrBuf_ServGetln(Buf);
437                         if ((len <0) || 
438                             ((len == 3) &&
439                              !strcmp(ChrPtr(Buf), "000")))
440                         {
441                                 Done = 1;
442                                 break;
443                         }
444                         Stat = (LogStatusStruct*) malloc (sizeof(LogStatusStruct));
445                         Pos = NULL;
446                         Stat->Name = NewStrBufPlain(NULL, len);
447                         StrBufExtract_NextToken(Stat->Name, Buf, &Pos, '|');
448                         Stat->Enable = StrBufExtractNext_int(Buf, &Pos, '|');
449
450                         Put(Hash, IKEY(num_logs), Stat, DeleteLogStatusStruct); 
451                         num_logs++;
452                 }
453         }
454         FreeStrBuf(&Buf);
455         return Hash;
456 }
457
458
459 void 
460 InitModule_SITECONFIG
461 (void)
462 {
463         WebcitAddUrlHandler(HKEY("siteconfig"), "", 0, siteconfig, CTX_NONE);
464
465         RegisterNamespace("SERV:CFG", 1, 2, tmplput_servcfg, NULL, CTX_NONE);
466         RegisterConditional(HKEY("COND:SERVCFG"), 3, ConditionalServCfg, CTX_NONE);
467         RegisterConditional(HKEY("COND:SERVCFG:CTXSTRBUF"), 4, ConditionalServCfgCTXStrBuf, CTX_STRBUF);
468         RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, NULL, NULL, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
469
470         REGISTERTokenParamDefine(roompolicy);
471         REGISTERTokenParamDefine(floorpolicy);
472         REGISTERTokenParamDefine(sitepolicy);
473         REGISTERTokenParamDefine(mailboxespolicy);
474
475         REGISTERTokenParamDefine(EXPIRE_NEXTLEVEL);
476         REGISTERTokenParamDefine(EXPIRE_MANUAL);
477         REGISTERTokenParamDefine(EXPIRE_NUMMSGS);
478         REGISTERTokenParamDefine(EXPIRE_AGE);
479
480         RegisterConditional(HKEY("COND:EXPIRE:MODE"), 2, ConditionalExpire, CTX_NONE);
481         RegisterNamespace("EXPIRE:VALUE", 1, 2, tmplput_ExpireValue, NULL, CTX_NONE);
482         RegisterNamespace("EXPIRE:MODE", 1, 2, tmplput_ExpireMode, NULL, CTX_NONE);
483
484         RegisterConditional(HKEY("COND:SERVCFG:THISLOGENABLE"), 4, ConditionalServCfgThisLogEnabled, CTX_SRVLOG);
485         RegisterIterator("SERVCFG:LOGENABLE", 0, NULL, iterate_GetSrvLogEnable, NULL, DeleteHash, CTX_SRVLOG, CTX_NONE, IT_NOFLAG);
486         RegisterNamespace("SERVCFG:LOGNAME", 0, 1, tmplput_servcfg_LogName, NULL, CTX_SRVLOG);
487 }
488
489 void 
490 ServerStartModule_SITECONFIG
491 (void)
492 {
493         LoadZoneFiles();
494 }
495
496 void 
497 ServerShutdownModule_SITECONFIG
498 (void)
499 {
500         DeleteHash(&ZoneHash);
501 }
502
503
504 void 
505 SessionDestroyModule_SITECONFIG
506 (wcsession *sess)
507 {
508         DeleteHash(&sess->ServCfg);
509 }