// 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"
#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
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)
{
- *this = uri;
+ Assign(uri);
}
// ---------------------------------------------------------------------------
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;
// ---------------------------------------------------------------------------
// 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
// ---------------------------------------------------------------------------
-void wxURI::Unescape(const wxChar*& s, wxChar& c)
+wxUniChar wxURI::TranslateEscape(const wxString::const_iterator& s)
{
- wxASSERT_MSG(IsHex(*s) && IsHex(*(s+1)), wxT("Invalid escape!"));
- c = CharToHex(*s) * 0x10 + CharToHex(*++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)
+{
+ 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 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;
}
// ---------------------------------------------------------------------------
-// HasXXX
+// GetUser
+// GetPassword
+//
+// Gets the username and password via the old URL method.
// ---------------------------------------------------------------------------
+wxString wxURI::GetUser() const
+{
+ size_t dwPasswordPos = m_userinfo.find(':');
-bool wxURI::HasScheme() const
-{ return (m_fields & wxURI_SCHEME) == wxURI_SCHEME; }
-
-bool wxURI::HasUser() const
-{ return (m_fields & wxURI_USER) == wxURI_USER; }
-
-bool wxURI::HasServer() const
-{ return (m_fields & wxURI_SERVER) == wxURI_SERVER; }
-
-bool wxURI::HasPort() const
-{ return (m_fields & wxURI_PORT) == wxURI_PORT; }
-
-bool wxURI::HasPath() const
-{ return (m_fields & wxURI_PATH) == wxURI_PATH; }
+ if (dwPasswordPos == wxString::npos)
+ dwPasswordPos = 0;
+
+ return m_userinfo(0, dwPasswordPos);
+}
-bool wxURI::HasQuery() const
-{ return (m_fields & wxURI_QUERY) == wxURI_QUERY; }
+wxString wxURI::GetPassword() const
+{
+ size_t dwPasswordPos = m_userinfo.find(':');
-bool wxURI::HasFragment() const
-{ return (m_fields & wxURI_FRAGMENT) == wxURI_FRAGMENT; }
+ if (dwPasswordPos == wxString::npos)
+ return wxT("");
+ else
+ return m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1);
+}
// ---------------------------------------------------------------------------
-// GetXXX
+// BuildURI
//
-// The normal Get() actually builds the entire URI into a useable
+// 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
// ---------------------------------------------------------------------------
-const wxString& wxURI::GetScheme() const
-{ return m_scheme; }
-
-const wxString& wxURI::GetPath() const
-{ return m_path; }
-
-const wxString& wxURI::GetQuery() const
-{ return m_query; }
-
-const wxString& wxURI::GetFragment() const
-{ return m_fragment; }
-
-const wxString& wxURI::GetPort() const
-{ return m_port; }
-
-const wxString& wxURI::GetUser() const
-{ return m_user; }
-
-const wxString& wxURI::GetServer() const
-{ return m_server; }
-
-const wxURIHostType& wxURI::GetHostType() const
-{ return m_hostType; }
-
-wxString wxURI::Get() const
-{
+wxString wxURI::BuildURI() const
+{
wxString ret;
if (HasScheme())
{
ret += wxT("//");
- if (HasUser())
- ret = ret + m_user + wxT("@");
+ if (HasUserInfo())
+ ret = ret + m_userinfo + wxT("@");
ret += m_server;
return ret;
}
-// ---------------------------------------------------------------------------
-// operator = and ==
-// ---------------------------------------------------------------------------
-
-wxURI& wxURI::operator = (const wxURI& uri)
+wxString wxURI::BuildUnescapedURI() const
{
- if (HasScheme())
- m_scheme = uri.m_scheme;
+ wxString ret;
+ if (HasScheme())
+ ret = ret + m_scheme + wxT(":");
if (HasServer())
{
- if (HasUser())
- m_user = uri.m_user;
+ ret += wxT("//");
- m_server = uri.m_server;
- m_hostType = uri.m_hostType;
+ 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())
- m_port = uri.m_port;
+ ret = ret + wxT(":") + m_port;
}
-
- if (HasPath())
- m_path = uri.m_path;
+ ret += wxURI::Unescape(m_path);
if (HasQuery())
- m_query = uri.m_query;
+ ret = ret + wxT("?") + wxURI::Unescape(m_query);
if (HasFragment())
- m_fragment = uri.m_fragment;
+ ret = ret + wxT("#") + wxURI::Unescape(m_fragment);
+
+ return ret;
+}
+
+// ---------------------------------------------------------------------------
+// Assignment
+// ---------------------------------------------------------------------------
+
+wxURI& wxURI::Assign(const wxURI& uri)
+{
+ //assign fields
+ m_fields = uri.m_fields;
+
+ //ref over components
+ m_scheme = uri.m_scheme;
+ m_userinfo = uri.m_userinfo;
+ m_server = uri.m_server;
+ m_hostType = uri.m_hostType;
+ m_port = uri.m_port;
+ m_path = uri.m_path;
+ m_query = uri.m_query;
+ m_fragment = uri.m_fragment;
return *this;
}
-wxURI& wxURI::operator = (const wxChar* string)
-{
+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)
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 ||
// 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);
// Individual parsers for each URI component
// ---------------------------------------------------------------------------
-const wxChar* wxURI::ParseScheme(const wxChar* uri)
+const wxChar* wxURI::ParseScheme(const wxChar *uri)
{
wxASSERT(uri != NULL);
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;
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);
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;
}
// 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;
}
{
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
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;
return uri;
}
-const wxChar* wxURI::ParsePath(const wxChar* uri, const bool& bReference, const bool& bNormalize)
+const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormalize)
{
wxASSERT(uri != NULL);
/// ; 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));
}
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));
}
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
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
}
// ---------------------------------------------------------------------------
-// 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, const bool& bStrict)
+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 (!bStrict &&
- HasScheme() && base.HasScheme() &&
- this->m_scheme == base.m_scheme )
- {
+ if ( !(flags & wxURI_STRICT) &&
+ HasScheme() && base.HasScheme() &&
+ m_scheme == base.m_scheme )
+ {
m_fields -= wxURI_SCHEME;
}
return;
}
- //No sheme - inherit
+ //No scheme - inherit
m_scheme = base.m_scheme;
m_fields |= wxURI_SCHEME;
}
//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())
// T.path = Base.path;
m_path = base.m_path;
m_fields |= wxURI_PATH;
-
+
// if defined(R.query) then
// T.query = R.query;
// 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;
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) == '/')
+ if (uri != uristart && *(uri-1) == wxT('/'))
{
uri -= 2;
}
-
+
for(;uri != uristart; --uri)
{
- if (*uri == '/')
+ if (*uri == wxT('/'))
{
++uri;
break;
}
//!!!TODO:HACK!!!//
- if (uri == uristart && *uri == '/')
+ if (uri == uristart && *uri == wxT('/'))
++uri;
//!!!//
}
-void wxURI::Normalize(wxChar* s, const bool& bIgnoreLeads)
+// 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) == wxT('/'))
+ {
+ uri -= 2;
+ }
+
+ for(;uri != uristart; --uri)
+ {
+ if (*uri == wxT('/'))
+ {
+ ++uri;
+ break;
+ }
+ }
+
+ //!!!TODO:HACK!!!//
+ 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')
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)
}
}
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)
{
++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')))
)
)
)
//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')))
)
)
)
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
bEndHex = true;
break;
}
-
- if(*uri != ':')
+
+ if(*uri != wxT(':'))
{
break;
}
if (numPrefix)
return false;
- if (*uri == ':')
+ if (*uri == wxT(':'))
{
- if (*++uri != ':')
+ if (*++uri != wxT(':'))
return false;
maxPostfix = 5;
}
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;
else
{
uri += 2;
-
+
if (numPrefix > 3)
maxPostfix = 0;
else
for(; maxPostfix != 0; --maxPostfix)
{
- if(!ParseH16(uri) || *uri != ':')
+ if(!ParseH16(uri) || *uri != wxT(':'))
return false;
}
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;
return true;
uri = uristart;
-
+
if (!bAllowAltEnding)
return false;
}
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