summaryrefslogtreecommitdiffabout
path: root/lib/configuration.cc
Side-by-side diff
Diffstat (limited to 'lib/configuration.cc') (more/less context) (show 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 @@
#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()");