-rw-r--r-- | lib/configuration.cc | 9 |
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 @@ #ifdef USE_PCH #include "pch.h" #else #include <unistd.h> #include <fnmatch.h> #include <cassert> #include <stdexcept> using namespace std; + #include <konforka/util.h> #include <dotconf.h> #include "sitecing/configuration.h" #include "sitecing/sitecing_util.h" #include "sitecing/scoreboard.h" #endif namespace sitecing { configuration::configuration() : flags(0), autobuild(false) { } configuration::configuration(const string& cfile,bool ab) : flags(0), autobuild(ab) { parse(cfile); } enum dc_ctx { DCC_ROOT = 1, DCC_PATH = 2, DCC_SCRC = 4 }; struct dc_context { dc_ctx ctx; configuration* cf; list<config_options*> co; }; static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; dcc->cf->root_source = cmd->data.str; dcc->cf->flags |= configuration::flag_root_source; return NULL; } static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; dcc->cf->root_intermediate = cmd->data.str; dcc->cf->flags |= configuration::flag_root_intermediate; return NULL; } static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; dcc->cf->root_so = cmd->data.str; dcc->cf->flags |= configuration::flag_root_so; return NULL; } static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; dcc->cf->listen_socket = cmd->data.str; dcc->cf->flags |= configuration::flag_listen_socket; return NULL; } static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; dcc->cf->rc_file_name = cmd->data.str; @@ -259,207 +260,207 @@ namespace sitecing { if(stat(source_file.c_str(),&nst)) return false; if(st.st_mtime!=nst.st_mtime) return false; return true; } loaded_options *configuration::lookup_loaded_options(const string& target) { // we assume 'target' is a directory with trailing slash appended string scrc = root_source+target; if(flags&flag_rc_file_name) scrc += rc_file_name; else scrc += ".scrc"; // TODO: normalize me, anyway. if(access(scrc.c_str(),R_OK)) return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal loaded_specs_t::iterator i = loaded_specs.find(target); if(i==loaded_specs.end() || !i->second.is_valid()) { if(i!=loaded_specs.end()) loaded_specs.erase(i); pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); assert(ii.first!=loaded_specs.end()); ii.first->second.parse(this,scrc); i = ii.first; } assert(i!=loaded_specs.end()); return &(i->second); } config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { if(i->regex.search(target)) return &*i; } return NULL; } string config_options::lookup_http_status_handler(const string& status) { http_status_handlers_t::const_iterator i = http_status_handlers.find(status); string rv; if(i!=http_status_handlers.end()) rv = i->second; return rv; } string configuration::lookup_http_status_handler(const string& target,const string& status) { string t = "/"; - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); string rv; for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { rv = lo->lookup_http_status_handler(status); if(!rv.empty()) return rv; } } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { rv = i->second.lookup_http_status_handler(status); if(!rv.empty()) return rv; } if(t.empty()) return rv; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { string t = "/"; - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_action_handlers) ) { config_options::action_handler_t *rv = lo->lookup_action_handler(target); if(rv) return rv; } } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { config_options::action_handler_t *rv = i->second.lookup_action_handler(target); if(rv) return rv; } if(t.empty()) return NULL; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } config_options* configuration::lookup_config(const string& target,int flag) { string t = "/"; // always assume leading slash - t += normalize_path(target,strip_leading_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash); // XXX: reconsider precedence for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if( lo && (lo->flags&flag)==flag ) return lo; } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&flag)==flag ) return &(i->second); if(t.empty()) return NULL; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } bool config_options::match_autobuild_files(const char *fn,bool &rv) { for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { const char *pat = i->c_str(); bool plus = true; if((*pat)=='+') pat++; else if((*pat)=='-') { plus = false; pat++; } if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { rv = plus; return true; } } return false; } bool configuration::match_autobuild_files(const string& target,const char *fn) { string t = "/"; - t += normalize_path(target,strip_leading_slash|strip_trailing_slash); + t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash); t += "/"; bool rv = false; for(;;) { if(t[t.length()-1]=='/') { loaded_options* lo = lookup_loaded_options(t); if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) return rv; } specs_t::iterator i = specs.find(t); if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) return rv; if(t.empty()) return rv; string::size_type sl=t.rfind('/'); if(sl==string::npos) { t.erase(); }else{ if(sl==(t.length()-1)) t.erase(sl); else t.erase(sl+1); } } } void configuration::parse(const string& cfile) { struct dc_context dcc; dcc.cf = this; dcc.ctx = DCC_ROOT; dcc.co.push_front(&root_options()); configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); if(!cf) throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; if(!dotconf_command_loop(cf)) throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); dotconf_cleanup(cf); } void loaded_options::parse(configuration *config,const string& cfile) { struct dc_context dcc; dcc.cf = config; dcc.ctx = DCC_SCRC; dcc.co.push_front(this); configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); if(!cf) throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); |