X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Futils.cpp;h=0803c14c74edc980951e50b8c960ebcb94481622;hb=1c965907682f4714db7b952915cf5b6bf9b7f4c1;hp=d550259984f79357ca94449df00a4a53ce8dbdcc;hpb=077408f98f08fac1a098a501fffdb22728a57a46;p=libs%2Fnet.git diff --git a/source/utils.cpp b/source/utils.cpp index d550259..0803c14 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -1,22 +1,23 @@ -/* $Id$ - -This file is part of libmsphttp -Copyright © 2009 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include #include +#include +#include #include "utils.h" using namespace std; namespace { -const char reserved[]=" :/?#[]@!$&'()*+,;=%"; +const char *reserved[]= +{ + " #%&+=?", + " #%&*+:;=?@[]", + " !#$%&'()*+,/:;=?@[]", +}; -bool is_reserved(char c) +bool is_reserved(char c, unsigned level) { - for(const char *r=reserved; *r; ++r) + for(const char *r=reserved[level]; *r; ++r) if(c==*r) return true; return false; @@ -27,15 +28,30 @@ bool is_reserved(char c) namespace Msp { namespace Http { -string urlencode(const string &str) +string urlencode(const string &str, EncodeLevel level) { string result; for(string::const_iterator i=str.begin(); i!=str.end(); ++i) { - if(is_reserved(*i)) - result+=format("%%%02X", *i); + if(is_reserved(*i, level)) + result += format("%%%02X", *i); else - result+=*i; + result += *i; + } + return result; +} + +string urlencode_plus(const string &str, EncodeLevel level) +{ + string result; + for(string::const_iterator i=str.begin(); i!=str.end(); ++i) + { + if(*i==' ') + result += '+'; + else if(is_reserved(*i, level)) + result += format("%%%02X", *i); + else + result += *i; } return result; } @@ -45,21 +61,88 @@ string urldecode(const string &str) string result; for(unsigned i=0; istr.size()) throw InvalidParameterValue("Malformed data"); - result+=lexical_cast(str.substr(i+1, 2), "x"); - i+=2; + result += lexical_cast(str.substr(i+1, 2), "x"); + i += 2; } else if(c=='+') - result+=' '; + result += ' '; else - result+=c; + result += c; } return result; } +Url parse_url(const string &str) +{ + static Regex r_url("(([a-z]+)://)?([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*(:[0-9])?)?(/[^?#]*)?(\\?([^#]+))?(#(.*))?"); + if(RegMatch m = r_url.match(str)) + { + Url url; + url.scheme = m[2].str; + url.host = m[3].str; + url.path = urldecode(m[6].str); + url.query = m[8].str; + url.fragment = m[10].str; + return url; + } + else + throw InvalidParameterValue("Invalid URL"); +} + +string build_url(const Url &url) +{ + if(!url.path.empty() && url.path[0]!='/') + throw InvalidParameterValue("Only absolute paths are supported"); + string str; + if(!url.scheme.empty()) + str += url.scheme+"://"; + str += url.host; + str += urlencode(url.path); + if(!url.query.empty()) + { + str += '?'; + str += url.query; + } + if(!url.fragment.empty()) + { + str += '#'; + str += url.fragment; + } + return str; +} + +Query parse_query(const std::string &str) +{ + vector parts = split(str, '&'); + Query query; + for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) + { + unsigned equals = i->find('='); + string &value = query[urldecode(i->substr(0, equals))]; + if(equals!=string::npos) + value = urldecode(i->substr(equals+1)); + } + return query; +} + +string build_query(const Query &query) +{ + string str; + for(Query::const_iterator i=query.begin(); i!=query.end(); ++i) + { + if(i!=query.begin()) + str += '&'; + str += urlencode_plus(i->first); + str += '='; + str += urlencode_plus(i->second); + } + return str; +} + } // namespace Http } // namespace Msp