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