-rw-r--r-- | lib/util.cc | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/lib/util.cc b/lib/util.cc index 74039c6..069590b 100644 --- a/lib/util.cc +++ b/lib/util.cc @@ -1,98 +1,99 @@ #include <sys/types.h> #include <sys/stat.h> +#include <cassert> #include <konforka/util.h> namespace konforka { /* * XXX: this code is borrowed from sitecing as is, although it should be optimized. */ string normalize_path(const string& p,int o) { const char *s = p.c_str(); if( s[0]=='.' && s[1]=='/' ) s += 2; // skip leading './' if(o&strip_leading_slash) for(;(*s)=='/';s++); string rv; string::size_type notslash = 0; for(;*s;s++) { if(s[0]=='/') { if(s[1]=='/') continue; // skip duplicate slash if(s[1]=='.' && s[2]=='/') { // '/./' sequence encountered s += 2; continue; } } if( (o&restrict_dotdot) && ( ( rv.empty() && s[0]=='.' && s[1]=='.' && s[2]=='/' ) // '^../' || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]=='/' || s[3]==0) ) // '/../' or '/..$' ) ) throw restricted_sequence_error(CODEPOINT,"restricted updir (..) sequence encountered"); rv += *s; if( (*s) !='/' ) notslash = rv.length(); } if(!(o&strip_trailing_slash)) notslash++; if(notslash<rv.length()) rv.erase(notslash); // XXX: does this operation have enough sense to be performed? return rv; } string dir_name(const string& p) { string::size_type sl = p.find_last_of('/'); if(sl==string::npos) return ""; // no slashes -- no dir. string::size_type nosl = p.find_last_not_of('/',sl); if(nosl==string::npos) return ""; // only slashes -- no dir. return p.substr(0,nosl+1); } string combine_path(const string& orig,const string& rel,int o) { string r = normalize_path(rel,0); if(r.empty()) { // XXX: this behaviour is questionable. return normalize_path( (o&origin_is_file)?dir_name(orig):orig, strip_leading_slash|restrict_dotdot|strip_trailing_slash); } string rv; if(r[0]=='/') { r.erase(0,1); }else{ rv = normalize_path( (o&origin_is_file)?dir_name(orig):orig, restrict_dotdot|strip_trailing_slash); } string::size_type lsl = rv.rfind('/'); // iterate through slashes in relative path for(string::size_type sl=r.find('/');sl!=string::npos;sl=r.find('/')) { assert(sl!=0); // sure we don't start with '/' at this point if(sl==1 && r[0]=='.') { // './' r.erase(0,2); }else if(sl==2 && r[0]=='.' && r[1]=='.') { // '../' if(lsl==string::npos) { if(rv.empty() && (o&fail_beyond_root)) throw beyond_root_error(CODEPOINT,"went beyond root while combining path"); rv.clear(); }else{ rv.erase(lsl); lsl = rv.rfind('/'); } r.erase(0,3); }else{ // '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[1]=='.') { if(lsl==string::npos) { if(rv.empty() && (o&fail_beyond_root)) throw beyond_root_error(CODEPOINT,"went beyond root while combining path"); |