// 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
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);
}
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;
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()));
}
// ---------------------------------------------------------------------------
// 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;
{
// 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
//
{
ret += wxT("//");
- if (HasUser())
- ret = ret + m_user + wxT("@");
+ if (HasUserInfo())
+ ret = ret + m_userinfo + wxT("@");
ret += m_server;
{
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);
//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;
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);
}
else
//relative uri with relative path reference
- m_scheme = wxT("");
+ m_scheme = wxEmptyString;
}
// else
//relative uri with _possible_ relative path reference
// 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);
// 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;
}
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
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
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
// 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++);
}
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++);
}
if (bNormalize)
{
wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
-#if wxUSE_STL
- wxMemcpy(theBuffer, m_path.c_str(), 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));
//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++);
}
{
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++);
}
if (bNormalize)
{
wxStringBufferLength theBuffer(m_path, m_path.length() + 1);
-#if wxUSE_STL
- wxMemcpy(theBuffer, m_path.c_str(), 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));
++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++);
}
++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++);
}
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;
// T.query = R.query;
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) != 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;
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());
}
}
// ---------------------------------------------------------------------------
//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('/'))
{
//!!!//
}
+// 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
//
{ 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