From: Christian P. <cp...@us...> - 2005-01-17 21:58:51
|
Update of /cvsroot/pclasses/pclasses2/src/IO In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23030/src/IO Modified Files: URL.cpp Log Message: Added support for URL arguments (needed for HTTP post data as well). Added support for URL anchors. Added support for URL encoding/decoding. todo: Implement URL::encode()/URL::decode() Index: URL.cpp =================================================================== RCS file: /cvsroot/pclasses/pclasses2/src/IO/URL.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- URL.cpp 26 Dec 2004 16:26:03 -0000 1.1 +++ URL.cpp 17 Jan 2005 21:58:36 -0000 1.2 @@ -32,254 +32,429 @@ namespace P { namespace IO { -using namespace std; - URL::URL() { - m_proto = "file"; - m_port = 0; - m_path = "/"; + _proto = "file"; + _port = 0; + _path = "/"; } -URL::URL(const string& url) throw(InvalidURL/*,NetDbError*/) +URL::URL(const std::string& url) throw(InvalidURL/*,NetDbError*/) { - *this = url; + *this = url; } URL::URL(const URL& url) -: m_proto(url.m_proto), m_host(url.m_host), m_user(url.m_user), - m_passwd(url.m_passwd), m_port(url.m_port), m_path(url.m_path) -{} +: _proto(url._proto), _host(url._host), _user(url._user), + _passwd(url._passwd), _port(url._port), _path(url._path), + _args(url._args), _anchor(url._anchor) +{ +} -URL::~URL() +URL::~URL() throw() { } -void URL::setProtocol(const string& proto, bool setPort) +void URL::setProtocol(const std::string& proto) { - m_proto = proto; + _proto = proto; +} - if(setPort) - { - m_port = lookupPort(proto); - } +const std::string& URL::protocol() const throw() +{ + return _proto; } -void URL::setHost(const string& host) +void URL::setHost(const std::string& host) { - m_host = host; + _host = host; } -void URL::setUser(const string& user) +const std::string& URL::host() const throw() { - m_user = user; + return _host; } -void URL::setPassword(const string& passwd) +void URL::setUser(const std::string& user) { - m_passwd = passwd; + _user = user; +} + +const std::string& URL::user() const throw() +{ + return _user; +} + +void URL::setPassword(const std::string& passwd) +{ + _passwd = passwd; +} + +const std::string& URL::password() const throw() +{ + return _passwd; } void URL::setPort(unsigned short port) { - m_port = port; + _port = port; } -void URL::setPath(const string& path) +unsigned short URL::port() const throw() { - if(path.empty()) - m_path = "/"; - else - m_path = path; + return _port; +} + +void URL::setPath(const std::string& path) +{ + if(path.empty()) + { + _path = "/"; + } + else + { + // make sure we have a leading slash in the path ... + if(path[0] != '/') + _path = "/" + path; + else + _path = path; + } +} + +const std::string& URL::path() const throw() +{ + return _path; +} + +URL::ArgumentMap URL::fromString(const std::string& args) +{ + ArgumentMap pargs; + std::istringstream is(args); + + char ch; + bool invalue = false; + std::ostringstream os_name, os_val; + + do + { + is >> ch; + + if(ch == '?' || ch == '&' || !is) + { + std::string name = os_name.str(); + std::string value = os_val.str(); + + if(!name.empty()) + pargs[decode(name)] = decode(value); + + invalue = false; + os_name.str(""); + os_val.str(""); + continue; + } + + if(ch == '=') + { + invalue = true; + continue; + } + + if(invalue) + os_val << ch; + else + os_name << ch; + + } while(is); + + return pargs; +} + +std::string URL::toString(const ArgumentMap& args) +{ + std::ostringstream os; + + // add URL arguments ... + URL::ArgumentMap::const_iterator i = args.begin(); + while(i != args.end()) + { + if(i != args.begin()) + os << '&'; + + // add urlencoded arg... + os << URL::encode(i->first) + << '=' + << URL::encode(i->second); + + ++i; + } + + return os.str(); +} + +void URL::addArg(const std::string& name, const std::string& value) +{ + _args[name] = value; +} + +const std::string& URL::arg(const std::string& name) const throw() +{ + static std::string emptyStr; + ArgumentMap::const_iterator i = _args.find(name); + if(i != _args.end()) + return i->second; + + return emptyStr; +} + +void URL::setArgs(const ArgumentMap& args) +{ + _args = args; +} + +void URL::setArgs(const std::string& args) +{ + _args = fromString(args); +} + +const URL::ArgumentMap& URL::args() const throw() +{ + return _args; +} + +std::string URL::args(std::string /*<- dummy */) const +{ + return toString(_args); +} + +void URL::clearArgs() throw() +{ + _args.clear(); +} + +void URL::setAnchor(const std::string& anch) +{ + _anchor = anch; +} + +const std::string& URL::anchor() const throw() +{ + return _anchor; } URL& URL::operator=(const URL& url) { - m_proto = url.m_proto; - m_host = url.m_host; - m_user = url.m_user; - m_passwd= url.m_passwd; - m_port = url.m_port; - m_path = url.m_path; - return *this; + _proto = url._proto; + _host = url._host; + _user = url._user; + _passwd = url._passwd; + _port = url._port; + _path = url._path; + _args = url._args; + _anchor = url._anchor; + + return *this; } -URL& URL::operator=(const string& url) throw(InvalidURL/*,NetDbError*/) +URL& URL::operator=(const std::string& url) throw(InvalidURL/*,NetDbError*/) { - string proto, host, user, passwd, path, port; - istringstream is(url); - ostringstream os; - - char ch; - bool atfound = url.find('@') != (size_t)-1 ? true : false; + std::string proto, host, user, passwd, path, port; + std::istringstream is(url); + std::ostringstream os; + + char ch; + bool atfound = url.find('@') != (size_t)-1 ? true : false; - // parse until protocol delimiter found... - while((is >> ch)) - { - if(ch == ':') - { - if((is >> ch) && ch == '/' && - (is >> ch) && ch == '/') - break; - throw InvalidURL(std::string("Invalid url: "+url).c_str(), P_SOURCEINFO); - - } - else if(!isalnum(ch) && !isalpha(ch)) - throw InvalidURL(std::string("Invalid url: "+url).c_str(), P_SOURCEINFO); - os << ch; - } + // parse until protocol delimiter found... + while((is >> ch)) + { + if(ch == ':') + { + if((is >> ch) && ch == '/' && + (is >> ch) && ch == '/') + break; - if(!is) - throw InvalidURL("Invalid url", P_SOURCEINFO); + throw InvalidURL(std::string("Invalid url: "+url).c_str(), P_SOURCEINFO); + + } + else if(!isalnum(ch) && !isalpha(ch)) + throw InvalidURL(std::string("Invalid url: "+url).c_str(), P_SOURCEINFO); - proto = os.str(); - os.str(""); + os << ch; + } - // parse hostname ... - bool atproc = false; - while((is >> ch)) - { - // username in hostname ? - if(ch == '@') - { - user = os.str(); - os.str(""); + if(!is) + throw InvalidURL("Invalid url", P_SOURCEINFO); - size_t pos = user.find(':'); - if(pos != (size_t)-1) - { - passwd = user.substr(pos+1, user.length() - (pos + 1)); - user = user.substr(0, pos); - } - - atproc = true; - continue; - } - else if(((atfound && ch == ':') && (atproc && ch == ':')) || ch == '/') - break; + proto = os.str(); + os.str(""); - os << ch; - } + // parse hostname ... + bool atproc = false; + while((is >> ch)) + { + // username in hostname ? + if(ch == '@') + { + user = os.str(); + os.str(""); - host = os.str(); - os.str(""); + size_t pos = user.find(':'); + if(pos != (size_t)-1) + { + passwd = user.substr(pos+1, user.length() - (pos + 1)); + user = user.substr(0, pos); + } - if(!is) - { - m_proto = proto; - m_host = host; - m_user = user; - m_passwd= passwd; - m_port = lookupPort(proto); - m_path = "/"; - return *this; - } + atproc = true; + continue; + } + else if(((atfound && ch == ':') && (atproc && ch == ':')) || ch == '/') + break; + + os << ch; + } + + host = os.str(); + os.str(""); + + if(!is) + { + _proto = proto; + _host = host; + _user = user; + _passwd = passwd; + _port = 0; + _path = "/"; + _args.clear(); + _anchor = ""; + + return *this; + } - // parse port ... - if(ch == ':') - { - while((is >> ch)) - { - if(ch == '/') - break; - else if(!isdigit(ch)) - throw InvalidURL("Non-digit in port not allowed", P_SOURCEINFO); + // parse port ... + if(ch == ':') + { + while((is >> ch)) + { + if(ch == '/') + break; + else if(!isdigit(ch)) + throw InvalidURL("Non-digit in port not allowed", P_SOURCEINFO); - os << ch; - } + os << ch; + } - port = os.str(); - os.str(""); - } + port = os.str(); + os.str(""); + } - if(!is) - { - m_proto = proto; - m_host = host; - m_user = user; - m_passwd= passwd; + if(!is) + { + _proto = proto; + _host = host; + _user = user; + _passwd = passwd; + _port = atoi(port.c_str()); + _path = "/"; + _args.clear(); + _anchor = ""; + return *this; + } - m_port = atoi(port.c_str()); - if(!m_port) - m_port = lookupPort(proto); - - m_path = "/"; - return *this; - } + os << '/'; - os << '/'; - - // parse path - while((is >> ch)) - os << ch; - - m_proto = proto; - m_host = host; - m_user = user; - m_passwd= passwd; + // parse path + while((is >> ch)) + os << ch; - m_port = atoi(port.c_str()); - if(!m_port) - m_port = lookupPort(proto); + //@@fixme ... parse args and anchor + + _proto = proto; + _host = host; + _user = user; + _passwd = passwd; + _port = atoi(port.c_str()); + _path = decode(os.str()); + _args.clear(); + _anchor = ""; - m_path = os.str(); - - return *this; + return *this; } -bool URL::operator==(const URL& url) const +bool URL::operator==(const URL& url) const throw() { - if(m_proto == url.m_proto && m_host == url.m_host && - m_user == url.m_user && m_passwd == url.m_passwd && - m_port == url.m_port && m_path == url.m_path) - return true; - return false; + if(_proto == url._proto && _host == url._host && + _user == url._user && _passwd == url._passwd && + _port == url._port && _path == url._path && + _args == url._args && _anchor == url._anchor) + return true; + + return false; } -string URL::str() const +std::string URL::str() const { - ostringstream os; - os << *this; - return os.str(); + std::ostringstream os; + os << *this; + return os.str(); } -ostream& operator<<(ostream& os, const URL& url) +std::ostream& operator<<(std::ostream& os, const URL& url) { - os << url.m_proto << "://"; + // add protocol... + os << url._proto << "://"; - if(!url.m_user.empty()) - { - os << url.m_user; - os << '@'; - } - - os << url.m_host; + // add username ... + if(!url._user.empty()) + { + os << url._user; + os << '@'; + } - if(url.m_port != URL::lookupPort(url.m_proto)) - os << ':' << url.m_port; + // add hostname + os << url._host; - os << url.m_path; - return os; + // add port ... + if(url._port) + os << ':' << url._port; + + // add path ... + os << URL::encode(url._path); + + // add URL arguments ... + std::string args = URL::toString(url._args); + if(!args.empty()) + os << '?' << args; + + // add anchor if set ... + if(!url._anchor.empty()) + os << "#" << URL::encode(url._anchor); + + return os; } -istream& operator>>(istream& is, URL& url) throw(InvalidURL) +std::istream& operator>>(std::istream& is, URL& url) throw(InvalidURL) { - string str; - if(is) - { - is >> str; - url = str; - } - - return is; + std::string str; + if(is) + { + is >> str; + url = str; + } + + return is; } -unsigned short URL::lookupPort(const string& service, const string& proto) +std::string URL::encode(const std::string& str) { - return 0; -// NetDb::ServiceEntry se = NetDb::serviceByName(service, proto); -// return se.port(); + return str; } -}} // P::IO +std::string URL::decode(const std::string& str) +{ + return str; +} + +} // !namespace IO +} // !namespace P |