-rw-r--r-- | components/exception_dev | 7 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | include/sitecing/sitecing_util.h | 85 | ||||
-rw-r--r-- | lib/component_factory.cc | 31 | ||||
-rw-r--r-- | lib/configuration.cc | 9 | ||||
-rw-r--r-- | lib/sitecing_parser.ll | 13 | ||||
-rw-r--r-- | lib/sitecing_util.cc | 117 | ||||
-rw-r--r-- | lib/sitespace.cc | 3 | ||||
-rw-r--r-- | src/sitecing-build.cc | 5 | ||||
-rw-r--r-- | src/sitecing-fastcgi.cc | 4 | ||||
-rw-r--r-- | src/sitecing-plaincgi.cc | 4 |
11 files changed, 47 insertions, 235 deletions
diff --git a/components/exception_dev b/components/exception_dev index d8c84e1..d62f462 100644 --- a/components/exception_dev +++ b/components/exception_dev @@ -1,24 +1,25 @@ %%decl using namespace std; <%impl> #include <iostream> #include <fstream> #include <sstream> #include <cassert> #include <cstdarg> #include <stdexcept> #include <cxxabi.h> #include <sitecing/sitecing_util.h> #include <sitecing/util.h> #include <sitecing/magic.h> + #include <konforka/util.h> #include <konforka/exception.h> </%impl> %%var string message; %%var string root_source; %%var string root_intermediate; %%var string root_so; %%var string component; %%var int line_number = -1; %%var const exception* exception_caught; <%code> __SCIF->headers.clear(); __SCIF->out->seekp(0); @@ -245,35 +246,35 @@ string::size_type nd = ln.find_first_not_of("0123456789"); if(nd==string::npos) { try { error_file = sitecing::strip_prefix(fn,"In file included from "); }catch(sitecing::utility_no_prefix& unp) { error_file = fn; } error_line = strtol(ln.c_str(),0,10); } } } if((oel>0 && !oef.empty()) && (oel!=error_line || oef!=error_file)) { - string ef = "/"+sitecing::combine_path(root_source+component,oef); + string ef = "/"+konforka::combine_path(root_source+component,oef); report_error(ef,oel,remove_roots(cumulative)); cumulative.clear(); } } if(!cumulative.empty()) cumulative += '\n'; cumulative += line; } if(!(cumulative.empty() || error_file.empty() || error_line<0)) { - error_file = "/"+sitecing::combine_path(root_source+component,error_file); + error_file = "/"+konforka::combine_path(root_source+component,error_file); report_error(error_file,error_line,remove_roots(cumulative)); } } </%code> </div> </%method> <%method void handle_unknown_error() %> <div class="exception-unknown"> <h1>unknown error</h1> </div> </%method> <%method void report_error(const string& file,long line,const string& message) %> @@ -309,25 +310,25 @@ } <%output></ul></%output> } } } </%code> <div class="what"> <% sitecing::html_escape(message,sitecing::html_escape_br) %> </div> </div> </%method> <%codemethod string strip_roots(const string& filename) %> - string np = sitecing::normalize_path(filename); + string np = konforka::normalize_path(filename); try{ return sitecing::strip_prefix(np,root_source); }catch(sitecing::utility_no_prefix& e){ } try{ return sitecing::strip_prefix(np,root_intermediate); }catch(sitecing::utility_no_prefix& e){ } </%codemethod> <%codemethod string remove_roots(const string& str) %> string rv = str; string::size_type rp; string::size_type rl = root_source.length(); while((rp=rv.find(root_source))!=string::npos) { diff --git a/configure.ac b/configure.ac index a8aa142..fde326b 100644 --- a/configure.ac +++ b/configure.ac @@ -11,24 +11,28 @@ AM_PROG_LEX AC_PROG_LIBTOOL AC_HEADER_STDC AC_CHECK_HEADERS([stdlib.h unistd.h]) AC_C_CONST AC_FUNC_MALLOC AC_FUNC_REALLOC AC_WITH_PKGCONFIG +PKG_CHECK_MODULES([KONFORKA],[konforka >= 0.0.1],,[ + AC_MSG_ERROR([no proper version of konforka library found, get it at http://kin.klever.net/konforka/]) +]) + PKG_CHECK_MODULES([KINGATE],[kingate >= 0.0.1],,[ AC_MSG_ERROR([no kingate library found, get it at http://kin.klever.net/kingate/]) ]) HAVE_FCGI=false HAVE_PLAINCGI=false PKG_CHECK_MODULES([KINGATE_FCGI],[kingate-fcgi >= 0.0.1],[ HAVE_FCGI=true ],[ AC_MSG_NOTICE([no fastcgi support in kingate library]) ]) PKG_CHECK_MODULES([KINGATE_PLAINCGI],[kingate-plaincgi >= 0.0.1],[ HAVE_PLAINCGI=true diff --git a/include/sitecing/sitecing_util.h b/include/sitecing/sitecing_util.h index d1a6c4a..f642c74 100644 --- a/include/sitecing/sitecing_util.h +++ b/include/sitecing/sitecing_util.h @@ -1,43 +1,37 @@ #ifndef __SITECING_SITECING_UTIL_H #define __SITECING_SITECING_UTIL_H #include <sys/types.h> #include <string> #include <konforka/exception.h> +#include <konforka/util.h> /** * @file * @brief utility classes and functions. */ namespace sitecing { using namespace std; /** * Base class for utility exceptions. */ class utility_error : public konforka::exception { public: utility_error(const string& fi,const string& fu,int l,const string& w) : konforka::exception(fi,fu,l,w) { } }; - /** - * Restricted sequence encountered. - */ - class utility_restricted_sequence : public utility_error { - public: - utility_restricted_sequence(const string& fi,const string& fu,int l,const string& w) - : utility_error(fi,fu,l,w) { } - }; + /** * No prefix or suffix found to strip out. */ class utility_no_affix : public utility_error { public: utility_no_affix(const string& fi,const string& fu,int l,const string& w) : utility_error(fi,fu,l,w) { } }; /** * No prefix to strip found. */ class utility_no_prefix : public utility_no_affix { @@ -46,34 +40,24 @@ namespace sitecing { : utility_no_affix(fi,fu,l,w) { } }; /** * No suffix to strip found. */ class utility_no_suffix : public utility_no_affix { public: utility_no_suffix(const string& fi,const string& fu,int l,const string& w) : utility_no_affix(fi,fu,l,w) { } }; /** - * Went up beyond root. - * @todo TODO: wish I could remember the details -- document me. - */ - class utility_beyond_root : public utility_error { - public: - utility_beyond_root(const string& fi,const string& fu,int l,const string& w) - : utility_error(fi,fu,l,w) { } - }; - - /** * The file lock object. Released at the object destruction. */ class file_lock { public: /** * The file descriptor. */ int fd; file_lock() : fd(-1) { } /** @@ -206,104 +190,39 @@ namespace sitecing { /** * Lock it. */ void lock(); /** * Unlock it. */ void unlock(); }; /** - * normalize_path options enumeration. - * @see normalize_path() - */ - enum normalize_path_options { - /** - * Restrict the /../ sequence. - */ - restrict_dotdot = 1, - /** - * Strip out the leading slash. - */ - strip_leading_slash = 2, - /** - * Strip out the trailing slash. - */ - strip_trailing_slash = 4 - }; - /** - * combine_path options enumeration. - * @see combine_path() - */ - enum combine_path_options { - /** - * The origin is file. Otherwise it is directory. - */ - origin_is_file = 1, - /** - * Fail if we've gone up beyond root. - */ - fail_beyond_root = 2 - }; - - /** - * Normalize pathname by stripping duplicate slashes, etc. - * @param path the path name. - * @param opts options. - * @return the normalized path. - * @see normalize_path_options - * @todo TODO: document exceptions. - */ - string normalize_path(const string& path,int opts=(restrict_dotdot|strip_trailing_slash)); - /** * Strip prefix from the string. * @param str the string. * @param prefix prefix to strip. * @return the string without prefix. * @todo TODO: document exceptions. */ string strip_prefix(const string& str,const string& prefix); /** * Strip suffix from the string. * @param str the string. * @param suffix suffix to strip. * @return the string without suffix. * @todo TODO: document exceptions. */ string strip_suffix(const string& str,const string& suffix); - /** - * Get the directory part of the filename. - * @param filename the full file name. - * @return the directory part. - */ - string dir_name(const string& filename); - /** - * Combine path with the relative path. - * @param origin the origin. - * @param relative relative path to combine origin with. - * @param opts options. - * @return the pathc combined. - * @see combine_path_options - * @todo TODO: document exceptions. - */ - string combine_path(const string& origin,const string& relative,int opts=origin_is_file); - - /** - * Create directory and parent directories if needed. - * @param path the pathname. - * @param mode the mode for newly created directories. - */ - void make_path(const string& path,mode_t mode); /** * Change to the directory and pop back at object's destruction (e.g. when * the object goes out of scope). */ class auto_chdir { public: /** * Saved working directory. */ string saved_pwd; /** diff --git a/lib/component_factory.cc b/lib/component_factory.cc index d9692de..af3d911 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc @@ -2,45 +2,46 @@ #include "pch.h" #else #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <sys/wait.h> #include <fcntl.h> #include <iostream> #include <fstream> #include <stdexcept> #include <vector> using namespace std; + #include <konforka/util.h> #include "sitecing/component_factory.h" #include "sitecing/sitecing_util.h" #include "sitecing/sitecing_parser.h" #include "sitecing/sitecing_exception.h" #endif namespace sitecing { static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; static const char *cc_targets[] = { ".o", ".d" }; component_factory::component_factory(configuration& c) : config(c), - root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), - root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), - root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { + root_source(konforka::normalize_path(c.root_source,konforka::strip_trailing_slash)+'/'), + root_intermediate(konforka::normalize_path(c.root_intermediate,konforka::strip_trailing_slash)+'/'), + root_so(konforka::normalize_path(c.root_so,konforka::strip_trailing_slash)+'/') { } void component_factory::get_dependencies(const string& dst,file_list_t& deps) { deps.clear(); - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); // source documents try { // XXX: or just compare it off? string noro = strip_prefix(dp,root_source); return; }catch(utility_no_affix& una) { } // .so binaries try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); deps.push_back(root_intermediate+noro+".o"); config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); if(co_so_deps) { @@ -89,77 +90,77 @@ namespace sitecing { for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { try { string nos = strip_suffix(noro,cc_targets[cct]); deps.push_back(root_intermediate+nos+".cc"); config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { ifstream df((root_intermediate+nos+".d").c_str(),ios::in); if(df.good()) { string str; while(!df.eof()) { df >> str; if(str.find_first_of("\\:")==string::npos) - deps.push_back(combine_path(config.root_source+nos,str)); + deps.push_back(konforka::combine_path(config.root_source+nos,str)); } } } // XXX: intermediate_deps should be broken down config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); if(co_intermediate_deps) { for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) deps.push_back(*i); } }catch(utility_no_suffix& uns) { } } }catch(utility_no_prefix& unp) { } } bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); try { string noro = strip_prefix(dp,root_intermediate); for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); }catch(utility_no_suffix& uns) { } } bool rv = file_factory::is_uptodate(dst,deps); return rv; }catch(utility_no_prefix& unp) { } // XXX: or just compare it off, instead of throwing things around. try { strip_prefix(dp,root_so); return file_factory::is_uptodate(dst,deps); }catch(utility_no_prefix& unp) { } return true; } void component_factory::build(const string& dst) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); // sources try { string noro = strip_prefix(dp,root_source); // building the sources is left up to developer return; }catch(utility_no_prefix& unp) { } // .so files try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); string o = root_intermediate+noro+".o"; cerr << "Linking " << noro << endl; if(access(o.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); - make_path(dir_name(root_so+noro),0755); + konforka::make_path(konforka::dir_name(root_so+noro),0755); file_lock lock_cc(root_intermediate+noro+".o.lock"); file_lock lock_so(root_so+noro+".so.lock"); int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdO<0) throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdE<0) { close(stdO); throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); } list<string> args; config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); @@ -186,26 +187,26 @@ namespace sitecing { }catch(utility_no_suffix& uns) { } try { string noro = strip_prefix(dp,root_intermediate); // compiler targets for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { try { string nos = strip_suffix(noro,cc_targets[cct]); string cc = root_intermediate+nos+".cc"; string o = root_intermediate+nos+".o"; cerr << "Compiling " << nos << endl; if(access(cc.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); - make_path(dir_name(cc),0755); - string pwd = dir_name(root_source+nos); + konforka::make_path(konforka::dir_name(cc),0755); + string pwd = konforka::dir_name(root_source+nos); auto_chdir dir_changer(pwd); file_lock lock_source(root_intermediate+nos+".lock"); file_lock lock_cc(root_intermediate+nos+".o.lock"); int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdO<0) throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); if(stdE<0) { close(stdO); throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); } list<string> args; @@ -226,32 +227,32 @@ namespace sitecing { throw compile_error(CODEPOINT,"failed to compile component",nos); return; }catch(utility_no_suffix& uns) { } } // preprocessor targets for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { try { string nos = strip_suffix(noro,pp_targets[ppt]); string src = root_source+nos; cerr << "Preprocessing " << nos << endl; if(access(src.c_str(),R_OK)) throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); - make_path(dir_name(root_intermediate+nos),0755); + konforka::make_path(konforka::dir_name(root_intermediate+nos),0755); file_lock lock(root_intermediate+nos+".lock"); sitecing_parser parser(*this); config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); if(co_skeleton) parser.skeleton = co_skeleton->skeleton; static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); + parser.class_name = konforka::normalize_path(nos,konforka::strip_leading_slash|konforka::strip_trailing_slash); for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { string::size_type lc = parser.class_name.find_first_of(id_chars,illc); int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; parser.class_name.replace(illc,n,n,'_'); } parser.class_name = "_SCC_"+parser.class_name; parser.output_basename = root_intermediate+nos; parser.component_basename = nos; try { parser.preprocess(src); string sf = root_intermediate+nos+".pp_stamp"; ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp @@ -259,25 +260,25 @@ namespace sitecing { pe.component_name = nos; pe.see(CODEPOINT); throw; } return; }catch(utility_no_suffix& uns) { } } }catch(utility_no_prefix& unp) { } cerr << "ignoring build request for " << dp << endl; } void component_factory::make(const string& dst) { - string dp = normalize_path(dst,strip_trailing_slash); + string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); try { string noso = strip_suffix(dp,".so"); string noro = strip_prefix(noso,root_so); file_list_t a; get_ancestors(noro,a); for(file_list_t::const_iterator i=a.begin();i!=a.end();++i) { make(root_so+*i+".so"); } }catch(utility_no_affix& una) { } file_factory::make(dst); } @@ -308,35 +309,35 @@ namespace sitecing { execvp(cmd.c_str(),(char**)&argv.front()); _exit(-1); } // parent close(stdo); close(stde); int rv; if(waitpid(pid,&rv,0)<0) throw konforka::exception(CODEPOINT,"failed to waitpid()"); return rv; } string component_factory::get_classname(const string& component) { - string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".classname"; + string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".classname"; make(cn); ifstream ifs(cn.c_str()); if(!ifs.good()) throw konforka::exception(CODEPOINT,"failed to access component .classname"); ifs >> cn; return cn; } void component_factory::get_ancestors(const string& component,file_list_t& rv) { - string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".ancestors"; + string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".ancestors"; make(cn); ifstream ifs(cn.c_str()); if(!ifs.good()) throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors"); rv.clear(); while(!ifs.eof()) { string a; ifs >> a; if(!a.empty()) rv.push_back(a); } } diff --git a/lib/configuration.cc b/lib/configuration.cc index 4ee1526..6b21690 100644 --- a/lib/configuration.cc +++ b/lib/configuration.cc @@ -1,20 +1,21 @@ #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) { @@ -295,25 +296,25 @@ namespace sitecing { } 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) ) { @@ -328,25 +329,25 @@ namespace sitecing { 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); @@ -360,25 +361,25 @@ namespace sitecing { 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; @@ -405,25 +406,25 @@ namespace sitecing { 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()) diff --git a/lib/sitecing_parser.ll b/lib/sitecing_parser.ll index 4fd6709..8dd8d5f 100644 --- a/lib/sitecing_parser.ll +++ b/lib/sitecing_parser.ll @@ -1,21 +1,22 @@ %{ /* * XXX: I have a strong feeling that this parser should be completely rewritten. */ #include <iostream> #include <fstream> #include <cassert> #include <stdexcept> using namespace std; +#include <konforka/util.h> #include "sitecing/sitecing_util.h" #include "sitecing/sitecing_exception.h" using namespace sitecing; #define sitecing_parser_flexlexer_once #include "sitecing/sitecing_parser.h" #include "sitecing/sitecing_enflesher.h" #undef yyFlexLexer #define yyFlexLexer sitecing_parserFlexLexer %} %x SLASHSTAR_COMMENT SLASHSLASH_COMMENT STRING %x CODELINE CLASSLINE DECLLINE IMPLLINE DECLBLOCK IMPLBLOCK VARLINE VARINIT %x IMPORTLINE IMPORTCOMPONENT @@ -288,26 +289,26 @@ NOIDCHAR [^A-Za-z0-9_] \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true)); + string c = konforka::combine_path(component_basename,m.output); + member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true)); modi.pop_front(); BEGIN(INITIAL); } } <IMPORTTYPELINE>{ {WHITESPACE}+ { } {ID} { modus_operandi& m = M(); if(!m._name.empty()) throw preprocessor_error(CODEPOINT,"syntax error",lineno()); m._name = yytext; @@ -322,26 +323,26 @@ NOIDCHAR [^A-Za-z0-9_] \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true,true)); + string c = konforka::combine_path(component_basename,m.output); + member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true,true)); modi.pop_front(); BEGIN(INITIAL); } } <DERIVELINE>{ {WHITESPACE}+ { } {ID} { modus_operandi& m = M(); if(!m._name.empty()) throw preprocessor_error(CODEPOINT,"syntax_error",lineno()); m._name = yytext; @@ -356,26 +357,26 @@ NOIDCHAR [^A-Za-z0-9_] \n { modus_operandi& m = M(); string::size_type t = m.output.find_first_not_of(" \t"); if(t!=string::npos) m.output.erase(0,t); t = m.output.find_last_not_of(" \t;"); if(t!=string::npos) m.output.erase(t+1); if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { m.output.erase(0,1); m.output.erase(m.output.length()-1); } - string c = combine_path(component_basename,m.output); - ancestor_classes.push_back(ancestor_class(m._name,normalize_path(c,strip_leading_slash))); + string c = konforka::combine_path(component_basename,m.output); + ancestor_classes.push_back(ancestor_class(m._name,konforka::normalize_path(c,konforka::strip_leading_slash))); modi.pop_front(); BEGIN(INITIAL); } } <VARLINE>{ {WHITESPACE}+ { modus_operandi& m = M(); if(!m.output.empty()) { if(!m._lastid.empty()) { if(!m._type.empty()) m._type += ' '; m._type += m._lastid; diff --git a/lib/sitecing_util.cc b/lib/sitecing_util.cc index f892a60..f1432df 100644 --- a/lib/sitecing_util.cc +++ b/lib/sitecing_util.cc @@ -11,98 +11,36 @@ #include <iostream> #include <fstream> #include <cassert> #include "sitecing/sitecing_util.h" #endif namespace sitecing { /* * XXX: all of these utilities could be sheerly optimized. */ - string normalize_path(const string& path,int opts) { - const char *s = path.c_str(); - string rv; - string::size_type notslash = 0; - if( (*s)=='.' && s[1]=='/' ) - s+=2; - if(opts&strip_leading_slash) - for(;(*s) && (*s)=='/';s++); - for(;*s;s++) { - if( (*s)=='/' ) { - if(s[1]=='/') - continue; - if(s[1]=='.' && s[2]=='/') { - s+=2; - continue; - } - } - if(opts&restrict_dotdot) { - if( - ( rv.empty() && s[0]=='.' && s[1]=='.' && s[2]=='/' ) // "^../" - || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)" - ) - throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered"); - } - rv += *s; - if( (*s) != '/' ) - notslash=rv.length(); - } - if(!(opts&strip_trailing_slash)) - notslash++; - if(notslash<rv.length()) - rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash - return rv; - } - string strip_prefix(const string& str,const string& prefix) { if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) throw utility_no_prefix(CODEPOINT,"no such prefix"); return str.substr(prefix.length()); } string strip_suffix(const string& str,const string& suffix) { if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) throw utility_no_suffix(CODEPOINT,"no such suffix"); return str.substr(0,str.length()-suffix.length()); } - string dir_name(const string& filename) { - string::size_type sl = filename.find_last_of('/'); - if(sl==string::npos) - return ""; // no slashes -- no dir. - string::size_type nosl = filename.find_last_not_of('/',sl); - if(nosl==string::npos) - return ""; // only slashes -- no dir. XXX: only slashes after the last slash... does it mean no dir? - return filename.substr(0,nosl+1); - } - - void make_path(const string& path,mode_t mode) { - struct stat st; - for(string::size_type sl=0;sl!=string::npos;sl=path.find('/',sl+1)) { - if(!sl) - continue; - string p = path.substr(0,sl); - if(stat(p.c_str(),&st) || !S_ISDIR(st.st_mode)) { - if(mkdir(p.c_str(),mode)) - throw konforka::exception(CODEPOINT,"failed to mkdir()"); - } - } - if(stat(path.c_str(),&st) || !S_ISDIR(st.st_mode)) { - if(mkdir(path.c_str(),mode)) - throw konforka::exception(CODEPOINT,"failed to mkdir()"); - } - } - void file_lock::lock(const string& f) { unlock(); fd = open(f.c_str(),O_CREAT|O_RDWR,S_IRUSR|S_IWUSR); if(fd<0) throw konforka::exception(CODEPOINT,"failed to open/create lockfile"); try { lock(); }catch(konforka::exception& ke) { ke.see(CODEPOINT); close(fd); fd=-1; throw; }catch(...) { @@ -195,79 +133,24 @@ namespace sitecing { sem->on(); locked = true; } void semaphore_lock::unlock() { if(!sem) return; if(!locked) return; sem->off(); locked=false; } - string combine_path(const string& origin,const string& relative,int opts) { - string r = normalize_path(relative,0); - string rv; - // XXX: what to do if relative is empty is a question, really. - if(r.empty()) { - return normalize_path( (opts&origin_is_file)?dir_name(origin):origin ,strip_leading_slash|restrict_dotdot|strip_trailing_slash); - }else{ - if(r[0]=='/') { - r.erase(0,1); - }else{ - rv = normalize_path((opts&origin_is_file)?dir_name(origin):origin,restrict_dotdot|strip_trailing_slash); - } - } - string::size_type lsl = rv.rfind('/'); - for(string::size_type sl=r.find('/');sl!=string::npos;sl=r.find('/')) { - assert(sl!=0); - if(sl==1 && r[0]=='.') { - // it's a "./" - r.erase(0,2); - }else if(sl==2 && r[0]=='.' && r[1]=='.') { - // we have a "../" - if(lsl==string::npos) { - if(rv.empty() && (opts&fail_beyond_root)) - throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); - rv.clear(); - }else{ - rv.erase(lsl); - lsl = rv.rfind('/'); - } - r.erase(0,3); - }else{ - // we have a "something/" - lsl = rv.length(); - rv += '/'; - rv += r.substr(0,sl); - r.erase(0,sl+1); - } - } - if(r.empty()) - return rv+'/'; - if(r.length()==2 && r[0]=='.' && r[0]=='.') { - if(lsl==string::npos) { - if(rv.empty() & (opts&fail_beyond_root)) - throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); - return "/"; - }else{ - rv.erase(lsl+1); - return rv; - } - } - rv += '/'; - rv += r; - return rv; - } - void auto_chdir::pushdir(const string& td,bool ap) { /* TODO: make use of fchdir(2) instead */ char *tmp = getcwd(0,0); assert(tmp); saved_pwd = tmp; free(tmp); autopop=ap; if(chdir(td.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir()"); } void auto_chdir::popdir() { autopop=false; diff --git a/lib/sitespace.cc b/lib/sitespace.cc index 0406d11..d5592bf 100644 --- a/lib/sitespace.cc +++ b/lib/sitespace.cc @@ -1,35 +1,36 @@ #ifdef USE_PCH #include "pch.h" #else #include <cassert> + #include <konforka/util.h> #include "sitecing/sitespace.h" #include "sitecing/sitecing_util.h" #endif namespace sitecing { sitespace::sitespace(configuration& c) : config(c), factory(c) { } sitespace::~sitespace() { for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { assert((*i)->chickens_used.empty()); delete *i; } } so_component sitespace::fetch(const string& c,sitecing_interface* scif) { execute_sentenced(); - string sobase = normalize_path(c); + string sobase = konforka::normalize_path(c); string sopath = factory.root_so+sobase+".so"; config_options *co_build = config.lookup_config(sobase,config_options::flag_build); if( (!co_build) || co_build->build ) factory.make(sopath); components_t::iterator i = components.find(sopath); if(i!=components.end()) { if(i->second->is_uptodate()) return so_component(i->second,scif); if(i->second->chickens_used.empty()) { delete i->second; }else{ sentenced.push_back(i->second); diff --git a/src/sitecing-build.cc b/src/sitecing-build.cc index 4cad0a3..887ef83 100644 --- a/src/sitecing-build.cc +++ b/src/sitecing-build.cc @@ -1,21 +1,22 @@ #include <sys/types.h> #include <dirent.h> #include <getopt.h> #include <iostream> #include <memory> #include <fstream> #include <cassert> #include <set> using namespace std; +#include <konforka/util.h> #include "sitecing/sitecing_util.h" #include "sitecing/util.h" #include "sitecing/sitespace.h" #include "sitecing/sitecing_interface_cgi.h" #include "sitecing/cgi_component.h" #include "sitecing/configuration.h" #include "sitecing/magic.h" #include "sitecing/sitecing_exception.h" #include "sitecing/exception.h" using namespace sitecing; #include "config.h" @@ -69,25 +70,25 @@ void build_imports(const string& component) { while(!ifs.eof()) { ifs >> import; if(!import.empty()) build_with_imports(import); } } } void build_http_status_handlers(const string& target) { assert(site_space); set<string> stop_list; 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 = site_space->config.lookup_loaded_options(t); if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { for(config_options::http_status_handlers_t::const_iterator i=lo->http_status_handlers.begin();i!=lo->http_status_handlers.end();++i) { if(stop_list.find(i->first)==stop_list.end()) { build_with_imports(i->second); stop_list.insert(i->first); } } } } @@ -138,25 +139,25 @@ void build(const string& target) { if(S_ISREG(st.st_mode)) { build_target(target); }else if(S_ISDIR(st.st_mode)) { build_http_status_handlers(target); DIR *d=opendir(target_source.c_str()); if(!d) throw konforka::exception(CODEPOINT,"failed to opendir()"); for(struct dirent *de=readdir(d);de;de=readdir(d)) { if(!strcmp(de->d_name,".")) continue; if(!strcmp(de->d_name,"..")) continue; - string subtarget = normalize_path(target+"/"+de->d_name); + string subtarget = konforka::normalize_path(target+"/"+de->d_name); struct stat sts; if(stat((site_space->config.root_source+subtarget).c_str(),&sts)) throw konforka::exception(CODEPOINT,"failed to stat() subtarget"); if(S_ISDIR(sts.st_mode)) { build(subtarget); }else{ if(site_space->config.match_autobuild_files(target,de->d_name)){ build_target(subtarget); } } } closedir(d); diff --git a/src/sitecing-fastcgi.cc b/src/sitecing-fastcgi.cc index 756dcee..03587aa 100644 --- a/src/sitecing-fastcgi.cc +++ b/src/sitecing-fastcgi.cc @@ -156,44 +156,44 @@ void sitecing_fastcgi_pm::process(int slot) { sslot->state = scoreboard_slot::state_idle; sl.sem = &sem; sl.lock(); } sslot->state = scoreboard_slot::state_accept; fcgi_interface fi(fs); sslot->state = scoreboard_slot::state_processing; if(multi) sl.unlock(); cgi_gateway gw(fi); scif.prepare(&gw); try { - component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); + component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash); string full_component_path; string sitecing_path_info; while(true) { full_component_path = config.root_source+'/'+component_path; if(!access(full_component_path.c_str(),F_OK)) break; string::size_type sl = component_path.rfind('/'); if(sl==string::npos) throw konforka::exception(CODEPOINT,"can't find the target component"); sitecing_path_info.insert(0,component_path,sl,string::npos); component_path.erase(sl); } fi.metavars["SITECING_PATH_INFO"]=sitecing_path_info; action = component_path; action_handler = config.lookup_action_handler(component_path); if(action_handler) { action = action_handler->action; } - string pwd = dir_name(full_component_path); + string pwd = konforka::dir_name(full_component_path); if(chdir(pwd.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); so_component soc = ss.fetch(action,&scif); if(action_handler) { soc.ac->run(__magic_action, config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), &(action_handler->args) ); }else{ soc.ac->main(0,NULL); } }catch(http_status& hs) { diff --git a/src/sitecing-plaincgi.cc b/src/sitecing-plaincgi.cc index 3bd291a..2f93cc5 100644 --- a/src/sitecing-plaincgi.cc +++ b/src/sitecing-plaincgi.cc @@ -41,44 +41,44 @@ class adummyClass : public cgi_component { void process_request(configuration& config) { try { sitespace ss(config); sitecing_interface_cgi scif(&ss); string component_path; string action; config_options::action_handler_t *action_handler; plaincgi_interface ci; cgi_gateway gw(ci); scif.prepare(&gw); try { - component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); + component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash); string full_component_path; string sitecing_path_info; while(true) { full_component_path = config.root_source+'/'+component_path; if(!access(full_component_path.c_str(),F_OK)) break; string::size_type sl = component_path.rfind('/'); if(sl==string::npos) throw konforka::exception(CODEPOINT,"can't find the target component"); sitecing_path_info.insert(0,component_path,sl,string::npos); component_path.erase(sl); } ci.metavars["SITECING_PATH_INFO"]=sitecing_path_info; action = component_path; action_handler = config.lookup_action_handler(component_path); if(action_handler) { action = action_handler->action; } - string pwd = dir_name(full_component_path); + string pwd = konforka::dir_name(full_component_path); if(chdir(pwd.c_str())) throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); so_component soc = ss.fetch(action,&scif); if(action_handler) { soc.ac->run(__magic_action, config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), &(action_handler->args) ); }else{ soc.ac->main(0,NULL); } }catch(http_status& hs) { |