summaryrefslogtreecommitdiffabout
path: root/lib/configuration.cc
Unidiff
Diffstat (limited to 'lib/configuration.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/configuration.cc9
1 files changed, 5 insertions, 4 deletions
diff --git a/lib/configuration.cc b/lib/configuration.cc
index 4ee1526..6b21690 100644
--- a/lib/configuration.cc
+++ b/lib/configuration.cc
@@ -1,56 +1,57 @@
1#ifdef USE_PCH 1#ifdef USE_PCH
2 #include "pch.h" 2 #include "pch.h"
3#else 3#else
4 #include <unistd.h> 4 #include <unistd.h>
5 #include <fnmatch.h> 5 #include <fnmatch.h>
6 #include <cassert> 6 #include <cassert>
7 #include <stdexcept> 7 #include <stdexcept>
8 using namespace std; 8 using namespace std;
9 #include <konforka/util.h>
9 #include <dotconf.h> 10 #include <dotconf.h>
10 #include "sitecing/configuration.h" 11 #include "sitecing/configuration.h"
11 #include "sitecing/sitecing_util.h" 12 #include "sitecing/sitecing_util.h"
12 #include "sitecing/scoreboard.h" 13 #include "sitecing/scoreboard.h"
13#endif 14#endif
14 15
15namespace sitecing { 16namespace sitecing {
16 17
17 configuration::configuration() 18 configuration::configuration()
18 : flags(0), autobuild(false) { } 19 : flags(0), autobuild(false) { }
19 configuration::configuration(const string& cfile,bool ab) 20 configuration::configuration(const string& cfile,bool ab)
20 : flags(0), autobuild(ab) { 21 : flags(0), autobuild(ab) {
21 parse(cfile); 22 parse(cfile);
22 } 23 }
23 24
24 enum dc_ctx { 25 enum dc_ctx {
25 DCC_ROOT = 1, 26 DCC_ROOT = 1,
26 DCC_PATH = 2, 27 DCC_PATH = 2,
27 DCC_SCRC = 4 28 DCC_SCRC = 4
28 }; 29 };
29 struct dc_context { 30 struct dc_context {
30 dc_ctx ctx; 31 dc_ctx ctx;
31 configuration* cf; 32 configuration* cf;
32 list<config_options*> co; 33 list<config_options*> co;
33 }; 34 };
34 35
35 static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; 36 static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx;
36 dcc->cf->root_source = cmd->data.str; 37 dcc->cf->root_source = cmd->data.str;
37 dcc->cf->flags |= configuration::flag_root_source; 38 dcc->cf->flags |= configuration::flag_root_source;
38 return NULL; 39 return NULL;
39 } 40 }
40 static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; 41 static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx;
41 dcc->cf->root_intermediate = cmd->data.str; 42 dcc->cf->root_intermediate = cmd->data.str;
42 dcc->cf->flags |= configuration::flag_root_intermediate; 43 dcc->cf->flags |= configuration::flag_root_intermediate;
43 return NULL; 44 return NULL;
44 } 45 }
45 static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; 46 static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx;
46 dcc->cf->root_so = cmd->data.str; 47 dcc->cf->root_so = cmd->data.str;
47 dcc->cf->flags |= configuration::flag_root_so; 48 dcc->cf->flags |= configuration::flag_root_so;
48 return NULL; 49 return NULL;
49 } 50 }
50 static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; 51 static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx;
51 dcc->cf->listen_socket = cmd->data.str; 52 dcc->cf->listen_socket = cmd->data.str;
52 dcc->cf->flags |= configuration::flag_listen_socket; 53 dcc->cf->flags |= configuration::flag_listen_socket;
53 return NULL; 54 return NULL;
54 } 55 }
55 static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; 56 static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx;
56 dcc->cf->rc_file_name = cmd->data.str; 57 dcc->cf->rc_file_name = cmd->data.str;
@@ -259,207 +260,207 @@ namespace sitecing {
259 if(stat(source_file.c_str(),&nst)) 260 if(stat(source_file.c_str(),&nst))
260 return false; 261 return false;
261 if(st.st_mtime!=nst.st_mtime) 262 if(st.st_mtime!=nst.st_mtime)
262 return false; 263 return false;
263 return true; 264 return true;
264 } 265 }
265 266
266 loaded_options *configuration::lookup_loaded_options(const string& target) { 267 loaded_options *configuration::lookup_loaded_options(const string& target) {
267 // we assume 'target' is a directory with trailing slash appended 268 // we assume 'target' is a directory with trailing slash appended
268 string scrc = root_source+target; 269 string scrc = root_source+target;
269 if(flags&flag_rc_file_name) 270 if(flags&flag_rc_file_name)
270 scrc += rc_file_name; 271 scrc += rc_file_name;
271 else 272 else
272 scrc += ".scrc"; 273 scrc += ".scrc";
273 // TODO: normalize me, anyway. 274 // TODO: normalize me, anyway.
274 if(access(scrc.c_str(),R_OK)) 275 if(access(scrc.c_str(),R_OK))
275 return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal 276 return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal
276 loaded_specs_t::iterator i = loaded_specs.find(target); 277 loaded_specs_t::iterator i = loaded_specs.find(target);
277 if(i==loaded_specs.end() || !i->second.is_valid()) { 278 if(i==loaded_specs.end() || !i->second.is_valid()) {
278 if(i!=loaded_specs.end()) 279 if(i!=loaded_specs.end())
279 loaded_specs.erase(i); 280 loaded_specs.erase(i);
280 pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); 281 pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options()));
281 assert(ii.first!=loaded_specs.end()); 282 assert(ii.first!=loaded_specs.end());
282 ii.first->second.parse(this,scrc); 283 ii.first->second.parse(this,scrc);
283 i = ii.first; 284 i = ii.first;
284 } 285 }
285 assert(i!=loaded_specs.end()); 286 assert(i!=loaded_specs.end());
286 return &(i->second); 287 return &(i->second);
287 } 288 }
288 289
289 config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { 290 config_options::action_handler_t *config_options::lookup_action_handler(const string& target) {
290 for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { 291 for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) {
291 if(i->regex.search(target)) 292 if(i->regex.search(target))
292 return &*i; 293 return &*i;
293 } 294 }
294 return NULL; 295 return NULL;
295 } 296 }
296 297
297 string config_options::lookup_http_status_handler(const string& status) { 298 string config_options::lookup_http_status_handler(const string& status) {
298 http_status_handlers_t::const_iterator i = http_status_handlers.find(status); 299 http_status_handlers_t::const_iterator i = http_status_handlers.find(status);
299 string rv; 300 string rv;
300 if(i!=http_status_handlers.end()) 301 if(i!=http_status_handlers.end())
301 rv = i->second; 302 rv = i->second;
302 return rv; 303 return rv;
303 } 304 }
304 305
305 string configuration::lookup_http_status_handler(const string& target,const string& status) { 306 string configuration::lookup_http_status_handler(const string& target,const string& status) {
306 string t = "/"; 307 string t = "/";
307 t += normalize_path(target,strip_leading_slash); 308 t += konforka::normalize_path(target,konforka::strip_leading_slash);
308 string rv; 309 string rv;
309 for(;;) { 310 for(;;) {
310 if(t[t.length()-1]=='/') { 311 if(t[t.length()-1]=='/') {
311 loaded_options* lo = lookup_loaded_options(t); 312 loaded_options* lo = lookup_loaded_options(t);
312 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { 313 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) {
313 rv = lo->lookup_http_status_handler(status); 314 rv = lo->lookup_http_status_handler(status);
314 if(!rv.empty()) 315 if(!rv.empty())
315 return rv; 316 return rv;
316 } 317 }
317 } 318 }
318 specs_t::iterator i = specs.find(t); 319 specs_t::iterator i = specs.find(t);
319 if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { 320 if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) {
320 rv = i->second.lookup_http_status_handler(status); 321 rv = i->second.lookup_http_status_handler(status);
321 if(!rv.empty()) 322 if(!rv.empty())
322 return rv; 323 return rv;
323 } 324 }
324 if(t.empty()) 325 if(t.empty())
325 return rv; 326 return rv;
326 string::size_type sl=t.rfind('/'); 327 string::size_type sl=t.rfind('/');
327 if(sl==string::npos) { 328 if(sl==string::npos) {
328 t.erase(); 329 t.erase();
329 }else{ 330 }else{
330 if(sl==(t.length()-1)) 331 if(sl==(t.length()-1))
331 t.erase(sl); 332 t.erase(sl);
332 else 333 else
333 t.erase(sl+1); 334 t.erase(sl+1);
334 } 335 }
335 } 336 }
336 } 337 }
337 338
338 config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { 339 config_options::action_handler_t *configuration::lookup_action_handler(const string& target) {
339 string t = "/"; 340 string t = "/";
340 t += normalize_path(target,strip_leading_slash); 341 t += konforka::normalize_path(target,konforka::strip_leading_slash);
341 for(;;) { 342 for(;;) {
342 if(t[t.length()-1]=='/') { 343 if(t[t.length()-1]=='/') {
343 loaded_options* lo = lookup_loaded_options(t); 344 loaded_options* lo = lookup_loaded_options(t);
344 if( lo && (lo->flags&config_options::flag_action_handlers) ) { 345 if( lo && (lo->flags&config_options::flag_action_handlers) ) {
345 config_options::action_handler_t *rv = lo->lookup_action_handler(target); 346 config_options::action_handler_t *rv = lo->lookup_action_handler(target);
346 if(rv) 347 if(rv)
347 return rv; 348 return rv;
348 } 349 }
349 } 350 }
350 specs_t::iterator i = specs.find(t); 351 specs_t::iterator i = specs.find(t);
351 if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { 352 if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) {
352 config_options::action_handler_t *rv = i->second.lookup_action_handler(target); 353 config_options::action_handler_t *rv = i->second.lookup_action_handler(target);
353 if(rv) 354 if(rv)
354 return rv; 355 return rv;
355 } 356 }
356 if(t.empty()) 357 if(t.empty())
357 return NULL; 358 return NULL;
358 string::size_type sl=t.rfind('/'); 359 string::size_type sl=t.rfind('/');
359 if(sl==string::npos) { 360 if(sl==string::npos) {
360 t.erase(); 361 t.erase();
361 }else{ 362 }else{
362 if(sl==(t.length()-1)) 363 if(sl==(t.length()-1))
363 t.erase(sl); 364 t.erase(sl);
364 else 365 else
365 t.erase(sl+1); 366 t.erase(sl+1);
366 } 367 }
367 } 368 }
368 } 369 }
369 370
370 config_options* configuration::lookup_config(const string& target,int flag) { 371 config_options* configuration::lookup_config(const string& target,int flag) {
371 string t = "/"; // always assume leading slash 372 string t = "/"; // always assume leading slash
372 t += normalize_path(target,strip_leading_slash); 373 t += konforka::normalize_path(target,konforka::strip_leading_slash);
373 // XXX: reconsider precedence 374 // XXX: reconsider precedence
374 for(;;) { 375 for(;;) {
375 if(t[t.length()-1]=='/') { 376 if(t[t.length()-1]=='/') {
376 loaded_options* lo = lookup_loaded_options(t); 377 loaded_options* lo = lookup_loaded_options(t);
377 if( lo && (lo->flags&flag)==flag ) 378 if( lo && (lo->flags&flag)==flag )
378 return lo; 379 return lo;
379 } 380 }
380 specs_t::iterator i = specs.find(t); 381 specs_t::iterator i = specs.find(t);
381 if( i!=specs.end() && (i->second.flags&flag)==flag ) 382 if( i!=specs.end() && (i->second.flags&flag)==flag )
382 return &(i->second); 383 return &(i->second);
383 if(t.empty()) 384 if(t.empty())
384 return NULL; 385 return NULL;
385 string::size_type sl=t.rfind('/'); 386 string::size_type sl=t.rfind('/');
386 if(sl==string::npos) { 387 if(sl==string::npos) {
387 t.erase(); 388 t.erase();
388 }else{ 389 }else{
389 if(sl==(t.length()-1)) 390 if(sl==(t.length()-1))
390 t.erase(sl); 391 t.erase(sl);
391 else 392 else
392 t.erase(sl+1); 393 t.erase(sl+1);
393 } 394 }
394 } 395 }
395 } 396 }
396 397
397 bool config_options::match_autobuild_files(const char *fn,bool &rv) { 398 bool config_options::match_autobuild_files(const char *fn,bool &rv) {
398 for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { 399 for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) {
399 const char *pat = i->c_str(); 400 const char *pat = i->c_str();
400 bool plus = true; 401 bool plus = true;
401 if((*pat)=='+') 402 if((*pat)=='+')
402 pat++; 403 pat++;
403 else if((*pat)=='-') { 404 else if((*pat)=='-') {
404 plus = false; 405 plus = false;
405 pat++; 406 pat++;
406 } 407 }
407 if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { 408 if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) {
408 rv = plus; 409 rv = plus;
409 return true; 410 return true;
410 } 411 }
411 } 412 }
412 return false; 413 return false;
413 } 414 }
414 415
415 bool configuration::match_autobuild_files(const string& target,const char *fn) { 416 bool configuration::match_autobuild_files(const string& target,const char *fn) {
416 string t = "/"; 417 string t = "/";
417 t += normalize_path(target,strip_leading_slash|strip_trailing_slash); 418 t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash);
418 t += "/"; 419 t += "/";
419 bool rv = false; 420 bool rv = false;
420 for(;;) { 421 for(;;) {
421 if(t[t.length()-1]=='/') { 422 if(t[t.length()-1]=='/') {
422 loaded_options* lo = lookup_loaded_options(t); 423 loaded_options* lo = lookup_loaded_options(t);
423 if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) 424 if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) )
424 return rv; 425 return rv;
425 } 426 }
426 specs_t::iterator i = specs.find(t); 427 specs_t::iterator i = specs.find(t);
427 if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) 428 if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) )
428 return rv; 429 return rv;
429 if(t.empty()) 430 if(t.empty())
430 return rv; 431 return rv;
431 string::size_type sl=t.rfind('/'); 432 string::size_type sl=t.rfind('/');
432 if(sl==string::npos) { 433 if(sl==string::npos) {
433 t.erase(); 434 t.erase();
434 }else{ 435 }else{
435 if(sl==(t.length()-1)) 436 if(sl==(t.length()-1))
436 t.erase(sl); 437 t.erase(sl);
437 else 438 else
438 t.erase(sl+1); 439 t.erase(sl+1);
439 } 440 }
440 } 441 }
441 } 442 }
442 443
443 void configuration::parse(const string& cfile) { 444 void configuration::parse(const string& cfile) {
444 struct dc_context dcc; 445 struct dc_context dcc;
445 dcc.cf = this; 446 dcc.cf = this;
446 dcc.ctx = DCC_ROOT; 447 dcc.ctx = DCC_ROOT;
447 dcc.co.push_front(&root_options()); 448 dcc.co.push_front(&root_options());
448 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); 449 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE);
449 if(!cf) 450 if(!cf)
450 throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); 451 throw konforka::exception(CODEPOINT,"failed to dotconf_create()");
451 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; 452 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler;
452 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; 453 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker;
453 if(!dotconf_command_loop(cf)) 454 if(!dotconf_command_loop(cf))
454 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); 455 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()");
455 dotconf_cleanup(cf); 456 dotconf_cleanup(cf);
456 } 457 }
457 458
458 void loaded_options::parse(configuration *config,const string& cfile) { 459 void loaded_options::parse(configuration *config,const string& cfile) {
459 struct dc_context dcc; 460 struct dc_context dcc;
460 dcc.cf = config; 461 dcc.cf = config;
461 dcc.ctx = DCC_SCRC; 462 dcc.ctx = DCC_SCRC;
462 dcc.co.push_front(this); 463 dcc.co.push_front(this);
463 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); 464 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE);
464 if(!cf) 465 if(!cf)
465 throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); 466 throw konforka::exception(CODEPOINT,"failed to dotconf_create()");