From 469bbcf0701e1eb8a6670c23145b0da87357e178 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 25 Mar 2012 20:00:08 +0000 Subject: Code is all reorganized. We're about ready to release. I should write up a little explenation of the arrangement. --- src/unstable/url.cpp | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 src/unstable/url.cpp (limited to 'src/unstable/url.cpp') diff --git a/src/unstable/url.cpp b/src/unstable/url.cpp new file mode 100644 index 0000000..7b4a48e --- /dev/null +++ b/src/unstable/url.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/url.h" +#ifndef WIN32 +# include +# include +#endif +#include + +char Bu::Url::hexcode[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +Bu::Url::Url() +{ +} + +Bu::Url::Url( const Bu::String &sUrl ) +{ + parseUrl( sUrl ); +} + +Bu::Url::~Url() +{ +} + +void Bu::Url::parseUrl( const Bu::String &sUrl ) +{ + clear(); + + Bu::String::const_iterator i = sUrl.begin(); + parseProtocol( i ); + parseUserPass( i ); + parseHost( i ); + parsePath( i ); +} + +Bu::String Bu::Url::decode( const Bu::String &sStr ) +{ + Bu::String sRet; + char buf[3] = {0, 0, 0}; + for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) + { + if( *i == '+' ) + { + sRet += ' '; + } + else if( *i == '%' ) + { + i++; + buf[0] = *i; + i++; + buf[1] = *i; + sRet += (char)((unsigned char)strtol( buf, NULL, 16 )); + } + else + { + sRet += *i; + } + } + return sRet; +} + +Bu::String Bu::Url::encode( const Bu::String &sStr ) +{ + Bu::String sRet; + for( Bu::String::const_iterator i = sStr.begin(); i; i++ ) + { + if( *i == ' ' ) + { + sRet += '+'; + } + else if( + (*i >= 'A' && *i <= 'Z') || + (*i >= 'a' && *i <= 'z') || + (*i >= '0' && *i <= '9') || + (*i == '-' || *i == '_' || *i == '.' || *i == '~') + ) + { + sRet += *i; + } + else + { + unsigned char b = *i; + sRet += '%'; + sRet += hexcode[(b>>4)&0xF]; + sRet += hexcode[b&0xF]; + } + } + return sRet; +} + +void Bu::Url::parseProtocol( Bu::String::const_iterator &i ) +{ + Bu::String::const_iterator s = i.find("://", 3); + if( !s ) + throw Bu::ExceptionBase("No :// in url"); + Bu::String sTmp( i, s ); + setProtocol( sTmp ); + i = s + 3; +} + +void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort ) +{ + sProtocol = sNewProto; +#ifndef WIN32 + if( bAutoSetPort ) + { + struct servent *se = getservbyname( sProtocol.getStr(), "tcp" ); + if( se ) + { + iPort = ntohs( se->s_port ); + } + } +#endif +} + +void Bu::Url::parseUserPass( Bu::String::const_iterator &i ) +{ + Bu::String::const_iterator s = i.find('@'); + if( !s ) + return; + + Bu::String::const_iterator p = i.find(':'); + if( p ) + { + sUser.set( i, p ); + sPass.set( p+1, s ); + } + else + { + sUser.set( i, s ); + } + + i = s + 1; +} + +void Bu::Url::parseHost( Bu::String::const_iterator &i ) +{ + Bu::String::const_iterator s = i; + for( ; s && *s != '/'; s++ ) + { + if( *s == ':' ) + { + sHost.set( i, s ); + i = s + 1; + s = i.find('/'); + Bu::String sPort( i, s ); + iPort = strtol( sPort.getStr(), NULL, 10 ); + i = s; + return; + } + } + sHost.set( i, s ); + i = s; +} + +void Bu::Url::parsePath( const Bu::String &sPath ) +{ + Bu::String::const_iterator i = sPath.begin(); + parsePath( i ); +} + +void Bu::Url::parsePath( Bu::String::const_iterator &i ) +{ + if( i ) + { + Bu::String::const_iterator s = i.find('?'); + sPath.set( i, s ); + i = s + 1; + if( s ) + { + parseParams( i ); + } + } + else + { + sPath = "/"; + } +} + +void Bu::Url::parseParams( const Bu::String &sQuery ) +{ + Bu::String::const_iterator i = sQuery.begin(); + parseParams( i ); +} + +void Bu::Url::parseParams( Bu::String::const_iterator &i ) +{ + bool bName = true; + Bu::String sName, sValue; + for( Bu::String::const_iterator s = i; s; s++ ) + { + if( bName ) + { + if( *s == '&' ) + { + sName.set( i, s ); + sValue.clear(); + i = s + 1; + addParam( decode( sName ), decode( sValue ) ); + } + else if( *s == '=' ) + { + sName.set( i, s ); + i = s + 1; + bName = false; + } + } + else + { + if( *s == '&' ) + { + sValue.set( i, s ); + i = s + 1; + bName = true; + addParam( decode( sName ), decode( sValue ) ); + } + } + } + if( i ) + { + if( bName ) + { + sName.set( i ); + sValue.clear(); + } + else + { + sValue.set( i ); + } + addParam( decode( sName ), decode( sValue ) ); + } +} + +void Bu::Url::addParam( const Bu::String &n, const Bu::String &v ) +{ + lParam.append( Param( n, v ) ); +} + +void Bu::Url::clear() +{ + sProtocol.clear(); + sUser.clear(); + sPass.clear(); + sHost.clear(); + sPath.clear(); + iPort.clear(); +} + +Bu::String Bu::Url::getFullPath() const +{ + Bu::String sBuf = sPath; + if( !lParam.isEmpty() ) + { + for( ParamList::const_iterator i = lParam.begin(); i; i++ ) + { + if( i == lParam.begin() ) + sBuf += "?"; + else + sBuf += "&"; + + sBuf += encode( (*i).sName ); + if( !(*i).sValue.isEmpty() ) + { + sBuf += "=" + encode( (*i).sValue ); + } + } + } + + return sBuf; +} + +Bu::String Bu::Url::getUrl() const +{ + Bu::String sBuf = sProtocol + "://" + sHost + getFullPath(); + return sBuf; +} + -- cgit v1.2.3