X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b60b2ec8ac57d569c4831eb98113f7cb713a117a..628e155d8c70da0f962289cf1e1dea3699255707:/src/common/uri.cpp diff --git a/src/common/uri.cpp b/src/common/uri.cpp index 0c9a16f65b..bcdd7eae66 100644 --- a/src/common/uri.cpp +++ b/src/common/uri.cpp @@ -8,11 +8,6 @@ // Licence: wxWindows ///////////////////////////////////////////////////////////////////////////// -// -//TODO: RN: I had some massive doxygen docs, I need to move these -//in a presentable form in these sources -// - // =========================================================================== // declarations // =========================================================================== @@ -21,10 +16,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "uri.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -32,13 +23,17 @@ #pragma hdrstop #endif +#ifndef WX_PRECOMP + #include "wx/crt.h" +#endif + #include "wx/uri.h" // --------------------------------------------------------------------------- // definitions // --------------------------------------------------------------------------- -IMPLEMENT_CLASS(wxURI, wxObject); +IMPLEMENT_CLASS(wxURI, wxObject) // =========================================================================== // implementation @@ -61,13 +56,13 @@ IMPLEMENT_CLASS(wxURI, wxObject); wxURI::wxURI() : m_hostType(wxURI_REGNAME), m_fields(0) { } - + wxURI::wxURI(const wxString& uri) : m_hostType(wxURI_REGNAME), m_fields(0) { Create(uri); } -wxURI::wxURI(const wxURI& uri) : m_hostType(wxURI_REGNAME), m_fields(0) +wxURI::wxURI(const wxURI& uri) : wxObject(), m_hostType(wxURI_REGNAME), m_fields(0) { Assign(uri); } @@ -83,8 +78,8 @@ wxURI::~wxURI() void wxURI::Clear() { - m_scheme = m_user = m_server = m_port = m_path = - m_query = m_fragment = wxT(""); + m_scheme = m_userinfo = m_server = m_port = m_path = + m_query = m_fragment = wxEmptyString; m_hostType = wxURI_REGNAME; @@ -94,61 +89,116 @@ void wxURI::Clear() // --------------------------------------------------------------------------- // Create // -// This creates the URI - all we do here is call the main parsing method +// This creates the URI - all we do here is call the main parsing method // --------------------------------------------------------------------------- -void wxURI::Create(const wxString& uri) -{ +const wxChar* wxURI::Create(const wxString& uri) +{ if (m_fields) Clear(); - Parse(uri); -} + // FIXME-UTF8: rewrite ParseXXX() methods using iterators + // NB: using wxWxCharBuffer instead of just c_str() avoids keeping + // converted string in memory for longer than needed + return Parse(wxWxCharBuffer(uri.c_str())); +} // --------------------------------------------------------------------------- -// Escape/Unescape/IsEscape +// Escape Methods +// +// TranslateEscape unencodes a 3 character URL escape sequence // -// Unescape unencodes a 3 character URL escape sequence // Escape encodes an invalid URI character into a 3 character sequence +// // IsEscape determines if the input string contains an escape sequence, // if it does, then it moves the input string past the escape sequence +// +// Unescape unencodes all 3 character URL escape sequences in a wxString // --------------------------------------------------------------------------- -wxChar wxURI::Unescape(const wxChar* s) +wxUniChar wxURI::TranslateEscape(const wxString::const_iterator& s) +{ + wxChar c1(*s); + wxChar c2(*(s + 1)); + + wxASSERT_MSG( IsHex(c1) && IsHex(c2), wxT("Invalid escape sequence!")); + + return wx_truncate_cast(wxChar, (CharToHex(c1) << 4 ) | CharToHex(c2)); +} + +wxString wxURI::Unescape(const wxString& uri) { - wxASSERT_MSG(IsHex(*s) && IsHex(*(s+1)), wxT("Invalid escape!")); + wxString new_uri; + + for (wxString::const_iterator i = uri.begin(); i != uri.end(); ++i) + { + if ( *i == wxT('%') ) + { + new_uri += wxURI::TranslateEscape(i + 1); + i += 2; + } + else + new_uri += *i; + } - return CharToHex(*s) * 0x10 + CharToHex(*++s); + return new_uri; } void wxURI::Escape(wxString& s, const wxChar& c) { const wxChar* hdig = wxT("0123456789abcdef"); - s += '%'; + s += wxT('%'); s += hdig[(c >> 4) & 15]; - s += hdig[c & 15]; + s += hdig[c & 15]; } bool wxURI::IsEscape(const wxChar*& uri) { - if(*uri == '%' && IsHex(*(uri+1)) && IsHex(*(uri+2))) - { - uri += 3; + // pct-encoded = "%" HEXDIG HEXDIG + if(*uri == wxT('%') && IsHex(*(uri+1)) && IsHex(*(uri+2))) return true; - } else return false; } // --------------------------------------------------------------------------- -// Get +// GetUser +// GetPassword // -// Get() actually builds the entire URI into a useable +// Gets the username and password via the old URL method. +// --------------------------------------------------------------------------- +wxString wxURI::GetUser() const +{ + size_t dwPasswordPos = m_userinfo.find(':'); + + if (dwPasswordPos == wxString::npos) + dwPasswordPos = 0; + + return m_userinfo(0, dwPasswordPos); +} + +wxString wxURI::GetPassword() const +{ + size_t dwPasswordPos = m_userinfo.find(':'); + + if (dwPasswordPos == wxString::npos) + return wxT(""); + else + return m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1); +} + +// --------------------------------------------------------------------------- +// BuildURI +// +// BuildURI() builds the entire URI into a useable // representation, including proper identification characters such as slashes +// +// BuildUnescapedURI() does the same thing as BuildURI(), only it unescapes +// the components that accept escape sequences // --------------------------------------------------------------------------- -wxString wxURI::Get() const -{ +wxString wxURI::BuildURI() const +{ wxString ret; if (HasScheme()) @@ -158,8 +208,8 @@ wxString wxURI::Get() const { ret += wxT("//"); - if (HasUser()) - ret = ret + m_user + wxT("@"); + if (HasUserInfo()) + ret = ret + m_userinfo + wxT("@"); ret += m_server; @@ -178,15 +228,44 @@ wxString wxURI::Get() const return ret; } -// --------------------------------------------------------------------------- -// operator = and == -// --------------------------------------------------------------------------- - -wxURI& wxURI::operator = (const wxURI& uri) +wxString wxURI::BuildUnescapedURI() const { - return Assign(uri); + wxString ret; + + if (HasScheme()) + ret = ret + m_scheme + wxT(":"); + + if (HasServer()) + { + ret += wxT("//"); + + if (HasUserInfo()) + ret = ret + wxURI::Unescape(m_userinfo) + wxT("@"); + + if (m_hostType == wxURI_REGNAME) + ret += wxURI::Unescape(m_server); + else + ret += m_server; + + if (HasPort()) + ret = ret + wxT(":") + m_port; + } + + ret += wxURI::Unescape(m_path); + + if (HasQuery()) + ret = ret + wxT("?") + wxURI::Unescape(m_query); + + if (HasFragment()) + ret = ret + wxT("#") + wxURI::Unescape(m_fragment); + + return ret; } +// --------------------------------------------------------------------------- +// Assignment +// --------------------------------------------------------------------------- + wxURI& wxURI::Assign(const wxURI& uri) { //assign fields @@ -194,7 +273,7 @@ wxURI& wxURI::Assign(const wxURI& uri) //ref over components m_scheme = uri.m_scheme; - m_user = uri.m_user; + m_userinfo = uri.m_userinfo; m_server = uri.m_server; m_hostType = uri.m_hostType; m_port = uri.m_port; @@ -205,14 +284,23 @@ wxURI& wxURI::Assign(const wxURI& uri) return *this; } +wxURI& wxURI::operator = (const wxURI& uri) +{ + return Assign(uri); +} + wxURI& wxURI::operator = (const wxString& string) -{ +{ Create(string); return *this; } +// --------------------------------------------------------------------------- +// Comparison +// --------------------------------------------------------------------------- + bool wxURI::operator == (const wxURI& uri) const -{ +{ if (HasScheme()) { if(m_scheme != uri.m_scheme) @@ -224,12 +312,12 @@ bool wxURI::operator == (const wxURI& uri) const if (HasServer()) { - if (HasUser()) + if (HasUserInfo()) { - if (m_user != uri.m_user) + if (m_userinfo != uri.m_userinfo) return false; } - else if (uri.HasUser()) + else if (uri.HasUserInfo()) return false; if (m_server != uri.m_server || @@ -290,10 +378,10 @@ bool wxURI::IsReference() const // Master URI parsing method. Just calls the individual parsing methods // // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] -// URI-reference = URI / relative-URITestCase +// URI-reference = URI / relative // --------------------------------------------------------------------------- -const wxChar* wxURI::Parse(const wxChar* uri) +const wxChar* wxURI::Parse(const wxChar *uri) { uri = ParseScheme(uri); uri = ParseAuthority(uri); @@ -308,7 +396,7 @@ const wxChar* wxURI::Parse(const wxChar* uri) // Individual parsers for each URI component // --------------------------------------------------------------------------- -const wxChar* wxURI::ParseScheme(const wxChar* uri) +const wxChar* wxURI::ParseScheme(const wxChar *uri) { wxASSERT(uri != NULL); @@ -322,29 +410,28 @@ const wxChar* wxURI::ParseScheme(const wxChar* uri) m_scheme += *uri++; //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - //RN: Scheme can not be escaped - while (IsAlpha(*uri) || IsDigit(*uri) || - *uri == '+' || - *uri == '-' || - *uri == '.') - { - m_scheme += *uri++; + while (IsAlpha(*uri) || IsDigit(*uri) || + *uri == wxT('+') || + *uri == wxT('-') || + *uri == wxT('.')) + { + m_scheme += *uri++; } //valid scheme? - if (*uri == ':') - { + if (*uri == wxT(':')) + { //mark the scheme as valid m_fields |= wxURI_SCHEME; //move reference point up to input buffer uricopy = ++uri; } - else + else //relative uri with relative path reference - m_scheme = wxT(""); + m_scheme = wxEmptyString; } -// else +// else //relative uri with _possible_ relative path reference return uricopy; @@ -353,19 +440,26 @@ const wxChar* wxURI::ParseScheme(const wxChar* uri) const wxChar* wxURI::ParseAuthority(const wxChar* uri) { // authority = [ userinfo "@" ] host [ ":" port ] - if (*uri == '/' && *(uri+1) == '/') + if (*uri == wxT('/') && *(uri+1) == wxT('/')) { + //skip past the two slashes uri += 2; - uri = ParseUser(uri); + // ############# DEVIATION FROM RFC ######################### + // Don't parse the server component for file URIs + if(m_scheme != wxT("file")) + { + //normal way + uri = ParseUserInfo(uri); uri = ParseServer(uri); return ParsePort(uri); + } } return uri; } -const wxChar* wxURI::ParseUser(const wxChar* uri) +const wxChar* wxURI::ParseUserInfo(const wxChar* uri) { wxASSERT(uri != NULL); @@ -374,24 +468,30 @@ const wxChar* wxURI::ParseUser(const wxChar* uri) const wxChar* uricopy = uri; // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) - while(*uri && *uri != '@' && *uri != '/' && *uri != '#' && *uri != '?') + while(*uri && *uri != wxT('@') && *uri != wxT('/') && *uri != wxT('#') && *uri != wxT('?')) { - if(IsUnreserved(*uri) || IsEscape(uri) || - IsSubDelim(*uri) || *uri == ':') - m_user += *uri++; + if(IsUnreserved(*uri) || + IsSubDelim(*uri) || *uri == wxT(':')) + m_userinfo += *uri++; + else if (IsEscape(uri)) + { + m_userinfo += *uri++; + m_userinfo += *uri++; + m_userinfo += *uri++; + } else - Escape(m_user, *uri++); + Escape(m_userinfo, *uri++); } - if(*uri == '@') + if(*uri == wxT('@')) { //valid userinfo - m_fields |= wxURI_USER; + m_fields |= wxURI_USERINFO; uricopy = ++uri; } else - m_user = wxT(""); + m_userinfo = wxEmptyString; return uricopy; } @@ -406,45 +506,47 @@ const wxChar* wxURI::ParseServer(const wxChar* uri) // host = IP-literal / IPv4address / reg-name // IP-literal = "[" ( IPv6address / IPvFuture ) "]" - if (*uri == '[') + if (*uri == wxT('[')) { - if (ParseIPv6address(++uri) && *uri == ']') + ++uri; //some compilers don't support *&ing a ++* + if (ParseIPv6address(uri) && *uri == wxT(']')) { ++uri; m_hostType = wxURI_IPV6ADDRESS; - + wxStringBufferLength theBuffer(m_server, uri - uricopy); - wxMemcpy(theBuffer, uricopy, uri-uricopy); + wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } else { uri = uricopy; - if (ParseIPvFuture(++uri) && *uri == ']') + ++uri; //some compilers don't support *&ing a ++* + if (ParseIPvFuture(uri) && *uri == wxT(']')) { ++uri; - m_hostType = wxURI_IPVFUTURE; - + m_hostType = wxURI_IPVFUTURE; + wxStringBufferLength theBuffer(m_server, uri - uricopy); - wxMemcpy(theBuffer, uricopy, uri-uricopy); + wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } - else + else uri = uricopy; } } - else + else { if (ParseIPv4address(uri)) { m_hostType = wxURI_IPV4ADDRESS; wxStringBufferLength theBuffer(m_server, uri - uricopy); - wxMemcpy(theBuffer, uricopy, uri-uricopy); + wxTmemcpy(theBuffer, uricopy, uri-uricopy); theBuffer.SetLength(uri-uricopy); } - else + else uri = uricopy; } @@ -452,13 +554,19 @@ const wxChar* wxURI::ParseServer(const wxChar* uri) { uri = uricopy; // reg-name = *( unreserved / pct-encoded / sub-delims ) - while(*uri && *uri != '/' && *uri != ':' && *uri != '#' && *uri != '?') + while(*uri && *uri != wxT('/') && *uri != wxT(':') && *uri != wxT('#') && *uri != wxT('?')) { - if(IsUnreserved(*uri) || IsEscape(uri) || IsSubDelim(*uri)) + if(IsUnreserved(*uri) || IsSubDelim(*uri)) + m_server += *uri++; + else if (IsEscape(uri)) + { + m_server += *uri++; + m_server += *uri++; m_server += *uri++; + } else Escape(m_server, *uri++); - } + } } //mark the server as valid @@ -467,19 +575,19 @@ const wxChar* wxURI::ParseServer(const wxChar* uri) return uri; } - + const wxChar* wxURI::ParsePort(const wxChar* uri) { wxASSERT(uri != NULL); // port = *DIGIT - if(*uri == ':') + if(*uri == wxT(':')) { ++uri; - while(IsDigit(*uri)) + while(IsDigit(*uri)) { m_port += *uri++; - } + } //mark the port as valid m_fields |= wxURI_PORT; @@ -518,22 +626,32 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali /// ; non-zero-length segment without any colon ":" /// /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - if (*uri == '/') + if (*uri == wxT('/')) { m_path += *uri++; - while(*uri && *uri != '#' && *uri != '?') - { - if( IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) || - *uri == ':' || *uri == '@' || *uri == '/') - m_path += *uri++; - else - Escape(m_path, *uri++); + while(*uri && *uri != wxT('#') && *uri != wxT('?')) + { + if( IsUnreserved(*uri) || IsSubDelim(*uri) || + *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/')) + m_path += *uri++; + else if (IsEscape(uri)) + { + m_path += *uri++; + m_path += *uri++; + m_path += *uri++; + } + else + Escape(m_path, *uri++); } if (bNormalize) { wxStringBufferLength theBuffer(m_path, m_path.length() + 1); +#if wxUSE_STL || wxUSE_UNICODE_UTF8 + // FIXME-UTF8: have some wxReadWriteStringBuffer instead? + wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1); +#endif Normalize(theBuffer, true); theBuffer.SetLength(wxStrlen(theBuffer)); } @@ -545,32 +663,48 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali if (bReference) { //no colon allowed - while(*uri && *uri != '#' && *uri != '?') + while(*uri && *uri != wxT('#') && *uri != wxT('?')) { - if(IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) || - *uri == '@' || *uri == '/') - m_path += *uri++; - else - Escape(m_path, *uri++); + if(IsUnreserved(*uri) || IsSubDelim(*uri) || + *uri == wxT('@') || *uri == wxT('/')) + m_path += *uri++; + else if (IsEscape(uri)) + { + m_path += *uri++; + m_path += *uri++; + m_path += *uri++; + } + else + Escape(m_path, *uri++); } - } + } else { - while(*uri && *uri != '#' && *uri != '?') + while(*uri && *uri != wxT('#') && *uri != wxT('?')) { - if(IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) || - *uri == ':' || *uri == '@' || *uri == '/') - m_path += *uri++; - else - Escape(m_path, *uri++); + if(IsUnreserved(*uri) || IsSubDelim(*uri) || + *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/')) + m_path += *uri++; + else if (IsEscape(uri)) + { + m_path += *uri++; + m_path += *uri++; + m_path += *uri++; + } + else + Escape(m_path, *uri++); } } if (uri != uricopy) - { + { if (bNormalize) { wxStringBufferLength theBuffer(m_path, m_path.length() + 1); +#if wxUSE_STL || wxUSE_UNICODE_UTF8 + // FIXME-UTF8: have some wxReadWriteStringBuffer instead? + wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1); +#endif Normalize(theBuffer); theBuffer.SetLength(wxStrlen(theBuffer)); } @@ -589,16 +723,22 @@ const wxChar* wxURI::ParseQuery(const wxChar* uri) wxASSERT(uri != NULL); // query = *( pchar / "/" / "?" ) - if (*uri == '?') + if (*uri == wxT('?')) { ++uri; - while(*uri && *uri != '#') + while(*uri && *uri != wxT('#')) { - if (IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) || - *uri == ':' || *uri == '@' || *uri == '/' || *uri == '?') - m_query += *uri++; + if (IsUnreserved(*uri) || IsSubDelim(*uri) || + *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/') || *uri == wxT('?')) + m_query += *uri++; + else if (IsEscape(uri)) + { + m_query += *uri++; + m_query += *uri++; + m_query += *uri++; + } else - Escape(m_query, *uri++); + Escape(m_query, *uri++); } //mark the server as valid @@ -614,16 +754,22 @@ const wxChar* wxURI::ParseFragment(const wxChar* uri) wxASSERT(uri != NULL); // fragment = *( pchar / "/" / "?" ) - if (*uri == '#') + if (*uri == wxT('#')) { ++uri; while(*uri) { - if (IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) || - *uri == ':' || *uri == '@' || *uri == '/' || *uri == '?') - m_fragment += *uri++; + if (IsUnreserved(*uri) || IsSubDelim(*uri) || + *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/') || *uri == wxT('?')) + m_fragment += *uri++; + else if (IsEscape(uri)) + { + m_fragment += *uri++; + m_fragment += *uri++; + m_fragment += *uri++; + } else - Escape(m_fragment, *uri++); + Escape(m_fragment, *uri++); } //mark the server as valid @@ -634,27 +780,29 @@ const wxChar* wxURI::ParseFragment(const wxChar* uri) } // --------------------------------------------------------------------------- -// Resolve URI +// Resolve +// +// Builds missing components of this uri from a base uri // -// Builds missing components of this uri from a base uri +// A version of the algorithm outlined in the RFC is used here +// (it is shown in comments) // -// A version of the algorithm outlined in the RFC is used here -// (it is shown in comments) +// Note that an empty URI inherits all components // --------------------------------------------------------------------------- void wxURI::Resolve(const wxURI& base, int flags) { - wxASSERT_MSG(!base.IsReference(), + wxASSERT_MSG(!base.IsReference(), wxT("wxURI to inherit from must not be a reference!")); - // If we arn't being strict, enable the older + // If we arn't being strict, enable the older (pre-RFC2396) // loophole that allows this uri to inherit other // properties from the base uri - even if the scheme // is defined if ( !(flags & wxURI_STRICT) && HasScheme() && base.HasScheme() && m_scheme == base.m_scheme ) - { + { m_fields -= wxURI_SCHEME; } @@ -670,7 +818,7 @@ void wxURI::Resolve(const wxURI& base, int flags) return; } - //No sheme - inherit + //No scheme - inherit m_scheme = base.m_scheme; m_fields |= wxURI_SCHEME; @@ -686,22 +834,22 @@ void wxURI::Resolve(const wxURI& base, int flags) } //No authority - inherit - if (base.HasUser()) + if (base.HasUserInfo()) { - m_user = base.m_user; - m_fields |= wxURI_USER; + m_userinfo = base.m_userinfo; + m_fields |= wxURI_USERINFO; } - + m_server = base.m_server; m_hostType = base.m_hostType; m_fields |= wxURI_SERVER; - + if (base.HasPort()) { m_port = base.m_port; m_fields |= wxURI_PORT; } - + // Simple path inheritance from base if (!HasPath()) @@ -709,7 +857,7 @@ void wxURI::Resolve(const wxURI& base, int flags) // T.path = Base.path; m_path = base.m_path; m_fields |= wxURI_PATH; - + // if defined(R.query) then // T.query = R.query; @@ -731,21 +879,21 @@ void wxURI::Resolve(const wxURI& base, int flags) // T.path = remove_dot_segments(T.path); // endif; // T.query = R.query; - if (m_path[(const size_t&)0] != '/') + if (m_path[0u] != wxT('/')) { - //Marge paths - const wxChar* op = m_path.c_str(); - const wxChar* bp = base.m_path.c_str() + base.m_path.Length(); + //Merge paths + wxString::const_iterator op = m_path.begin(); + wxString::const_iterator bp = base.m_path.begin() + base.m_path.length(); //not a ending directory? move up - if (base.m_path[0] && *(bp-1) != '/') - UpTree(base.m_path, bp); + if (base.m_path[0] && *(bp-1) != wxT('/')) + UpTree(base.m_path.begin(), bp); //normalize directories - while(*op == '.' && *(op+1) == '.' && - (*(op+2) == '\0' || *(op+2) == '/') ) + while(*op == wxT('.') && *(op+1) == wxT('.') && + (*(op+2) == '\0' || *(op+2) == wxT('/')) ) { - UpTree(base.m_path, bp); + UpTree(base.m_path.begin(), bp); if (*(op+2) == '\0') op += 2; @@ -753,31 +901,55 @@ void wxURI::Resolve(const wxURI& base, int flags) op += 3; } - m_path = base.m_path.substr(0, bp - base.m_path.c_str()) + - m_path.Mid((op - m_path.c_str()), m_path.Length()); + m_path = base.m_path.substr(0, bp - base.m_path.begin()) + + m_path.substr((op - m_path.begin()), m_path.length()); } } + + //T.fragment = R.fragment; } // --------------------------------------------------------------------------- -// Directory Normalization (static) +// UpTree // -// UpTree goes up a directory in a string and moves the pointer as such, -// while Normalize gets rid of duplicate/erronues directories in a URI -// according to RFC 2396 and modified quite a bit to meet the unit tests -// in it. +// Moves a URI path up a directory // --------------------------------------------------------------------------- -void wxURI::UpTree(const wxChar* uristart, const wxChar*& uri) +//static +void wxURI::UpTree(wxString::const_iterator uristart, + wxString::const_iterator& uri) +{ + if (uri != uristart && *(uri-1) == wxT('/')) + { + uri -= 2; + } + + for(;uri != uristart; --uri) + { + if (*uri == wxT('/')) + { + ++uri; + break; + } + } + + //!!!TODO:HACK!!!// + if (uri == uristart && *uri == wxT('/')) + ++uri; + //!!!// +} + +// FIXME-UTF8: fix Normalize() to use iterators instead of having this method! +/*static*/ void wxURI::UpTree(const wxChar* uristart, const wxChar*& uri) { - if (uri != uristart && *(uri-1) == '/') + if (uri != uristart && *(uri-1) == wxT('/')) { uri -= 2; } - + for(;uri != uristart; --uri) { - if (*uri == '/') + if (*uri == wxT('/')) { ++uri; break; @@ -785,23 +957,36 @@ void wxURI::UpTree(const wxChar* uristart, const wxChar*& uri) } //!!!TODO:HACK!!!// - if (uri == uristart && *uri == '/') + if (uri == uristart && *uri == wxT('/')) ++uri; //!!!// } +// end of FIXME-UTF8 + +// --------------------------------------------------------------------------- +// Normalize +// +// Normalizes directories in-place +// +// I.E. ./ and . are ignored +// +// ../ and .. are removed if a directory is before it, along +// with that directory (leading .. and ../ are kept) +// --------------------------------------------------------------------------- +//static void wxURI::Normalize(wxChar* s, bool bIgnoreLeads) { wxChar* cp = s; wxChar* bp = s; - if(s[0] == '/') + if(s[0] == wxT('/')) ++bp; while(*cp) { - if (*cp == '.' && (*(cp+1) == '/' || *(cp+1) == '\0') - && (bp == cp || *(cp-1) == '/')) + if (*cp == wxT('.') && (*(cp+1) == wxT('/') || *(cp+1) == '\0') + && (bp == cp || *(cp-1) == wxT('/'))) { //. _or_ ./ - ignore if (*(cp+1) == '\0') @@ -809,9 +994,9 @@ void wxURI::Normalize(wxChar* s, bool bIgnoreLeads) else cp += 2; } - else if (*cp == '.' && *(cp+1) == '.' && - (*(cp+2) == '/' || *(cp+2) == '\0') - && (bp == cp || *(cp-1) == '/')) + else if (*cp == wxT('.') && *(cp+1) == wxT('.') && + (*(cp+2) == wxT('/') || *(cp+2) == '\0') + && (bp == cp || *(cp-1) == wxT('/'))) { //.. _or_ ../ - go up the tree if (s != bp) @@ -842,14 +1027,39 @@ void wxURI::Normalize(wxChar* s, bool bIgnoreLeads) } } else - *s++ = *cp++; + *s++ = *cp++; } *s = '\0'; } // --------------------------------------------------------------------------- -// Misc. Parsing Methods +// ParseH16 +// +// Parses 1 to 4 hex values. Returns true if the first character of the input +// string is a valid hex character. It is the caller's responsability to move +// the input string back to its original position on failure. +// --------------------------------------------------------------------------- + +bool wxURI::ParseH16(const wxChar*& uri) +{ + // h16 = 1*4HEXDIG + if(!IsHex(*++uri)) + return false; + + if(IsHex(*++uri) && IsHex(*++uri) && IsHex(*++uri)) + ++uri; + + return true; +} + +// --------------------------------------------------------------------------- +// ParseIPXXX +// +// Parses a certain version of an IP address and moves the input string past +// it. Returns true if the input string contains the proper version of an ip +// address. It is the caller's responsability to move the input string back +// to its original position on failure. // --------------------------------------------------------------------------- bool wxURI::ParseIPv4address(const wxChar*& uri) @@ -866,14 +1076,14 @@ bool wxURI::ParseIPv4address(const wxChar*& uri) { ++iIPv4; - + //each ip part must be between 0-255 (dupe of version in for loop) if( IsDigit(*++uri) && IsDigit(*++uri) && //100 or less (note !) - !( (*(uri-2) < '2') || - //240 or less - (*(uri-2) == '2' && - (*(uri-1) < '5' || (*(uri-1) == '5' && *uri <= '5')) + !( (*(uri-2) < wxT('2')) || + //240 or less + (*(uri-2) == wxT('2') && + (*(uri-1) < wxT('5') || (*(uri-1) == wxT('5') && *uri <= wxT('5'))) ) ) ) @@ -886,16 +1096,16 @@ bool wxURI::ParseIPv4address(const wxChar*& uri) //compilers should unroll this loop for(; iIPv4 < 4; ++iIPv4) { - if (*uri != '.' || !IsDigit(*++uri)) + if (*uri != wxT('.') || !IsDigit(*++uri)) break; //each ip part must be between 0-255 if( IsDigit(*++uri) && IsDigit(*++uri) && //100 or less (note !) - !( (*(uri-2) < '2') || - //240 or less - (*(uri-2) == '2' && - (*(uri-1) < '5' || (*(uri-1) == '5' && *uri <= '5')) + !( (*(uri-2) < wxT('2')) || + //240 or less + (*(uri-2) == wxT('2') && + (*(uri-1) < wxT('5') || (*(uri-1) == wxT('5') && *uri <= wxT('5'))) ) ) ) @@ -908,18 +1118,6 @@ bool wxURI::ParseIPv4address(const wxChar*& uri) return iIPv4 == 4; } -bool wxURI::ParseH16(const wxChar*& uri) -{ - // h16 = 1*4HEXDIG - if(!IsHex(*++uri)) - return false; - - if(IsHex(*++uri) && IsHex(*++uri) && IsHex(*++uri)) - ++uri; - - return true; -} - bool wxURI::ParseIPv6address(const wxChar*& uri) { // IPv6address = 6( h16 ":" ) ls32 @@ -945,8 +1143,8 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) bEndHex = true; break; } - - if(*uri != ':') + + if(*uri != wxT(':')) { break; } @@ -959,9 +1157,9 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) if (numPrefix) return false; - if (*uri == ':') + if (*uri == wxT(':')) { - if (*++uri != ':') + if (*++uri != wxT(':')) return false; maxPostfix = 5; @@ -971,18 +1169,18 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) } else { - if (*uri != ':' || *(uri+1) != ':') + if (*uri != wxT(':') || *(uri+1) != wxT(':')) { if (numPrefix != 6) return false; - while (*--uri != ':') {} + while (*--uri != wxT(':')) {} ++uri; const wxChar* uristart = uri; //parse ls32 // ls32 = ( h16 ":" h16 ) / IPv4address - if (ParseH16(uri) && *uri == ':' && ParseH16(uri)) + if (ParseH16(uri) && *uri == wxT(':') && ParseH16(uri)) return true; uri = uristart; @@ -995,7 +1193,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) else { uri += 2; - + if (numPrefix > 3) maxPostfix = 0; else @@ -1007,7 +1205,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) for(; maxPostfix != 0; --maxPostfix) { - if(!ParseH16(uri) || *uri != ':') + if(!ParseH16(uri) || *uri != wxT(':')) return false; } @@ -1016,7 +1214,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) const wxChar* uristart = uri; //parse ls32 // ls32 = ( h16 ":" h16 ) / IPv4address - if (ParseH16(uri) && *uri == ':' && ParseH16(uri)) + if (ParseH16(uri) && *uri == wxT(':') && ParseH16(uri)) return true; uri = uristart; @@ -1025,7 +1223,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) return true; uri = uristart; - + if (!bAllowAltEnding) return false; } @@ -1039,181 +1237,97 @@ bool wxURI::ParseIPv6address(const wxChar*& uri) bool wxURI::ParseIPvFuture(const wxChar*& uri) { // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) - if (*++uri != 'v' || !IsHex(*++uri)) + if (*++uri != wxT('v') || !IsHex(*++uri)) return false; while (IsHex(*++uri)) {} - if (*uri != '.' || !(IsUnreserved(*++uri) || IsSubDelim(*uri) || *uri == ':')) + if (*uri != wxT('.') || !(IsUnreserved(*++uri) || IsSubDelim(*uri) || *uri == wxT(':'))) return false; - while(IsUnreserved(*++uri) || IsSubDelim(*uri) || *uri == ':') {} + while(IsUnreserved(*++uri) || IsSubDelim(*uri) || *uri == wxT(':')) {} return true; } // --------------------------------------------------------------------------- -// Misc methods - IsXXX and CharToHex +// CharToHex +// +// Converts a character into a numeric hexidecimal value, or 0 if the +// passed in character is not a valid hex character // --------------------------------------------------------------------------- -int wxURI::CharToHex(const wxChar& c) +//static +wxChar wxURI::CharToHex(const wxChar& c) { - if ((c >= 'A') && (c <= 'Z')) return c - 'A' + 0x0A; - if ((c >= 'a') && (c <= 'z')) return c - 'a' + 0x0a; - if ((c >= '0') && (c <= '9')) return c - '0' + 0x00; + if ((c >= wxT('A')) && (c <= wxT('Z'))) return wxChar(c - wxT('A') + 0x0A); + if ((c >= wxT('a')) && (c <= wxT('z'))) return wxChar(c - wxT('a') + 0x0a); + if ((c >= wxT('0')) && (c <= wxT('9'))) return wxChar(c - wxT('0') + 0x00); - return 0; + return 0; } +// --------------------------------------------------------------------------- +// IsXXX +// +// Returns true if the passed in character meets the criteria of the method +// --------------------------------------------------------------------------- + //! unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" bool wxURI::IsUnreserved (const wxChar& c) -{ return IsAlpha(c) || IsDigit(c) || - c == '-' || - c == '.' || - c == '_' || - c == '~' //tilde - ; +{ return IsAlpha(c) || IsDigit(c) || + c == wxT('-') || + c == wxT('.') || + c == wxT('_') || + c == wxT('~') //tilde + ; } bool wxURI::IsReserved (const wxChar& c) -{ +{ return IsGenDelim(c) || IsSubDelim(c); } //! gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" bool wxURI::IsGenDelim (const wxChar& c) { - return c == ':' || - c == '/' || - c == '?' || - c == '#' || - c == '[' || - c == ']' || - c == '@'; + return c == wxT(':') || + c == wxT('/') || + c == wxT('?') || + c == wxT('#') || + c == wxT('[') || + c == wxT(']') || + c == wxT('@'); } //! sub-delims = "!" / "$" / "&" / "'" / "(" / ")" //! / "*" / "+" / "," / ";" / "=" bool wxURI::IsSubDelim (const wxChar& c) { - return c == '!' || - c == '$' || - c == '&' || - c == '\'' || - c == '(' || - c == ')' || - c == '*' || - c == '+' || - c == ',' || - c == ';' || - c == '=' + return c == wxT('!') || + c == wxT('$') || + c == wxT('&') || + c == wxT('\'') || + c == wxT('(') || + c == wxT(')') || + c == wxT('*') || + c == wxT('+') || + c == wxT(',') || + c == wxT(';') || + c == wxT('=') ; } bool wxURI::IsHex(const wxChar& c) -{ return IsDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } +{ return IsDigit(c) || (c >= wxT('a') && c <= wxT('f')) || (c >= wxT('A') && c <= wxT('F')); } bool wxURI::IsAlpha(const wxChar& c) -{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +{ return (c >= wxT('a') && c <= wxT('z')) || (c >= wxT('A') && c <= wxT('Z')); } bool wxURI::IsDigit(const wxChar& c) -{ return c >= '0' && c <= '9'; } - - -// --------------------------------------------------------------------------- -// -// wxURL Compatability -// -// TODO: Use wxURI instead here... -// --------------------------------------------------------------------------- - -#if wxUSE_URL - -#include "wx/url.h" - -wxString wxURL::ConvertToValidURI(const wxString& uri, const wxChar* delims) -{ - wxString out_str; - wxString hexa_code; - size_t i; - - for (i = 0; i < uri.Len(); i++) - { - wxChar c = uri.GetChar(i); - - if (c == wxT(' ')) - { - // GRG, Apr/2000: changed to "%20" instead of '+' - - out_str += wxT("%20"); - } - else - { - // GRG, Apr/2000: modified according to the URI definition (RFC 2396) - // - // - Alphanumeric characters are never escaped - // - Unreserved marks are never escaped - // - Delimiters must be escaped if they appear within a component - // but not if they are used to separate components. Here we have - // no clear way to distinguish between these two cases, so they - // are escaped unless they are passed in the 'delims' parameter - // (allowed delimiters). - - static const wxChar marks[] = wxT("-_.!~*()'"); - - if ( !wxIsalnum(c) && !wxStrchr(marks, c) && !wxStrchr(delims, c) ) - { - hexa_code.Printf(wxT("%%%02X"), c); - out_str += hexa_code; - } - else - { - out_str += c; - } - } - } - - return out_str; -} - -wxString wxURL::ConvertFromURI(const wxString& uri) -{ - wxString new_uri; - - size_t i = 0; - while (i < uri.Len()) - { - int code; - if (uri[i] == wxT('%')) - { - i++; - if (uri[i] >= wxT('A') && uri[i] <= wxT('F')) - code = (uri[i] - wxT('A') + 10) * 16; - else if (uri[i] >= wxT('a') && uri[i] <= wxT('f')) - code = (uri[i] - wxT('a') + 10) * 16; - else - code = (uri[i] - wxT('0')) * 16; - - i++; - if (uri[i] >= wxT('A') && uri[i] <= wxT('F')) - code += (uri[i] - wxT('A')) + 10; - else if (uri[i] >= wxT('a') && uri[i] <= wxT('f')) - code += (uri[i] - wxT('a')) + 10; - else - code += (uri[i] - wxT('0')); - - i++; - new_uri += (wxChar)code; - continue; - } - new_uri += uri[i]; - i++; - } - return new_uri; -} +{ return c >= wxT('0') && c <= wxT('9'); } -#endif //wxUSE_URL //end of uri.cpp