]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/uri.cpp
native wxBitmapComboBox implementation for MSW (patch 1941399)
[wxWidgets.git] / src / common / uri.cpp
index 0d137f5bc1681834564f9a7a84edff3a2e60bdda..bcdd7eae660447ad11e6267d0c6408c4b24abc28 100644 (file)
 // 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
@@ -62,7 +62,7 @@ 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);
 }
@@ -78,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;
 
@@ -97,7 +97,10 @@ const wxChar* wxURI::Create(const wxString& uri)
     if (m_fields)
         Clear();
 
-    return 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()));
 }
 
 // ---------------------------------------------------------------------------
@@ -113,27 +116,29 @@ const wxChar* wxURI::Create(const wxString& uri)
 // Unescape unencodes all 3 character URL escape sequences in a wxString
 // ---------------------------------------------------------------------------
 
-wxChar wxURI::TranslateEscape(const wxChar* s)
+wxUniChar wxURI::TranslateEscape(const wxString::const_iterator& s)
 {
-    wxASSERT_MSG(IsHex(*s) && IsHex(*(s+1)), wxT("Invalid escape!"));
+    wxChar c1(*s);
+    wxChar c2(*(s + 1));
 
-    //<<4 == 16
-    return (wxChar)( CharToHex(*s) << 4 ) | CharToHex(*++s);
+    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(size_t i = 0; i < uri.length(); ++i)
+    for (wxString::const_iterator i = uri.begin(); i != uri.end(); ++i)
     {
-        if (uri[i] == wxT('%'))
+        if ( *i == wxT('%') )
         {
-            new_uri += wxURI::TranslateEscape( &(uri.c_str()[i+1]) );
+            new_uri += wxURI::TranslateEscape(i + 1);
             i += 2;
         }
         else
-            new_uri += uri[i];
+            new_uri += *i;
     }
 
     return new_uri;
@@ -151,14 +156,37 @@ bool wxURI::IsEscape(const wxChar*& uri)
 {
     // pct-encoded   = "%" HEXDIG HEXDIG
     if(*uri == wxT('%') && IsHex(*(uri+1)) && IsHex(*(uri+2)))
-    {
-        uri += 3;
         return true;
-    }
     else
         return false;
 }
 
+// ---------------------------------------------------------------------------
+// GetUser
+// GetPassword
+//
+// 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
 //
@@ -180,8 +208,8 @@ wxString wxURI::BuildURI() const
     {
         ret += wxT("//");
 
-        if (HasUser())
-            ret = ret + m_user + wxT("@");
+        if (HasUserInfo())
+            ret = ret + m_userinfo + wxT("@");
 
         ret += m_server;
 
@@ -211,8 +239,8 @@ wxString wxURI::BuildUnescapedURI() const
     {
         ret += wxT("//");
 
-        if (HasUser())
-            ret = ret + wxURI::Unescape(m_user) + wxT("@");
+        if (HasUserInfo())
+            ret = ret + wxURI::Unescape(m_userinfo) + wxT("@");
 
         if (m_hostType == wxURI_REGNAME)
             ret += wxURI::Unescape(m_server);
@@ -245,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;
@@ -284,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 ||
@@ -350,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 wxCharuri)
+const wxChar* wxURI::Parse(const wxChar *uri)
 {
     uri = ParseScheme(uri);
     uri = ParseAuthority(uri);
@@ -368,7 +396,7 @@ const wxChar* wxURI::Parse(const wxChar* uri)
 // Individual parsers for each URI component
 // ---------------------------------------------------------------------------
 
-const wxChar* wxURI::ParseScheme(const wxCharuri)
+const wxChar* wxURI::ParseScheme(const wxChar *uri)
 {
     wxASSERT(uri != NULL);
 
@@ -401,7 +429,7 @@ const wxChar* wxURI::ParseScheme(const wxChar* uri)
         }
         else
             //relative uri with relative path reference
-            m_scheme = wxT("");
+            m_scheme = wxEmptyString;
     }
 //    else
         //relative uri with _possible_ relative path reference
@@ -414,17 +442,24 @@ const wxChar* wxURI::ParseAuthority(const wxChar* uri)
     // authority     = [ userinfo "@" ] host [ ":" port ]
     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);
 
@@ -435,22 +470,28 @@ const wxChar* wxURI::ParseUser(const wxChar* uri)
     // userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
     while(*uri && *uri != wxT('@') && *uri != wxT('/') && *uri != wxT('#') && *uri != wxT('?'))
     {
-        if(IsUnreserved(*uri) || IsEscape(uri) ||
+        if(IsUnreserved(*uri) ||
            IsSubDelim(*uri) || *uri == wxT(':'))
-            m_user += *uri++;
+            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 == wxT('@'))
     {
         //valid userinfo
-        m_fields |= wxURI_USER;
+        m_fields |= wxURI_USERINFO;
 
         uricopy = ++uri;
     }
     else
-        m_user = wxT("");
+        m_userinfo = wxEmptyString;
 
     return uricopy;
 }
@@ -515,8 +556,14 @@ const wxChar* wxURI::ParseServer(const wxChar* uri)
         // reg-name      = *( unreserved / pct-encoded / sub-delims )
         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++);
         }
@@ -585,9 +632,15 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali
 
         while(*uri && *uri != wxT('#') && *uri != wxT('?'))
         {
-            if( IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(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++);
         }
@@ -595,7 +648,8 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali
         if (bNormalize)
         {
             wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
-#if wxUSE_STL
+#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);
@@ -611,9 +665,15 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali
             //no colon allowed
             while(*uri && *uri != wxT('#') && *uri != wxT('?'))
             {
-                if(IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(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++);
             }
@@ -622,9 +682,15 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali
         {
             while(*uri && *uri != wxT('#') && *uri != wxT('?'))
             {
-                if(IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(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++);
             }
@@ -635,7 +701,8 @@ const wxChar* wxURI::ParsePath(const wxChar* uri, bool bReference, bool bNormali
             if (bNormalize)
             {
                 wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
-#if wxUSE_STL
+#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);
@@ -661,9 +728,15 @@ const wxChar* wxURI::ParseQuery(const wxChar* uri)
         ++uri;
         while(*uri && *uri != wxT('#'))
         {
-            if (IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(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++);
         }
@@ -686,9 +759,15 @@ const wxChar* wxURI::ParseFragment(const wxChar* uri)
         ++uri;
         while(*uri)
         {
-            if (IsUnreserved(*uri) || IsSubDelim(*uri) || IsEscape(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++);
         }
@@ -755,10 +834,10 @@ 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;
@@ -803,18 +882,18 @@ void wxURI::Resolve(const wxURI& base, int flags)
         if (m_path[0u] != wxT('/'))
         {
             //Merge paths
-            const wxChar* op = m_path.c_str();
-            const wxChar* bp = base.m_path.c_str() + base.m_path.Length();
+            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) != wxT('/'))
-                UpTree(base.m_path, bp);
+                UpTree(base.m_path.begin(), bp);
 
             //normalize directories
             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;
@@ -822,8 +901,8 @@ 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.substr((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());
         }
     }
 
@@ -837,7 +916,8 @@ void wxURI::Resolve(const wxURI& base, int flags)
 // ---------------------------------------------------------------------------
 
 //static
-void wxURI::UpTree(const wxChar* uristart, const wxChar*& uri)
+void wxURI::UpTree(wxString::const_iterator uristart,
+                   wxString::const_iterator& uri)
 {
     if (uri != uristart && *(uri-1) == wxT('/'))
     {
@@ -859,6 +939,30 @@ void wxURI::UpTree(const wxChar* uristart, const wxChar*& 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) == 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
 //
@@ -1225,75 +1329,6 @@ bool wxURI::IsDigit(const wxChar& c)
 {   return c >= wxT('0') && c <= wxT('9');        }
 
 
-// ---------------------------------------------------------------------------
-//
-//                        wxURL Compatability
-//
-// ---------------------------------------------------------------------------
-
-#if wxUSE_URL
-
-#if WXWIN_COMPATIBILITY_2_4
-
-#include "wx/url.h"
-
-//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;
-  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)
-{
-    return wxURI::Unescape(uri);
-}
-
-#endif //WXWIN_COMPATIBILITY_2_4
-
-#endif //wxUSE_URL
-
 //end of uri.cpp