]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/uri.cpp
reenable WS_TABSTOP (patch 1045547)
[wxWidgets.git] / src / common / uri.cpp
index e37c99ccd01d8cfc93d52e6dc4ce7c8463f1f9d4..be18e65e5d3fd59a257cd3e2749c4ddd315c885a 100644 (file)
@@ -56,15 +56,15 @@ 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)
 {
-    *this = uri;
+    Assign(uri);
 }
 
 // ---------------------------------------------------------------------------
@@ -79,7 +79,7 @@ wxURI::~wxURI()
 void wxURI::Clear()
 {
     m_scheme = m_user = m_server = m_port = m_path =
-    m_query = m_fragment = wxT("");
+    m_query = m_fragment = wxEmptyString;
 
     m_hostType = wxURI_REGNAME;
 
@@ -89,44 +89,68 @@ 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);    
-} 
+    return Parse(uri);
+}
 
 // ---------------------------------------------------------------------------
-// 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)
+wxChar wxURI::TranslateEscape(const wxChar* s)
 {
     wxASSERT_MSG(IsHex(*s) && IsHex(*(s+1)), wxT("Invalid escape!"));
 
-    return CharToHex(*s) * 0x10 + CharToHex(*++s);
+    //<<4 == 16
+    return (wxChar)( CharToHex(*s) << 4 ) | CharToHex(*++s);
+}
+
+wxString wxURI::Unescape(const wxString& uri)
+{
+    wxString new_uri;
+
+    for(size_t i = 0; i < uri.length(); ++i)
+    {
+        if (uri[i] == wxT('%'))
+        {
+            new_uri += wxURI::TranslateEscape( &(uri.c_str()[i+1]) );
+            i += 2;
+        }
+        else
+            new_uri += 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)))
+    // pct-encoded   = "%" HEXDIG HEXDIG
+    if(*uri == wxT('%') && IsHex(*(uri+1)) && IsHex(*(uri+2)))
     {
         uri += 3;
         return true;
@@ -136,63 +160,17 @@ bool wxURI::IsEscape(const wxChar*& uri)
 }
 
 // ---------------------------------------------------------------------------
-// HasXXX
-// ---------------------------------------------------------------------------
-
-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;   }
-
-bool wxURI::HasQuery() const
-{   return (m_fields & wxURI_QUERY) == wxURI_QUERY;   }
-
-bool wxURI::HasFragment() const
-{   return (m_fields & wxURI_FRAGMENT) == wxURI_FRAGMENT;   }
-
-// ---------------------------------------------------------------------------
-// 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())
@@ -222,49 +200,79 @@ wxString wxURI::Get() const
     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())
     {
+        ret += wxT("//");
+
         if (HasUser())
-            m_user = uri.m_user;
+            ret = ret + wxURI::Unescape(m_user) + wxT("@");
 
-        m_server = uri.m_server;
-        m_hostType = uri.m_hostType;
+        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_user = uri.m_user;
+    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)
@@ -374,29 +382,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;
@@ -405,7 +412,7 @@ 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('/'))
     {
         uri += 2;
 
@@ -426,16 +433,16 @@ 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 == ':')
+        if(IsUnreserved(*uri) || IsEscape(uri) ||
+           IsSubDelim(*uri) || *uri == wxT(':'))
             m_user += *uri++;
         else
             Escape(m_user, *uri++);
     }
 
-    if(*uri == '@')
+    if(*uri == wxT('@'))
     {
         //valid userinfo
         m_fields |= wxURI_USER;
@@ -443,7 +450,7 @@ const wxChar* wxURI::ParseUser(const wxChar* uri)
         uricopy = ++uri;
     }
     else
-        m_user = wxT("");
+        m_user = wxEmptyString;
 
     return uricopy;
 }
@@ -458,45 +465,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;
     }
 
@@ -504,13 +513,13 @@ 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))
                 m_server += *uri++;
             else
                 Escape(m_server, *uri++);
-        }                
+        }
     }
 
     //mark the server as valid
@@ -519,19 +528,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;
@@ -570,22 +579,25 @@ 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 != '?') 
-        { 
+        while(*uri && *uri != wxT('#') && *uri != wxT('?'))
+        {
             if( IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(uri) ||
-                *uri == ':' || *uri == '@' || *uri == '/')
-                m_path += *uri++; 
-            else    
-                Escape(m_path, *uri++);    
+                *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/'))
+                m_path += *uri++;
+            else
+                Escape(m_path, *uri++);
         }
 
         if (bNormalize)
         {
             wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
+#if wxUSE_STL
+            wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1);
+#endif
             Normalize(theBuffer, true);
             theBuffer.SetLength(wxStrlen(theBuffer));
         }
@@ -597,32 +609,35 @@ 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++);    
+                  *uri == wxT('@') || *uri == wxT('/'))
+                    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++);    
+                   *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/'))
+                    m_path += *uri++;
+                else
+                    Escape(m_path, *uri++);
             }
         }
 
         if (uri != uricopy)
-        {         
+        {
             if (bNormalize)
             {
                 wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
+#if wxUSE_STL
+                wxTmemcpy(theBuffer, m_path.c_str(), m_path.length()+1);
+#endif
                 Normalize(theBuffer);
                 theBuffer.SetLength(wxStrlen(theBuffer));
             }
@@ -641,16 +656,16 @@ 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++;  
+                *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/') || *uri == wxT('?'))
+                  m_query += *uri++;
             else
-                  Escape(m_query, *uri++); 
+                  Escape(m_query, *uri++);
         }
 
         //mark the server as valid
@@ -666,16 +681,16 @@ 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++;  
+                *uri == wxT(':') || *uri == wxT('@') || *uri == wxT('/') || *uri == wxT('?'))
+                  m_fragment += *uri++;
             else
-                  Escape(m_fragment, *uri++); 
+                  Escape(m_fragment, *uri++);
         }
 
         //mark the server as valid
@@ -686,27 +701,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;
     }
 
@@ -722,7 +739,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;
 
@@ -743,17 +760,17 @@ void wxURI::Resolve(const wxURI& base, int flags)
         m_user = base.m_user;
         m_fields |= wxURI_USER;
     }
-    
+
     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())
@@ -761,7 +778,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;
@@ -783,19 +800,19 @@ 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
+            //Merge paths
             const wxChar* op = m_path.c_str();
             const wxChar* bp = base.m_path.c_str() + base.m_path.Length();
 
             //not a ending directory?  move up
-            if (base.m_path[0] && *(bp-1) != '/')
+            if (base.m_path[0] && *(bp-1) != wxT('/'))
                 UpTree(base.m_path, 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);
 
@@ -805,31 +822,31 @@ 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.c_str()) +
+                    m_path.substr((op - m_path.c_str()), 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
 // ---------------------------------------------------------------------------
 
+//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;
@@ -837,23 +854,35 @@ void wxURI::UpTree(const wxChar* uristart, const wxChar*& uri)
     }
 
     //!!!TODO:HACK!!!//
-    if (uri == uristart && *uri == '/')
+    if (uri == uristart && *uri == wxT('/'))
         ++uri;
     //!!!//
 }
 
+// ---------------------------------------------------------------------------
+// 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')
@@ -861,9 +890,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)
@@ -894,14 +923,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)
@@ -918,14 +972,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')))
              )
             )
           )
@@ -938,16 +992,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')))
                  )
                 )
               )
@@ -960,18 +1014,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
@@ -997,8 +1039,8 @@ bool wxURI::ParseIPv6address(const wxChar*& uri)
             bEndHex = true;
             break;
         }
-        
-        if(*uri != ':')
+
+        if(*uri != wxT(':'))
         {
             break;
         }
@@ -1011,9 +1053,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;
@@ -1023,18 +1065,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;
@@ -1047,7 +1089,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri)
         else
         {
             uri += 2;
-    
+
             if (numPrefix > 3)
                 maxPostfix = 0;
             else
@@ -1059,7 +1101,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri)
 
     for(; maxPostfix != 0; --maxPostfix)
     {
-        if(!ParseH16(uri) || *uri != ':')
+        if(!ParseH16(uri) || *uri != wxT(':'))
             return false;
     }
 
@@ -1068,7 +1110,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;
@@ -1077,7 +1119,7 @@ bool wxURI::ParseIPv6address(const wxChar*& uri)
             return true;
 
         uri = uristart;
-        
+
         if (!bAllowAltEnding)
             return false;
     }
@@ -1091,99 +1133,128 @@ 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';        }
+{   return c >= wxT('0') && c <= wxT('9');        }
 
 
 // ---------------------------------------------------------------------------
 //
-//                        wxURL Compatability
+//                        wxURL Compatibility
 //
-// TODO:  Use wxURI instead here...
 // ---------------------------------------------------------------------------
 
 #if wxUSE_URL
 
+#if WXWIN_COMPATIBILITY_2_4
+
 #include "wx/url.h"
 
+wxString wxURL::GetProtocolName() const
+{
+    return m_scheme;
+}
+
+wxString wxURL::GetHostName() const
+{
+    return m_server;
+}
+
+wxString wxURL::GetPath() const
+{
+    return m_path;
+}
+
+//Note that this old code really doesn't convert to a URI that well and looks
+//more like a dirty hack than anything else...
+
 wxString wxURL::ConvertToValidURI(const wxString& uri, const wxChar* delims)
 {
   wxString out_str;
@@ -1231,40 +1302,11 @@ wxString wxURL::ConvertToValidURI(const wxString& uri, const wxChar* delims)
 
 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 wxURI::Unescape(uri);
 }
 
+#endif //WXWIN_COMPATIBILITY_2_4
+
 #endif //wxUSE_URL
 
 //end of uri.cpp