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