]>
git.saurik.com Git - wxWidgets.git/blob - src/common/uri.cpp
c62395617778da6d8a869fd34c2f479c0280f769
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 void wxURI::Unescape(const wxChar
*& s
, wxChar
& c
)
114 wxASSERT_MSG(IsHex(*s
) && IsHex(*(s
+1)), wxT("Invalid escape!"));
115 c
= CharToHex(*s
) * 0x10 + CharToHex(*++s
);
118 void wxURI::Escape(wxString
& s
, const wxChar
& c
)
120 const wxChar
* hdig
= wxT("0123456789abcdef");
122 s
+= hdig
[(c
>> 4) & 15];
126 bool wxURI::IsEscape(const wxChar
*& uri
)
128 if(*uri
== '%' && IsHex(*(uri
+1)) && IsHex(*(uri
+2)))
137 // ---------------------------------------------------------------------------
139 // ---------------------------------------------------------------------------
141 bool wxURI::HasScheme() const
142 { return (m_fields
& wxURI_SCHEME
) == wxURI_SCHEME
; }
144 bool wxURI::HasUser() const
145 { return (m_fields
& wxURI_USER
) == wxURI_USER
; }
147 bool wxURI::HasServer() const
148 { return (m_fields
& wxURI_SERVER
) == wxURI_SERVER
; }
150 bool wxURI::HasPort() const
151 { return (m_fields
& wxURI_PORT
) == wxURI_PORT
; }
153 bool wxURI::HasPath() const
154 { return (m_fields
& wxURI_PATH
) == wxURI_PATH
; }
156 bool wxURI::HasQuery() const
157 { return (m_fields
& wxURI_QUERY
) == wxURI_QUERY
; }
159 bool wxURI::HasFragment() const
160 { return (m_fields
& wxURI_FRAGMENT
) == wxURI_FRAGMENT
; }
162 // ---------------------------------------------------------------------------
165 // The normal Get() actually builds the entire URI into a useable
166 // representation, including proper identification characters such as slashes
167 // ---------------------------------------------------------------------------
169 const wxString
& wxURI::GetScheme() const
172 const wxString
& wxURI::GetPath() const
175 const wxString
& wxURI::GetQuery() const
178 const wxString
& wxURI::GetFragment() const
179 { return m_fragment
; }
181 const wxString
& wxURI::GetPort() const
184 const wxString
& wxURI::GetUser() const
187 const wxString
& wxURI::GetServer() const
190 const wxURIHostType
& wxURI::GetHostType() const
191 { return m_hostType
; }
193 wxString
wxURI::Get() const
198 ret
= ret
+ m_scheme
+ wxT(":");
205 ret
= ret
+ m_user
+ wxT("@");
210 ret
= ret
+ wxT(":") + m_port
;
216 ret
= ret
+ wxT("?") + m_query
;
219 ret
= ret
+ wxT("#") + m_fragment
;
224 // ---------------------------------------------------------------------------
226 // ---------------------------------------------------------------------------
228 wxURI
& wxURI::operator = (const wxURI
& uri
)
231 m_scheme
= uri
.m_scheme
;
239 m_server
= uri
.m_server
;
240 m_hostType
= uri
.m_hostType
;
251 m_query
= uri
.m_query
;
254 m_fragment
= uri
.m_fragment
;
259 wxURI
& wxURI::operator = (const wxChar
* string
)
265 bool wxURI::operator == (const wxURI
& uri
) const
269 if(m_scheme
!= uri
.m_scheme
)
272 else if (uri
.HasScheme())
280 if (m_user
!= uri
.m_user
)
283 else if (uri
.HasUser())
286 if (m_server
!= uri
.m_server
||
287 m_hostType
!= uri
.m_hostType
)
292 if(m_port
!= uri
.m_port
)
295 else if (uri
.HasPort())
298 else if (uri
.HasServer())
304 if(m_path
!= uri
.m_path
)
307 else if (uri
.HasPath())
312 if (m_query
!= uri
.m_query
)
315 else if (uri
.HasQuery())
320 if (m_fragment
!= uri
.m_fragment
)
323 else if (uri
.HasFragment())
329 // ---------------------------------------------------------------------------
332 // if there is no authority or scheme, it is a reference
333 // ---------------------------------------------------------------------------
335 bool wxURI::IsReference() const
336 { return !HasScheme() || !HasServer(); }
338 // ---------------------------------------------------------------------------
341 // Master URI parsing method. Just calls the individual parsing methods
343 // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
344 // URI-reference = URI / relative-URITestCase
345 // ---------------------------------------------------------------------------
347 const wxChar
* wxURI::Parse(const wxChar
* uri
)
349 uri
= ParseScheme(uri
);
350 uri
= ParseAuthority(uri
);
351 uri
= ParsePath(uri
);
352 uri
= ParseQuery(uri
);
353 return ParseFragment(uri
);
356 // ---------------------------------------------------------------------------
359 // Individual parsers for each URI component
360 // ---------------------------------------------------------------------------
362 const wxChar
* wxURI::ParseScheme(const wxChar
* uri
)
364 wxASSERT(uri
!= NULL
);
366 //copy of the uri - used for figuring out
367 //length of each component
368 const wxChar
* uricopy
= uri
;
370 //Does the uri have a scheme (first character alpha)?
375 //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
376 //RN: Scheme can not be escaped
377 while (IsAlpha(*uri
) || IsDigit(*uri
) ||
388 //mark the scheme as valid
389 m_fields
|= wxURI_SCHEME
;
391 //move reference point up to input buffer
395 //relative uri with relative path reference
399 //relative uri with _possible_ relative path reference
404 const wxChar
* wxURI::ParseAuthority(const wxChar
* uri
)
406 // authority = [ userinfo "@" ] host [ ":" port ]
407 if (*uri
== '/' && *(uri
+1) == '/')
411 uri
= ParseUser(uri
);
412 uri
= ParseServer(uri
);
413 return ParsePort(uri
);
419 const wxChar
* wxURI::ParseUser(const wxChar
* uri
)
421 wxASSERT(uri
!= NULL
);
423 //copy of the uri - used for figuring out
424 //length of each component
425 const wxChar
* uricopy
= uri
;
427 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
428 while(*uri
&& *uri
!= '@' && *uri
!= '/' && *uri
!= '#' && *uri
!= '?')
430 if(IsUnreserved(*uri
) || IsEscape(uri
) ||
431 IsSubDelim(*uri
) || *uri
== ':')
434 Escape(m_user
, *uri
++);
440 m_fields
|= wxURI_USER
;
450 const wxChar
* wxURI::ParseServer(const wxChar
* uri
)
452 wxASSERT(uri
!= NULL
);
454 //copy of the uri - used for figuring out
455 //length of each component
456 const wxChar
* uricopy
= uri
;
458 // host = IP-literal / IPv4address / reg-name
459 // IP-literal = "[" ( IPv6address / IPvFuture ) "]"
462 if (ParseIPv6address(++uri
) && *uri
== ']')
465 m_hostType
= wxURI_IPV6ADDRESS
;
467 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
468 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
469 theBuffer
.SetLength(uri
-uricopy
);
475 if (ParseIPvFuture(++uri
) && *uri
== ']')
478 m_hostType
= wxURI_IPVFUTURE
;
480 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
481 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
482 theBuffer
.SetLength(uri
-uricopy
);
490 if (ParseIPv4address(uri
))
492 m_hostType
= wxURI_IPV4ADDRESS
;
494 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
495 wxMemcpy(theBuffer
, uricopy
, uri
-uricopy
);
496 theBuffer
.SetLength(uri
-uricopy
);
502 if(m_hostType
== wxURI_REGNAME
)
505 // reg-name = *( unreserved / pct-encoded / sub-delims )
506 while(*uri
&& *uri
!= '/' && *uri
!= ':' && *uri
!= '#' && *uri
!= '?')
508 if(IsUnreserved(*uri
) || IsEscape(uri
) || IsSubDelim(*uri
))
511 Escape(m_server
, *uri
++);
515 //mark the server as valid
516 m_fields
|= wxURI_SERVER
;
522 const wxChar
* wxURI::ParsePort(const wxChar
* uri
)
524 wxASSERT(uri
!= NULL
);
535 //mark the port as valid
536 m_fields
|= wxURI_PORT
;
542 const wxChar
* wxURI::ParsePath(const wxChar
* uri
, const bool& bReference
, const bool& bNormalize
)
544 wxASSERT(uri
!= NULL
);
546 //copy of the uri - used for figuring out
547 //length of each component
548 const wxChar
* uricopy
= uri
;
550 /// hier-part = "//" authority path-abempty
555 /// relative-part = "//" authority path-abempty
560 /// path-abempty = *( "/" segment )
561 /// path-absolute = "/" [ segment-nz *( "/" segment ) ]
562 /// path-noscheme = segment-nz-nc *( "/" segment )
563 /// path-rootless = segment-nz *( "/" segment )
564 /// path-empty = 0<pchar>
567 /// segment-nz = 1*pchar
568 /// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
569 /// ; non-zero-length segment without any colon ":"
571 /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
576 while(*uri
&& *uri
!= '#' && *uri
!= '?')
578 if( IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
579 *uri
== ':' || *uri
== '@' || *uri
== '/')
582 Escape(m_path
, *uri
++);
587 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
588 Normalize(theBuffer
, true);
589 theBuffer
.SetLength(wxStrlen(theBuffer
));
591 //mark the path as valid
592 m_fields
|= wxURI_PATH
;
594 else if(*uri
) //Relative path
599 while(*uri
&& *uri
!= '#' && *uri
!= '?')
601 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
602 *uri
== '@' || *uri
== '/')
605 Escape(m_path
, *uri
++);
610 while(*uri
&& *uri
!= '#' && *uri
!= '?')
612 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
613 *uri
== ':' || *uri
== '@' || *uri
== '/')
616 Escape(m_path
, *uri
++);
624 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
625 Normalize(theBuffer
);
626 theBuffer
.SetLength(wxStrlen(theBuffer
));
629 //mark the path as valid
630 m_fields
|= wxURI_PATH
;
638 const wxChar
* wxURI::ParseQuery(const wxChar
* uri
)
640 wxASSERT(uri
!= NULL
);
642 // query = *( pchar / "/" / "?" )
646 while(*uri
&& *uri
!= '#')
648 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
649 *uri
== ':' || *uri
== '@' || *uri
== '/' || *uri
== '?')
652 Escape(m_query
, *uri
++);
655 //mark the server as valid
656 m_fields
|= wxURI_QUERY
;
663 const wxChar
* wxURI::ParseFragment(const wxChar
* uri
)
665 wxASSERT(uri
!= NULL
);
667 // fragment = *( pchar / "/" / "?" )
673 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) || IsEscape(uri
) ||
674 *uri
== ':' || *uri
== '@' || *uri
== '/' || *uri
== '?')
675 m_fragment
+= *uri
++;
677 Escape(m_fragment
, *uri
++);
680 //mark the server as valid
681 m_fields
|= wxURI_FRAGMENT
;
687 // ---------------------------------------------------------------------------
690 // Builds missing components of this uri from a base uri
692 // A version of the algorithm outlined in the RFC is used here
693 // (it is shown in comments)
694 // ---------------------------------------------------------------------------
696 void wxURI::Resolve(const wxURI
& base
, const bool& bStrict
)
698 wxASSERT_MSG(!base
.IsReference(),
699 wxT("wxURI to inherit from must not be a reference!"));
701 // If we arn't being strict, enable the older
702 // loophole that allows this uri to inherit other
703 // properties from the base uri - even if the scheme
706 HasScheme() && base
.HasScheme() &&
707 this->m_scheme
== base
.m_scheme
)
709 m_fields
-= wxURI_SCHEME
;
713 // Do nothing if this is an absolute wxURI
714 // if defined(R.scheme) then
715 // T.scheme = R.scheme;
716 // T.authority = R.authority;
717 // T.path = remove_dot_segments(R.path);
718 // T.query = R.query;
725 m_scheme
= base
.m_scheme
;
726 m_fields
|= wxURI_SCHEME
;
728 // All we need to do for relative URIs with an
729 // authority component is just inherit the scheme
730 // if defined(R.authority) then
731 // T.authority = R.authority;
732 // T.path = remove_dot_segments(R.path);
733 // T.query = R.query;
739 //No authority - inherit
742 m_user
= base
.m_user
;
743 m_fields
|= wxURI_USER
;
746 m_server
= base
.m_server
;
747 m_hostType
= base
.m_hostType
;
748 m_fields
|= wxURI_SERVER
;
752 m_port
= base
.m_port
;
753 m_fields
|= wxURI_PORT
;
757 // Simple path inheritance from base
760 // T.path = Base.path;
761 m_path
= base
.m_path
;
762 m_fields
|= wxURI_PATH
;
765 // if defined(R.query) then
766 // T.query = R.query;
768 // T.query = Base.query;
772 m_query
= base
.m_query
;
773 m_fields
|= wxURI_QUERY
;
778 // if (R.path starts-with "/") then
779 // T.path = remove_dot_segments(R.path);
781 // T.path = merge(Base.path, R.path);
782 // T.path = remove_dot_segments(T.path);
784 // T.query = R.query;
785 if (m_path
[(const size_t&)0] != '/')
788 const wxChar
* op
= m_path
.c_str();
789 const wxChar
* bp
= base
.m_path
.c_str() + base
.m_path
.Length();
791 //not a ending directory? move up
792 if (base
.m_path
[0] && *(bp
-1) != '/')
793 UpTree(base
.m_path
, bp
);
795 //normalize directories
796 while(*op
== '.' && *(op
+1) == '.' &&
797 (*(op
+2) == '\0' || *(op
+2) == '/') )
799 UpTree(base
.m_path
, bp
);
807 m_path
= base
.m_path
.substr(0, bp
- base
.m_path
.c_str()) +
808 m_path
.Mid((op
- m_path
.c_str()), m_path
.Length());
813 // ---------------------------------------------------------------------------
814 // Directory Normalization (static)
816 // UpTree goes up a directory in a string and moves the pointer as such,
817 // while Normalize gets rid of duplicate/erronues directories in a URI
818 // according to RFC 2396 and modified quite a bit to meet the unit tests
820 // ---------------------------------------------------------------------------
822 void wxURI::UpTree(const wxChar
* uristart
, const wxChar
*& uri
)
824 if (uri
!= uristart
&& *(uri
-1) == '/')
829 for(;uri
!= uristart
; --uri
)
839 if (uri
== uristart
&& *uri
== '/')
844 void wxURI::Normalize(wxChar
* s
, const bool& bIgnoreLeads
)
854 if (*cp
== '.' && (*(cp
+1) == '/' || *(cp
+1) == '\0')
855 && (bp
== cp
|| *(cp
-1) == '/'))
863 else if (*cp
== '.' && *(cp
+1) == '.' &&
864 (*(cp
+2) == '/' || *(cp
+2) == '\0')
865 && (bp
== cp
|| *(cp
-1) == '/'))
867 //.. _or_ ../ - go up the tree
870 UpTree((const wxChar
*)bp
, (const wxChar
*&)s
);
877 else if (!bIgnoreLeads
)
902 // ---------------------------------------------------------------------------
903 // Misc. Parsing Methods
904 // ---------------------------------------------------------------------------
906 bool wxURI::ParseIPv4address(const wxChar
*& uri
)
908 //IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
910 //dec-octet = DIGIT ; 0-9
911 // / %x31-39 DIGIT ; 10-99
912 // / "1" 2DIGIT ; 100-199
913 // / "2" %x30-34 DIGIT ; 200-249
914 // / "25" %x30-35 ; 250-255
921 //each ip part must be between 0-255 (dupe of version in for loop)
922 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
923 //100 or less (note !)
924 !( (*(uri
-2) < '2') ||
927 (*(uri
-1) < '5' || (*(uri
-1) == '5' && *uri
<= '5'))
935 if(IsDigit(*uri
))++uri
;
937 //compilers should unroll this loop
938 for(; iIPv4
< 4; ++iIPv4
)
940 if (*uri
!= '.' || !IsDigit(*++uri
))
943 //each ip part must be between 0-255
944 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
945 //100 or less (note !)
946 !( (*(uri
-2) < '2') ||
949 (*(uri
-1) < '5' || (*(uri
-1) == '5' && *uri
<= '5'))
956 if(IsDigit(*uri
))++uri
;
962 bool wxURI::ParseH16(const wxChar
*& uri
)
968 if(IsHex(*++uri
) && IsHex(*++uri
) && IsHex(*++uri
))
974 bool wxURI::ParseIPv6address(const wxChar
*& uri
)
976 // IPv6address = 6( h16 ":" ) ls32
977 // / "::" 5( h16 ":" ) ls32
978 // / [ h16 ] "::" 4( h16 ":" ) ls32
979 // / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
980 // / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
981 // / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
982 // / [ *4( h16 ":" ) h16 ] "::" ls32
983 // / [ *5( h16 ":" ) h16 ] "::" h16
984 // / [ *6( h16 ":" ) h16 ] "::"
986 size_t numPrefix
= 0,
989 bool bEndHex
= false;
991 for( ; numPrefix
< 6; ++numPrefix
)
1006 if(!bEndHex
&& !ParseH16(uri
))
1025 if (*uri
!= ':' || *(uri
+1) != ':')
1030 while (*--uri
!= ':') {}
1033 const wxChar
* uristart
= uri
;
1035 // ls32 = ( h16 ":" h16 ) / IPv4address
1036 if (ParseH16(uri
) && *uri
== ':' && ParseH16(uri
))
1041 if (ParseIPv4address(uri
))
1053 maxPostfix
= 4 - numPrefix
;
1057 bool bAllowAltEnding
= maxPostfix
== 0;
1059 for(; maxPostfix
!= 0; --maxPostfix
)
1061 if(!ParseH16(uri
) || *uri
!= ':')
1067 const wxChar
* uristart
= uri
;
1069 // ls32 = ( h16 ":" h16 ) / IPv4address
1070 if (ParseH16(uri
) && *uri
== ':' && ParseH16(uri
))
1075 if (ParseIPv4address(uri
))
1080 if (!bAllowAltEnding
)
1084 if(numPrefix
<= 5 && ParseH16(uri
))
1090 bool wxURI::ParseIPvFuture(const wxChar
*& uri
)
1092 // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1093 if (*++uri
!= 'v' || !IsHex(*++uri
))
1096 while (IsHex(*++uri
)) {}
1098 if (*uri
!= '.' || !(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== ':'))
1101 while(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== ':') {}
1107 // ---------------------------------------------------------------------------
1108 // Misc methods - IsXXX and CharToHex
1109 // ---------------------------------------------------------------------------
1111 int wxURI::CharToHex(const wxChar
& c
)
1113 if ((c
>= 'A') && (c
<= 'Z')) return c
- 'A' + 0x0A;
1114 if ((c
>= 'a') && (c
<= 'z')) return c
- 'a' + 0x0a;
1115 if ((c
>= '0') && (c
<= '9')) return c
- '0' + 0x00;
1120 //! unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1121 bool wxURI::IsUnreserved (const wxChar
& c
)
1122 { return IsAlpha(c
) || IsDigit(c
) ||
1130 bool wxURI::IsReserved (const wxChar
& c
)
1132 return IsGenDelim(c
) || IsSubDelim(c
);
1135 //! gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
1136 bool wxURI::IsGenDelim (const wxChar
& c
)
1147 //! sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1148 //! / "*" / "+" / "," / ";" / "="
1149 bool wxURI::IsSubDelim (const wxChar
& c
)
1165 bool wxURI::IsHex(const wxChar
& c
)
1166 { return IsDigit(c
) || (c
>= 'a' && c
<= 'f') || (c
>= 'A' && c
<= 'F'); }
1168 bool wxURI::IsAlpha(const wxChar
& c
)
1169 { return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'); }
1171 bool wxURI::IsDigit(const wxChar
& c
)
1172 { return c
>= '0' && c
<= '9'; }
1175 // ---------------------------------------------------------------------------
1177 // wxURL Compatability
1179 // TODO: Use wxURI instead here...
1180 // ---------------------------------------------------------------------------
1186 wxString
wxURL::ConvertToValidURI(const wxString
& uri
, const wxChar
* delims
)
1192 for (i
= 0; i
< uri
.Len(); i
++)
1194 wxChar c
= uri
.GetChar(i
);
1198 // GRG, Apr/2000: changed to "%20" instead of '+'
1200 out_str
+= wxT("%20");
1204 // GRG, Apr/2000: modified according to the URI definition (RFC 2396)
1206 // - Alphanumeric characters are never escaped
1207 // - Unreserved marks are never escaped
1208 // - Delimiters must be escaped if they appear within a component
1209 // but not if they are used to separate components. Here we have
1210 // no clear way to distinguish between these two cases, so they
1211 // are escaped unless they are passed in the 'delims' parameter
1212 // (allowed delimiters).
1214 static const wxChar marks
[] = wxT("-_.!~*()'");
1216 if ( !wxIsalnum(c
) && !wxStrchr(marks
, c
) && !wxStrchr(delims
, c
) )
1218 hexa_code
.Printf(wxT("%%%02X"), c
);
1219 out_str
+= hexa_code
;
1231 wxString
wxURL::ConvertFromURI(const wxString
& uri
)
1236 while (i
< uri
.Len())
1239 if (uri
[i
] == wxT('%'))
1242 if (uri
[i
] >= wxT('A') && uri
[i
] <= wxT('F'))
1243 code
= (uri
[i
] - wxT('A') + 10) * 16;
1244 else if (uri
[i
] >= wxT('a') && uri
[i
] <= wxT('f'))
1245 code
= (uri
[i
] - wxT('a') + 10) * 16;
1247 code
= (uri
[i
] - wxT('0')) * 16;
1250 if (uri
[i
] >= wxT('A') && uri
[i
] <= wxT('F'))
1251 code
+= (uri
[i
] - wxT('A')) + 10;
1252 else if (uri
[i
] >= wxT('a') && uri
[i
] <= wxT('f'))
1253 code
+= (uri
[i
] - wxT('a')) + 10;
1255 code
+= (uri
[i
] - wxT('0'));
1258 new_uri
+= (wxChar
)code
;