]>
git.saurik.com Git - wxWidgets.git/blob - src/common/uri.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Implementation of a uri parser
7 // Copyright: (c) 2004 Ryan Norton
9 /////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
20 #pragma implementation "uri.h"
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
32 // ---------------------------------------------------------------------------
34 // ---------------------------------------------------------------------------
36 IMPLEMENT_CLASS(wxURI
, wxObject
);
38 // ===========================================================================
40 // ===========================================================================
42 // ---------------------------------------------------------------------------
44 // ---------------------------------------------------------------------------
46 // ---------------------------------------------------------------------------
50 // ---------------------------------------------------------------------------
52 // ---------------------------------------------------------------------------
54 // ---------------------------------------------------------------------------
56 wxURI::wxURI() : m_hostType(wxURI_REGNAME
), m_fields(0)
60 wxURI::wxURI(const wxString
& uri
) : m_hostType(wxURI_REGNAME
), m_fields(0)
65 wxURI::wxURI(const wxURI
& uri
) : m_hostType(wxURI_REGNAME
), m_fields(0)
70 // ---------------------------------------------------------------------------
71 // Destructor and cleanup
72 // ---------------------------------------------------------------------------
81 m_scheme
= m_user
= m_server
= m_port
= m_path
=
82 m_query
= m_fragment
= wxT("");
84 m_hostType
= wxURI_REGNAME
;
89 // ---------------------------------------------------------------------------
92 // This creates the URI - all we do here is call the main parsing method
93 // ---------------------------------------------------------------------------
95 void wxURI::Create(const wxString
& uri
)
103 // ---------------------------------------------------------------------------
104 // Escape/Unescape/IsEscape
106 // Unescape unencodes a 3 character URL escape sequence
107 // Escape encodes an invalid URI character into a 3 character sequence
108 // IsEscape determines if the input string contains an escape sequence,
109 // if it does, then it moves the input string past the escape sequence
110 // ---------------------------------------------------------------------------
112 wxChar
wxURI::Unescape(const wxChar
* s
)
114 wxASSERT_MSG(IsHex(*s
) && IsHex(*(s
+1)), wxT("Invalid escape!"));
116 return CharToHex(*s
) * 0x10 + CharToHex(*++s
);
119 void wxURI::Escape(wxString
& s
, const wxChar
& c
)
121 const wxChar
* hdig
= wxT("0123456789abcdef");
123 s
+= hdig
[(c
>> 4) & 15];
127 bool wxURI::IsEscape(const wxChar
*& uri
)
129 if(*uri
== '%' && IsHex(*(uri
+1)) && IsHex(*(uri
+2)))
138 // ---------------------------------------------------------------------------
140 // ---------------------------------------------------------------------------
142 bool wxURI::HasScheme() const
143 { return (m_fields
& wxURI_SCHEME
) == wxURI_SCHEME
; }
145 bool wxURI::HasUser() const
146 { return (m_fields
& wxURI_USER
) == wxURI_USER
; }
148 bool wxURI::HasServer() const
149 { return (m_fields
& wxURI_SERVER
) == wxURI_SERVER
; }
151 bool wxURI::HasPort() const
152 { return (m_fields
& wxURI_PORT
) == wxURI_PORT
; }
154 bool wxURI::HasPath() const
155 { return (m_fields
& wxURI_PATH
) == wxURI_PATH
; }
157 bool wxURI::HasQuery() const
158 { return (m_fields
& wxURI_QUERY
) == wxURI_QUERY
; }
160 bool wxURI::HasFragment() const
161 { return (m_fields
& wxURI_FRAGMENT
) == wxURI_FRAGMENT
; }
163 // ---------------------------------------------------------------------------
166 // The normal Get() actually builds the entire URI into a useable
167 // representation, including proper identification characters such as slashes
168 // ---------------------------------------------------------------------------
170 const wxString
& wxURI::GetScheme() const
173 const wxString
& wxURI::GetPath() const
176 const wxString
& wxURI::GetQuery() const
179 const wxString
& wxURI::GetFragment() const
180 { return m_fragment
; }
182 const wxString
& wxURI::GetPort() const
185 const wxString
& wxURI::GetUser() const
188 const wxString
& wxURI::GetServer() const
191 const wxURIHostType
& wxURI::GetHostType() const
192 { return m_hostType
; }
194 wxString
wxURI::Get() const
199 ret
= ret
+ m_scheme
+ wxT(":");
206 ret
= ret
+ m_user
+ wxT("@");
211 ret
= ret
+ wxT(":") + m_port
;
217 ret
= ret
+ wxT("?") + m_query
;
220 ret
= ret
+ wxT("#") + m_fragment
;
225 // ---------------------------------------------------------------------------
227 // ---------------------------------------------------------------------------
229 wxURI
& wxURI::operator = (const wxURI
& uri
)
232 m_scheme
= uri
.m_scheme
;
240 m_server
= uri
.m_server
;
241 m_hostType
= uri
.m_hostType
;
252 m_query
= uri
.m_query
;
255 m_fragment
= uri
.m_fragment
;
260 wxURI
& wxURI::operator = (const wxChar
* string
)
266 bool wxURI::operator == (const wxURI
& uri
) const
270 if(m_scheme
!= uri
.m_scheme
)
273 else if (uri
.HasScheme())
281 if (m_user
!= uri
.m_user
)
284 else if (uri
.HasUser())
287 if (m_server
!= uri
.m_server
||
288 m_hostType
!= uri
.m_hostType
)
293 if(m_port
!= uri
.m_port
)
296 else if (uri
.HasPort())
299 else if (uri
.HasServer())
305 if(m_path
!= uri
.m_path
)
308 else if (uri
.HasPath())
313 if (m_query
!= uri
.m_query
)
316 else if (uri
.HasQuery())
321 if (m_fragment
!= uri
.m_fragment
)
324 else if (uri
.HasFragment())
330 // ---------------------------------------------------------------------------
333 // if there is no authority or scheme, it is a reference
334 // ---------------------------------------------------------------------------
336 bool wxURI::IsReference() const
337 { return !HasScheme() || !HasServer(); }
339 // ---------------------------------------------------------------------------
342 // Master URI parsing method. Just calls the individual parsing methods
344 // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
345 // URI-reference = URI / relative-URITestCase
346 // ---------------------------------------------------------------------------
348 const wxChar
* wxURI::Parse(const wxChar
* uri
)
350 uri
= ParseScheme(uri
);
351 uri
= ParseAuthority(uri
);
352 uri
= ParsePath(uri
);
353 uri
= ParseQuery(uri
);
354 return ParseFragment(uri
);
357 // ---------------------------------------------------------------------------
360 // Individual parsers for each URI component
361 // ---------------------------------------------------------------------------
363 const wxChar
* wxURI::ParseScheme(const wxChar
* uri
)
365 wxASSERT(uri
!= NULL
);
367 //copy of the uri - used for figuring out
368 //length of each component
369 const wxChar
* uricopy
= uri
;
371 //Does the uri have a scheme (first character alpha)?
376 //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
377 //RN: Scheme can not be escaped
378 while (IsAlpha(*uri
) || IsDigit(*uri
) ||
389 //mark the scheme as valid
390 m_fields
|= wxURI_SCHEME
;
392 //move reference point up to input buffer
396 //relative uri with relative path reference
400 //relative uri with _possible_ relative path reference
405 const wxChar
* wxURI::ParseAuthority(const wxChar
* uri
)
407 // authority = [ userinfo "@" ] host [ ":" port ]
408 if (*uri
== '/' && *(uri
+1) == '/')
412 uri
= ParseUser(uri
);
413 uri
= ParseServer(uri
);
414 return ParsePort(uri
);
420 const wxChar
* wxURI::ParseUser(const wxChar
* uri
)
422 wxASSERT(uri
!= NULL
);
424 //copy of the uri - used for figuring out
425 //length of each component
426 const wxChar
* uricopy
= uri
;
428 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
429 while(*uri
&& *uri
!= '@' && *uri
!= '/' && *uri
!= '#' && *uri
!= '?')
431 if(IsUnreserved(*uri
) || IsEscape(uri
) ||
432 IsSubDelim(*uri
) || *uri
== ':')
435 Escape(m_user
, *uri
++);
441 m_fields
|= wxURI_USER
;
451 const wxChar
* wxURI::ParseServer(const wxChar
* uri
)
453 wxASSERT(uri
!= NULL
);
455 //copy of the uri - used for figuring out
456 //length of each component
457 const wxChar
* uricopy
= uri
;
459 // host = IP-literal / IPv4address / reg-name
460 // IP-literal = "[" ( IPv6address / IPvFuture ) "]"
463 if (ParseIPv6address(++uri
) && *uri
== ']')
466 m_hostType
= wxURI_IPV6ADDRESS
;
468 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
469 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
470 theBuffer
.SetLength(uri
-uricopy
);
476 if (ParseIPvFuture(++uri
) && *uri
== ']')
479 m_hostType
= wxURI_IPVFUTURE
;
481 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
482 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
483 theBuffer
.SetLength(uri
-uricopy
);
491 if (ParseIPv4address(uri
))
493 m_hostType
= wxURI_IPV4ADDRESS
;
495 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
496 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
497 theBuffer
.SetLength(uri
-uricopy
);
503 if(m_hostType
== wxURI_REGNAME
)
506 // reg-name = *( unreserved / pct-encoded / sub-delims )
507 while(*uri
&& *uri
!= '/' && *uri
!= ':' && *uri
!= '#' && *uri
!= '?')
509 if(IsUnreserved(*uri
) || IsEscape(uri
) || IsSubDelim(*uri
))
512 Escape(m_server
, *uri
++);
516 //mark the server as valid
517 m_fields
|= wxURI_SERVER
;
523 const wxChar
* wxURI::ParsePort(const wxChar
* uri
)
525 wxASSERT(uri
!= NULL
);
536 //mark the port as valid
537 m_fields
|= wxURI_PORT
;
543 const wxChar
* wxURI::ParsePath(const wxChar
* uri
, bool bReference
, bool bNormalize
)
545 wxASSERT(uri
!= NULL
);
547 //copy of the uri - used for figuring out
548 //length of each component
549 const wxChar
* uricopy
= uri
;
551 /// hier-part = "//" authority path-abempty
556 /// relative-part = "//" authority path-abempty
561 /// path-abempty = *( "/" segment )
562 /// path-absolute = "/" [ segment-nz *( "/" segment ) ]
563 /// path-noscheme = segment-nz-nc *( "/" segment )
564 /// path-rootless = segment-nz *( "/" segment )
565 /// path-empty = 0<pchar>
568 /// segment-nz = 1*pchar
569 /// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
570 /// ; non-zero-length segment without any colon ":"
572 /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
577 while(*uri
&& *uri
!= '#' && *uri
!= '?')
579 if( IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
580 *uri
== ':' || *uri
== '@' || *uri
== '/')
583 Escape(m_path
, *uri
++);
588 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
589 Normalize(theBuffer
, true);
590 theBuffer
.SetLength(wxStrlen(theBuffer
));
592 //mark the path as valid
593 m_fields
|= wxURI_PATH
;
595 else if(*uri
) //Relative path
600 while(*uri
&& *uri
!= '#' && *uri
!= '?')
602 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
603 *uri
== '@' || *uri
== '/')
606 Escape(m_path
, *uri
++);
611 while(*uri
&& *uri
!= '#' && *uri
!= '?')
613 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
614 *uri
== ':' || *uri
== '@' || *uri
== '/')
617 Escape(m_path
, *uri
++);
625 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
626 Normalize(theBuffer
);
627 theBuffer
.SetLength(wxStrlen(theBuffer
));
630 //mark the path as valid
631 m_fields
|= wxURI_PATH
;
639 const wxChar
* wxURI::ParseQuery(const wxChar
* uri
)
641 wxASSERT(uri
!= NULL
);
643 // query = *( pchar / "/" / "?" )
647 while(*uri
&& *uri
!= '#')
649 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
650 *uri
== ':' || *uri
== '@' || *uri
== '/' || *uri
== '?')
653 Escape(m_query
, *uri
++);
656 //mark the server as valid
657 m_fields
|= wxURI_QUERY
;
664 const wxChar
* wxURI::ParseFragment(const wxChar
* uri
)
666 wxASSERT(uri
!= NULL
);
668 // fragment = *( pchar / "/" / "?" )
674 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
675 *uri
== ':' || *uri
== '@' || *uri
== '/' || *uri
== '?')
676 m_fragment
+= *uri
++;
678 Escape(m_fragment
, *uri
++);
681 //mark the server as valid
682 m_fields
|= wxURI_FRAGMENT
;
688 // ---------------------------------------------------------------------------
691 // Builds missing components of this uri from a base uri
693 // A version of the algorithm outlined in the RFC is used here
694 // (it is shown in comments)
695 // ---------------------------------------------------------------------------
697 void wxURI::Resolve(const wxURI
& base
, int flags
)
699 wxASSERT_MSG(!base
.IsReference(),
700 wxT("wxURI to inherit from must not be a reference!"));
702 // If we arn't being strict, enable the older
703 // loophole that allows this uri to inherit other
704 // properties from the base uri - even if the scheme
706 if ( !(flags
& wxURI_STRICT
) &&
707 HasScheme() && base
.HasScheme() &&
708 m_scheme
== base
.m_scheme
)
710 m_fields
-= wxURI_SCHEME
;
714 // Do nothing if this is an absolute wxURI
715 // if defined(R.scheme) then
716 // T.scheme = R.scheme;
717 // T.authority = R.authority;
718 // T.path = remove_dot_segments(R.path);
719 // T.query = R.query;
726 m_scheme
= base
.m_scheme
;
727 m_fields
|= wxURI_SCHEME
;
729 // All we need to do for relative URIs with an
730 // authority component is just inherit the scheme
731 // if defined(R.authority) then
732 // T.authority = R.authority;
733 // T.path = remove_dot_segments(R.path);
734 // T.query = R.query;
740 //No authority - inherit
743 m_user
= base
.m_user
;
744 m_fields
|= wxURI_USER
;
747 m_server
= base
.m_server
;
748 m_hostType
= base
.m_hostType
;
749 m_fields
|= wxURI_SERVER
;
753 m_port
= base
.m_port
;
754 m_fields
|= wxURI_PORT
;
758 // Simple path inheritance from base
761 // T.path = Base.path;
762 m_path
= base
.m_path
;
763 m_fields
|= wxURI_PATH
;
766 // if defined(R.query) then
767 // T.query = R.query;
769 // T.query = Base.query;
773 m_query
= base
.m_query
;
774 m_fields
|= wxURI_QUERY
;
779 // if (R.path starts-with "/") then
780 // T.path = remove_dot_segments(R.path);
782 // T.path = merge(Base.path, R.path);
783 // T.path = remove_dot_segments(T.path);
785 // T.query = R.query;
786 if (m_path
[(const size_t&)0] != '/')
789 const wxChar
* op
= m_path
.c_str();
790 const wxChar
* bp
= base
.m_path
.c_str() + base
.m_path
.Length();
792 //not a ending directory? move up
793 if (base
.m_path
[0] && *(bp
-1) != '/')
794 UpTree(base
.m_path
, bp
);
796 //normalize directories
797 while(*op
== '.' && *(op
+1) == '.' &&
798 (*(op
+2) == '\0' || *(op
+2) == '/') )
800 UpTree(base
.m_path
, bp
);
808 m_path
= base
.m_path
.substr(0, bp
- base
.m_path
.c_str()) +
809 m_path
.Mid((op
- m_path
.c_str()), m_path
.Length());
814 // ---------------------------------------------------------------------------
815 // Directory Normalization (static)
817 // UpTree goes up a directory in a string and moves the pointer as such,
818 // while Normalize gets rid of duplicate/erronues directories in a URI
819 // according to RFC 2396 and modified quite a bit to meet the unit tests
821 // ---------------------------------------------------------------------------
823 void wxURI::UpTree(const wxChar
* uristart
, const wxChar
*& uri
)
825 if (uri
!= uristart
&& *(uri
-1) == '/')
830 for(;uri
!= uristart
; --uri
)
840 if (uri
== uristart
&& *uri
== '/')
845 void wxURI::Normalize(wxChar
* s
, bool bIgnoreLeads
)
855 if (*cp
== '.' && (*(cp
+1) == '/' || *(cp
+1) == '\0')
856 && (bp
== cp
|| *(cp
-1) == '/'))
864 else if (*cp
== '.' && *(cp
+1) == '.' &&
865 (*(cp
+2) == '/' || *(cp
+2) == '\0')
866 && (bp
== cp
|| *(cp
-1) == '/'))
868 //.. _or_ ../ - go up the tree
871 UpTree((const wxChar
*)bp
, (const wxChar
*&)s
);
878 else if (!bIgnoreLeads
)
903 // ---------------------------------------------------------------------------
904 // Misc. Parsing Methods
905 // ---------------------------------------------------------------------------
907 bool wxURI::ParseIPv4address(const wxChar
*& uri
)
909 //IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
911 //dec-octet = DIGIT ; 0-9
912 // / %x31-39 DIGIT ; 10-99
913 // / "1" 2DIGIT ; 100-199
914 // / "2" %x30-34 DIGIT ; 200-249
915 // / "25" %x30-35 ; 250-255
922 //each ip part must be between 0-255 (dupe of version in for loop)
923 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
924 //100 or less (note !)
925 !( (*(uri
-2) < '2') ||
928 (*(uri
-1) < '5' || (*(uri
-1) == '5' && *uri
<= '5'))
936 if(IsDigit(*uri
))++uri
;
938 //compilers should unroll this loop
939 for(; iIPv4
< 4; ++iIPv4
)
941 if (*uri
!= '.' || !IsDigit(*++uri
))
944 //each ip part must be between 0-255
945 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
946 //100 or less (note !)
947 !( (*(uri
-2) < '2') ||
950 (*(uri
-1) < '5' || (*(uri
-1) == '5' && *uri
<= '5'))
957 if(IsDigit(*uri
))++uri
;
963 bool wxURI::ParseH16(const wxChar
*& uri
)
969 if(IsHex(*++uri
) && IsHex(*++uri
) && IsHex(*++uri
))
975 bool wxURI::ParseIPv6address(const wxChar
*& uri
)
977 // IPv6address = 6( h16 ":" ) ls32
978 // / "::" 5( h16 ":" ) ls32
979 // / [ h16 ] "::" 4( h16 ":" ) ls32
980 // / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
981 // / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
982 // / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
983 // / [ *4( h16 ":" ) h16 ] "::" ls32
984 // / [ *5( h16 ":" ) h16 ] "::" h16
985 // / [ *6( h16 ":" ) h16 ] "::"
987 size_t numPrefix
= 0,
990 bool bEndHex
= false;
992 for( ; numPrefix
< 6; ++numPrefix
)
1007 if(!bEndHex
&& !ParseH16(uri
))
1026 if (*uri
!= ':' || *(uri
+1) != ':')
1031 while (*--uri
!= ':') {}
1034 const wxChar
* uristart
= uri
;
1036 // ls32 = ( h16 ":" h16 ) / IPv4address
1037 if (ParseH16(uri
) && *uri
== ':' && ParseH16(uri
))
1042 if (ParseIPv4address(uri
))
1054 maxPostfix
= 4 - numPrefix
;
1058 bool bAllowAltEnding
= maxPostfix
== 0;
1060 for(; maxPostfix
!= 0; --maxPostfix
)
1062 if(!ParseH16(uri
) || *uri
!= ':')
1068 const wxChar
* uristart
= uri
;
1070 // ls32 = ( h16 ":" h16 ) / IPv4address
1071 if (ParseH16(uri
) && *uri
== ':' && ParseH16(uri
))
1076 if (ParseIPv4address(uri
))
1081 if (!bAllowAltEnding
)
1085 if(numPrefix
<= 5 && ParseH16(uri
))
1091 bool wxURI::ParseIPvFuture(const wxChar
*& uri
)
1093 // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1094 if (*++uri
!= 'v' || !IsHex(*++uri
))
1097 while (IsHex(*++uri
)) {}
1099 if (*uri
!= '.' || !(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== ':'))
1102 while(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== ':') {}
1108 // ---------------------------------------------------------------------------
1109 // Misc methods - IsXXX and CharToHex
1110 // ---------------------------------------------------------------------------
1112 int wxURI::CharToHex(const wxChar
& c
)
1114 if ((c
>= 'A') && (c
<= 'Z')) return c
- 'A' + 0x0A;
1115 if ((c
>= 'a') && (c
<= 'z')) return c
- 'a' + 0x0a;
1116 if ((c
>= '0') && (c
<= '9')) return c
- '0' + 0x00;
1121 //! unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1122 bool wxURI::IsUnreserved (const wxChar
& c
)
1123 { return IsAlpha(c
) || IsDigit(c
) ||
1131 bool wxURI::IsReserved (const wxChar
& c
)
1133 return IsGenDelim(c
) || IsSubDelim(c
);
1136 //! gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
1137 bool wxURI::IsGenDelim (const wxChar
& c
)
1148 //! sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1149 //! / "*" / "+" / "," / ";" / "="
1150 bool wxURI::IsSubDelim (const wxChar
& c
)
1166 bool wxURI::IsHex(const wxChar
& c
)
1167 { return IsDigit(c
) || (c
>= 'a' && c
<= 'f') || (c
>= 'A' && c
<= 'F'); }
1169 bool wxURI::IsAlpha(const wxChar
& c
)
1170 { return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'); }
1172 bool wxURI::IsDigit(const wxChar
& c
)
1173 { return c
>= '0' && c
<= '9'; }
1176 // ---------------------------------------------------------------------------
1178 // wxURL Compatability
1180 // TODO: Use wxURI instead here...
1181 // ---------------------------------------------------------------------------
1187 wxString
wxURL::ConvertToValidURI(const wxString
& uri
, const wxChar
* delims
)
1193 for (i
= 0; i
< uri
.Len(); i
++)
1195 wxChar c
= uri
.GetChar(i
);
1199 // GRG, Apr/2000: changed to "%20" instead of '+'
1201 out_str
+= wxT("%20");
1205 // GRG, Apr/2000: modified according to the URI definition (RFC 2396)
1207 // - Alphanumeric characters are never escaped
1208 // - Unreserved marks are never escaped
1209 // - Delimiters must be escaped if they appear within a component
1210 // but not if they are used to separate components. Here we have
1211 // no clear way to distinguish between these two cases, so they
1212 // are escaped unless they are passed in the 'delims' parameter
1213 // (allowed delimiters).
1215 static const wxChar marks
[] = wxT("-_.!~*()'");
1217 if ( !wxIsalnum(c
) && !wxStrchr(marks
, c
) && !wxStrchr(delims
, c
) )
1219 hexa_code
.Printf(wxT("%%%02X"), c
);
1220 out_str
+= hexa_code
;
1232 wxString
wxURL::ConvertFromURI(const wxString
& uri
)
1237 while (i
< uri
.Len())
1240 if (uri
[i
] == wxT('%'))
1243 if (uri
[i
] >= wxT('A') && uri
[i
] <= wxT('F'))
1244 code
= (uri
[i
] - wxT('A') + 10) * 16;
1245 else if (uri
[i
] >= wxT('a') && uri
[i
] <= wxT('f'))
1246 code
= (uri
[i
] - wxT('a') + 10) * 16;
1248 code
= (uri
[i
] - wxT('0')) * 16;
1251 if (uri
[i
] >= wxT('A') && uri
[i
] <= wxT('F'))
1252 code
+= (uri
[i
] - wxT('A')) + 10;
1253 else if (uri
[i
] >= wxT('a') && uri
[i
] <= wxT('f'))
1254 code
+= (uri
[i
] - wxT('a')) + 10;
1256 code
+= (uri
[i
] - wxT('0'));
1259 new_uri
+= (wxChar
)code
;