summaryrefslogtreecommitdiffabout
path: root/lib
authorMichael Krelin <hacker@klever.net>2009-09-01 19:59:38 (UTC)
committer Michael Krelin <hacker@klever.net>2009-09-01 19:59:38 (UTC)
commitda3fe98e5c75940135fcd9bb45b36eed62d8b4dc (patch) (side-by-side diff)
treeeda546a705a667dd1b62f7eee481b3087fbfdf27 /lib
parent34d57b6b55b51e4b489a4cafce8874dec558b600 (diff)
downloadlibopkele-da3fe98e5c75940135fcd9bb45b36eed62d8b4dc.zip
libopkele-da3fe98e5c75940135fcd9bb45b36eed62d8b4dc.tar.gz
libopkele-da3fe98e5c75940135fcd9bb45b36eed62d8b4dc.tar.bz2
fixed normalization for the single-character trailing component
Thanks Hiroyuki ARAKI for spotting the bug and providing the fix Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/util.cc2
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/util.cc b/lib/util.cc
index 249eeed..4028697 100644
--- a/lib/util.cc
+++ b/lib/util.cc
@@ -279,193 +279,193 @@ namespace opkele {
* that is - [:alpha:][:digit:]._~-
* - remove dot segments
* - remove empty and default ports
* - if there's no path component, add '/'
*/
string rfc_3986_normalize_uri(const string& uri) {
string rv;
string::size_type ns = uri.find_first_not_of(data::_whitespace_chars);
if(ns==string::npos)
throw bad_input(OPKELE_CP_ "Can't normalize empty URI");
string::size_type colon = uri.find(':',ns);
if(colon==string::npos)
throw bad_input(OPKELE_CP_ "No scheme specified in URI");
transform(
uri.begin()+ns, uri.begin()+colon+1,
back_inserter(rv), ::tolower );
bool s;
string::size_type ul = uri.find_last_not_of(data::_whitespace_chars)+1;
if(ul <= (colon+3))
throw bad_input(OPKELE_CP_ "Unexpected end of URI being normalized encountered");
if(uri[colon+1]!='/' || uri[colon+2]!='/')
throw bad_input(OPKELE_CP_ "Unexpected input in URI being normalized after scheme component");
if(rv=="http:")
s = false;
else if(rv=="https:")
s = true;
else{
/* TODO: support more schemes. e.g. xri. How do we normalize
* xri?
*/
rv.append(uri,colon+1,ul-colon-1);
return rv;
}
rv += "//";
string::size_type interesting = uri.find_first_of(":/#?",colon+3);
if(interesting==string::npos) {
transform(
uri.begin()+colon+3,uri.begin()+ul,
back_inserter(rv), ::tolower );
rv += '/'; return rv;
}
transform(
uri.begin()+colon+3,uri.begin()+interesting,
back_inserter(rv), ::tolower );
bool qf = false;
char ic = uri[interesting];
if(ic==':') {
string::size_type ni = uri.find_first_of("/#?%",interesting+1);
const char *nptr = uri.data()+interesting+1;
char *eptr = 0;
long port = strtol(nptr,&eptr,10);
if( (port>0) && (port<65535) && port!=(s?443:80) ) {
char tmp[8];
snprintf(tmp,sizeof(tmp),":%ld",port);
rv += tmp;
}
if(ni==string::npos) {
rv += '/'; return rv;
}
interesting = ni;
}else if(ic!='/') {
rv += '/'; rv += ic;
qf = true;
++interesting;
}
string::size_type n = interesting;
char tmp[3] = { 0,0,0 };
stack<string::size_type> psegs; psegs.push(rv.length());
string pseg;
for(;n<ul;) {
string::size_type unsafe = uri.find_first_of(qf?"%":"%/?#",n);
if(unsafe==string::npos) {
pseg.append(uri,n,ul-n-1); n = ul-1;
}else{
pseg.append(uri,n,unsafe-n);
n = unsafe;
}
char c = uri[n++];
if(c=='%') {
if((n+1)>=ul)
throw bad_input(OPKELE_CP_ "Unexpected end of URI encountered while parsing percent-encoded character");
tmp[0] = uri[n++];
tmp[1] = uri[n++];
if(!( isxdigit(tmp[0]) && isxdigit(tmp[1]) ))
throw bad_input(OPKELE_CP_ "Invalid percent-encoded character in URI being normalized");
int cc = strtol(tmp,0,16);
if( isalpha(cc) || isdigit(cc) || strchr("._~-",cc) )
pseg += (char)cc;
else{
pseg += '%';
pseg += (char)toupper(tmp[0]); pseg += (char)toupper(tmp[1]);
}
}else if(qf) {
rv += pseg; rv += c;
pseg.clear();
}else if(n>=ul || strchr("?/#",c)) {
- if(pseg.empty() || pseg==".") {
+ if( (unsafe!=string::npos && pseg.empty()) || pseg==".") {
}else if(pseg=="..") {
if(psegs.size()>1) {
rv.resize(psegs.top()); psegs.pop();
}
}else{
psegs.push(rv.length());
if(c!='/') {
pseg += c;
qf = true;
}
rv += '/'; rv += pseg;
}
if(c=='/' && (n>=ul || strchr("?#",uri[n])) ) {
rv += '/';
if(n<ul)
qf = true;
}else if(strchr("?#",c)) {
if(psegs.size()==1 && psegs.top()==rv.length())
rv += '/';
if(pseg.empty())
rv += c;
qf = true;
}
pseg.clear();
}else{
pseg += c;
}
}
if(!pseg.empty()) {
if(!qf) rv += '/';
rv += pseg;
}
return rv;
}
string& strip_uri_fragment_part(string& u) {
string::size_type q = u.find('?'), f = u.find('#');
if(q==string::npos) {
if(f!=string::npos)
u.erase(f);
}else{
if(f!=string::npos) {
if(f<q)
u.erase(f,q-f);
else
u.erase(f);
}
}
return u;
}
bool uri_matches_realm(const string& uri,const string& realm) {
string nrealm = opkele::util::rfc_3986_normalize_uri(realm);
string nu = opkele::util::rfc_3986_normalize_uri(uri);
string::size_type pr = nrealm.find("://");
string::size_type pu = nu.find("://");
assert(!(pr==string::npos || pu==string::npos));
pr += sizeof("://")-1;
pu += sizeof("://")-1;
if(!strncmp(nrealm.c_str()+pr,"*.",2)) {
pr = nrealm.find('.',pr);
pu = nu.find('.',pu);
assert(pr!=string::npos);
if(pu==string::npos)
return false;
// TODO: check for overgeneralized realm
}
string::size_type lr = nrealm.length();
string::size_type lu = nu.length();
if( (lu-pu) < (lr-pr) )
return false;
pair<const char*,const char*> mp = mismatch(
nrealm.c_str()+pr,nrealm.c_str()+lr,
nu.c_str()+pu);
if( (*(mp.first-1))!='/'
&& !strchr("/?#",*mp.second) )
return false;
return true;
}
string abi_demangle(const char *mn) {
#ifndef HAVE_DEMANGLE
return mn;
#else /* !HAVE_DEMANGLE */
int dstat;
char *demangled = abi::__cxa_demangle(mn,0,0,&dstat);
if(dstat)
return mn;
string rv = demangled;
free(demangled);
return rv;
#endif /* !HAVE_DEMANGLE */
}
string base64_signature(const assoc_t& assoc,const basic_openid_message& om) {
const string& slist = om.get_field("signed");