]>
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 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 // ---------------------------------------------------------------------------
30 // ---------------------------------------------------------------------------
32 IMPLEMENT_CLASS(wxURI
, wxObject
)
34 // ===========================================================================
36 // ===========================================================================
38 // ---------------------------------------------------------------------------
40 // ---------------------------------------------------------------------------
42 // ---------------------------------------------------------------------------
46 // ---------------------------------------------------------------------------
48 // ---------------------------------------------------------------------------
50 // ---------------------------------------------------------------------------
52 wxURI::wxURI() : m_hostType(wxURI_REGNAME
), m_fields(0)
56 wxURI::wxURI(const wxString
& uri
) : m_hostType(wxURI_REGNAME
), m_fields(0)
61 wxURI::wxURI(const wxURI
& uri
) : wxObject(), m_hostType(wxURI_REGNAME
), m_fields(0)
66 // ---------------------------------------------------------------------------
67 // Destructor and cleanup
68 // ---------------------------------------------------------------------------
77 m_scheme
= m_userinfo
= m_server
= m_port
= m_path
=
78 m_query
= m_fragment
= wxEmptyString
;
80 m_hostType
= wxURI_REGNAME
;
85 // ---------------------------------------------------------------------------
88 // This creates the URI - all we do here is call the main parsing method
89 // ---------------------------------------------------------------------------
91 const wxChar
* wxURI::Create(const wxString
& uri
)
99 // ---------------------------------------------------------------------------
102 // TranslateEscape unencodes a 3 character URL escape sequence
104 // Escape encodes an invalid URI character into a 3 character sequence
106 // IsEscape determines if the input string contains an escape sequence,
107 // if it does, then it moves the input string past the escape sequence
109 // Unescape unencodes all 3 character URL escape sequences in a wxString
110 // ---------------------------------------------------------------------------
112 wxUniChar
wxURI::TranslateEscape(const wxString::const_iterator
& s
)
117 wxASSERT_MSG( IsHex(c1
) && IsHex(c2
), wxT("Invalid escape sequence!"));
119 return wx_truncate_cast(wxChar
, (CharToHex(c1
) << 4 ) | CharToHex(c2
));
122 wxString
wxURI::Unescape(const wxString
& uri
)
126 for (wxString::const_iterator i
= uri
.begin(); i
!= uri
.end(); ++i
)
128 if ( *i
== wxT('%') )
130 new_uri
+= wxURI::TranslateEscape(i
+ 1);
140 void wxURI::Escape(wxString
& s
, const wxChar
& c
)
142 const wxChar
* hdig
= wxT("0123456789abcdef");
144 s
+= hdig
[(c
>> 4) & 15];
148 bool wxURI::IsEscape(const wxChar
*& uri
)
150 // pct-encoded = "%" HEXDIG HEXDIG
151 if(*uri
== wxT('%') && IsHex(*(uri
+1)) && IsHex(*(uri
+2)))
157 // ---------------------------------------------------------------------------
161 // Gets the username and password via the old URL method.
162 // ---------------------------------------------------------------------------
163 wxString
wxURI::GetUser() const
165 size_t dwPasswordPos
= m_userinfo
.find(':');
167 if (dwPasswordPos
== wxString::npos
)
170 return m_userinfo(0, dwPasswordPos
);
173 wxString
wxURI::GetPassword() const
175 size_t dwPasswordPos
= m_userinfo
.find(':');
177 if (dwPasswordPos
== wxString::npos
)
180 return m_userinfo(dwPasswordPos
+1, m_userinfo
.length() + 1);
183 // ---------------------------------------------------------------------------
186 // BuildURI() builds the entire URI into a useable
187 // representation, including proper identification characters such as slashes
189 // BuildUnescapedURI() does the same thing as BuildURI(), only it unescapes
190 // the components that accept escape sequences
191 // ---------------------------------------------------------------------------
193 wxString
wxURI::BuildURI() const
198 ret
= ret
+ m_scheme
+ wxT(":");
205 ret
= ret
+ m_userinfo
+ wxT("@");
210 ret
= ret
+ wxT(":") + m_port
;
216 ret
= ret
+ wxT("?") + m_query
;
219 ret
= ret
+ wxT("#") + m_fragment
;
224 wxString
wxURI::BuildUnescapedURI() const
229 ret
= ret
+ m_scheme
+ wxT(":");
236 ret
= ret
+ wxURI::Unescape(m_userinfo
) + wxT("@");
238 if (m_hostType
== wxURI_REGNAME
)
239 ret
+= wxURI::Unescape(m_server
);
244 ret
= ret
+ wxT(":") + m_port
;
247 ret
+= wxURI::Unescape(m_path
);
250 ret
= ret
+ wxT("?") + wxURI::Unescape(m_query
);
253 ret
= ret
+ wxT("#") + wxURI::Unescape(m_fragment
);
258 // ---------------------------------------------------------------------------
260 // ---------------------------------------------------------------------------
262 wxURI
& wxURI::Assign(const wxURI
& uri
)
265 m_fields
= uri
.m_fields
;
267 //ref over components
268 m_scheme
= uri
.m_scheme
;
269 m_userinfo
= uri
.m_userinfo
;
270 m_server
= uri
.m_server
;
271 m_hostType
= uri
.m_hostType
;
274 m_query
= uri
.m_query
;
275 m_fragment
= uri
.m_fragment
;
280 wxURI
& wxURI::operator = (const wxURI
& uri
)
285 wxURI
& wxURI::operator = (const wxString
& string
)
291 // ---------------------------------------------------------------------------
293 // ---------------------------------------------------------------------------
295 bool wxURI::operator == (const wxURI
& uri
) const
299 if(m_scheme
!= uri
.m_scheme
)
302 else if (uri
.HasScheme())
310 if (m_userinfo
!= uri
.m_userinfo
)
313 else if (uri
.HasUserInfo())
316 if (m_server
!= uri
.m_server
||
317 m_hostType
!= uri
.m_hostType
)
322 if(m_port
!= uri
.m_port
)
325 else if (uri
.HasPort())
328 else if (uri
.HasServer())
334 if(m_path
!= uri
.m_path
)
337 else if (uri
.HasPath())
342 if (m_query
!= uri
.m_query
)
345 else if (uri
.HasQuery())
350 if (m_fragment
!= uri
.m_fragment
)
353 else if (uri
.HasFragment())
359 // ---------------------------------------------------------------------------
362 // if there is no authority or scheme, it is a reference
363 // ---------------------------------------------------------------------------
365 bool wxURI::IsReference() const
366 { return !HasScheme() || !HasServer(); }
368 // ---------------------------------------------------------------------------
371 // Master URI parsing method. Just calls the individual parsing methods
373 // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
374 // URI-reference = URI / relative
375 // ---------------------------------------------------------------------------
377 const wxChar
* wxURI::Parse(const wxChar
* uri
)
379 uri
= ParseScheme(uri
);
380 uri
= ParseAuthority(uri
);
381 uri
= ParsePath(uri
);
382 uri
= ParseQuery(uri
);
383 return ParseFragment(uri
);
386 // ---------------------------------------------------------------------------
389 // Individual parsers for each URI component
390 // ---------------------------------------------------------------------------
392 const wxChar
* wxURI::ParseScheme(const wxChar
* uri
)
394 wxASSERT(uri
!= NULL
);
396 //copy of the uri - used for figuring out
397 //length of each component
398 const wxChar
* uricopy
= uri
;
400 //Does the uri have a scheme (first character alpha)?
405 //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
406 while (IsAlpha(*uri
) || IsDigit(*uri
) ||
415 if (*uri
== wxT(':'))
417 //mark the scheme as valid
418 m_fields
|= wxURI_SCHEME
;
420 //move reference point up to input buffer
424 //relative uri with relative path reference
425 m_scheme
= wxEmptyString
;
428 //relative uri with _possible_ relative path reference
433 const wxChar
* wxURI::ParseAuthority(const wxChar
* uri
)
435 // authority = [ userinfo "@" ] host [ ":" port ]
436 if (*uri
== wxT('/') && *(uri
+1) == wxT('/'))
438 //skip past the two slashes
441 // ############# DEVIATION FROM RFC #########################
442 // Don't parse the server component for file URIs
443 if(m_scheme
!= wxT("file"))
446 uri
= ParseUserInfo(uri
);
447 uri
= ParseServer(uri
);
448 return ParsePort(uri
);
455 const wxChar
* wxURI::ParseUserInfo(const wxChar
* uri
)
457 wxASSERT(uri
!= NULL
);
459 //copy of the uri - used for figuring out
460 //length of each component
461 const wxChar
* uricopy
= uri
;
463 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
464 while(*uri
&& *uri
!= wxT('@') && *uri
!= wxT('/') && *uri
!= wxT('#') && *uri
!= wxT('?'))
466 if(IsUnreserved(*uri
) ||
467 IsSubDelim(*uri
) || *uri
== wxT(':'))
468 m_userinfo
+= *uri
++;
469 else if (IsEscape(uri
))
471 m_userinfo
+= *uri
++;
472 m_userinfo
+= *uri
++;
473 m_userinfo
+= *uri
++;
476 Escape(m_userinfo
, *uri
++);
482 m_fields
|= wxURI_USERINFO
;
487 m_userinfo
= wxEmptyString
;
492 const wxChar
* wxURI::ParseServer(const wxChar
* uri
)
494 wxASSERT(uri
!= NULL
);
496 //copy of the uri - used for figuring out
497 //length of each component
498 const wxChar
* uricopy
= uri
;
500 // host = IP-literal / IPv4address / reg-name
501 // IP-literal = "[" ( IPv6address / IPvFuture ) "]"
502 if (*uri
== wxT('['))
504 ++uri
; //some compilers don't support *&ing a ++*
505 if (ParseIPv6address(uri
) && *uri
== wxT(']'))
508 m_hostType
= wxURI_IPV6ADDRESS
;
510 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
511 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
512 theBuffer
.SetLength(uri
-uricopy
);
518 ++uri
; //some compilers don't support *&ing a ++*
519 if (ParseIPvFuture(uri
) && *uri
== wxT(']'))
522 m_hostType
= wxURI_IPVFUTURE
;
524 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
525 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
526 theBuffer
.SetLength(uri
-uricopy
);
534 if (ParseIPv4address(uri
))
536 m_hostType
= wxURI_IPV4ADDRESS
;
538 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
539 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
540 theBuffer
.SetLength(uri
-uricopy
);
546 if(m_hostType
== wxURI_REGNAME
)
549 // reg-name = *( unreserved / pct-encoded / sub-delims )
550 while(*uri
&& *uri
!= wxT('/') && *uri
!= wxT(':') && *uri
!= wxT('#') && *uri
!= wxT('?'))
552 if(IsUnreserved(*uri
) || IsSubDelim(*uri
))
554 else if (IsEscape(uri
))
561 Escape(m_server
, *uri
++);
565 //mark the server as valid
566 m_fields
|= wxURI_SERVER
;
572 const wxChar
* wxURI::ParsePort(const wxChar
* uri
)
574 wxASSERT(uri
!= NULL
);
585 //mark the port as valid
586 m_fields
|= wxURI_PORT
;
592 const wxChar
* wxURI::ParsePath(const wxChar
* uri
, bool bReference
, bool bNormalize
)
594 wxASSERT(uri
!= NULL
);
596 //copy of the uri - used for figuring out
597 //length of each component
598 const wxChar
* uricopy
= uri
;
600 /// hier-part = "//" authority path-abempty
605 /// relative-part = "//" authority path-abempty
610 /// path-abempty = *( "/" segment )
611 /// path-absolute = "/" [ segment-nz *( "/" segment ) ]
612 /// path-noscheme = segment-nz-nc *( "/" segment )
613 /// path-rootless = segment-nz *( "/" segment )
614 /// path-empty = 0<pchar>
617 /// segment-nz = 1*pchar
618 /// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
619 /// ; non-zero-length segment without any colon ":"
621 /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
622 if (*uri
== wxT('/'))
626 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
628 if( IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
629 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/'))
631 else if (IsEscape(uri
))
638 Escape(m_path
, *uri
++);
643 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
645 wxTmemcpy(theBuffer
, m_path
.c_str(), m_path
.length()+1);
647 Normalize(theBuffer
, true);
648 theBuffer
.SetLength(wxStrlen(theBuffer
));
650 //mark the path as valid
651 m_fields
|= wxURI_PATH
;
653 else if(*uri
) //Relative path
658 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
660 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
661 *uri
== wxT('@') || *uri
== wxT('/'))
663 else if (IsEscape(uri
))
670 Escape(m_path
, *uri
++);
675 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
677 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
678 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/'))
680 else if (IsEscape(uri
))
687 Escape(m_path
, *uri
++);
695 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
697 wxTmemcpy(theBuffer
, m_path
.c_str(), m_path
.length()+1);
699 Normalize(theBuffer
);
700 theBuffer
.SetLength(wxStrlen(theBuffer
));
703 //mark the path as valid
704 m_fields
|= wxURI_PATH
;
712 const wxChar
* wxURI::ParseQuery(const wxChar
* uri
)
714 wxASSERT(uri
!= NULL
);
716 // query = *( pchar / "/" / "?" )
717 if (*uri
== wxT('?'))
720 while(*uri
&& *uri
!= wxT('#'))
722 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
723 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/') || *uri
== wxT('?'))
725 else if (IsEscape(uri
))
732 Escape(m_query
, *uri
++);
735 //mark the server as valid
736 m_fields
|= wxURI_QUERY
;
743 const wxChar
* wxURI::ParseFragment(const wxChar
* uri
)
745 wxASSERT(uri
!= NULL
);
747 // fragment = *( pchar / "/" / "?" )
748 if (*uri
== wxT('#'))
753 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
754 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/') || *uri
== wxT('?'))
755 m_fragment
+= *uri
++;
756 else if (IsEscape(uri
))
758 m_fragment
+= *uri
++;
759 m_fragment
+= *uri
++;
760 m_fragment
+= *uri
++;
763 Escape(m_fragment
, *uri
++);
766 //mark the server as valid
767 m_fields
|= wxURI_FRAGMENT
;
773 // ---------------------------------------------------------------------------
776 // Builds missing components of this uri from a base uri
778 // A version of the algorithm outlined in the RFC is used here
779 // (it is shown in comments)
781 // Note that an empty URI inherits all components
782 // ---------------------------------------------------------------------------
784 void wxURI::Resolve(const wxURI
& base
, int flags
)
786 wxASSERT_MSG(!base
.IsReference(),
787 wxT("wxURI to inherit from must not be a reference!"));
789 // If we arn't being strict, enable the older (pre-RFC2396)
790 // loophole that allows this uri to inherit other
791 // properties from the base uri - even if the scheme
793 if ( !(flags
& wxURI_STRICT
) &&
794 HasScheme() && base
.HasScheme() &&
795 m_scheme
== base
.m_scheme
)
797 m_fields
-= wxURI_SCHEME
;
801 // Do nothing if this is an absolute wxURI
802 // if defined(R.scheme) then
803 // T.scheme = R.scheme;
804 // T.authority = R.authority;
805 // T.path = remove_dot_segments(R.path);
806 // T.query = R.query;
812 //No scheme - inherit
813 m_scheme
= base
.m_scheme
;
814 m_fields
|= wxURI_SCHEME
;
816 // All we need to do for relative URIs with an
817 // authority component is just inherit the scheme
818 // if defined(R.authority) then
819 // T.authority = R.authority;
820 // T.path = remove_dot_segments(R.path);
821 // T.query = R.query;
827 //No authority - inherit
828 if (base
.HasUserInfo())
830 m_userinfo
= base
.m_userinfo
;
831 m_fields
|= wxURI_USERINFO
;
834 m_server
= base
.m_server
;
835 m_hostType
= base
.m_hostType
;
836 m_fields
|= wxURI_SERVER
;
840 m_port
= base
.m_port
;
841 m_fields
|= wxURI_PORT
;
845 // Simple path inheritance from base
848 // T.path = Base.path;
849 m_path
= base
.m_path
;
850 m_fields
|= wxURI_PATH
;
853 // if defined(R.query) then
854 // T.query = R.query;
856 // T.query = Base.query;
860 m_query
= base
.m_query
;
861 m_fields
|= wxURI_QUERY
;
866 // if (R.path starts-with "/") then
867 // T.path = remove_dot_segments(R.path);
869 // T.path = merge(Base.path, R.path);
870 // T.path = remove_dot_segments(T.path);
872 // T.query = R.query;
873 if (m_path
[0u] != wxT('/'))
876 wxString::const_iterator op
= m_path
.begin();
877 wxString::const_iterator bp
= base
.m_path
.begin() + base
.m_path
.length();
879 //not a ending directory? move up
880 if (base
.m_path
[0] && *(bp
-1) != wxT('/'))
881 UpTree(base
.m_path
.begin(), bp
);
883 //normalize directories
884 while(*op
== wxT('.') && *(op
+1) == wxT('.') &&
885 (*(op
+2) == '\0' || *(op
+2) == wxT('/')) )
887 UpTree(base
.m_path
.begin(), bp
);
895 m_path
= base
.m_path
.substr(0, bp
- base
.m_path
.begin()) +
896 m_path
.substr((op
- m_path
.begin()), m_path
.length());
900 //T.fragment = R.fragment;
903 // ---------------------------------------------------------------------------
906 // Moves a URI path up a directory
907 // ---------------------------------------------------------------------------
910 void wxURI::UpTree(wxString::const_iterator uristart
,
911 wxString::const_iterator
& uri
)
913 if (uri
!= uristart
&& *(uri
-1) == wxT('/'))
918 for(;uri
!= uristart
; --uri
)
920 if (*uri
== wxT('/'))
928 if (uri
== uristart
&& *uri
== wxT('/'))
933 // FIXME-UTF8: fix Normalize() to use iterators instead of having this method!
934 /*static*/ void wxURI::UpTree(const wxChar
* uristart
, const wxChar
*& uri
)
936 if (uri
!= uristart
&& *(uri
-1) == wxT('/'))
941 for(;uri
!= uristart
; --uri
)
943 if (*uri
== wxT('/'))
951 if (uri
== uristart
&& *uri
== wxT('/'))
957 // ---------------------------------------------------------------------------
960 // Normalizes directories in-place
962 // I.E. ./ and . are ignored
964 // ../ and .. are removed if a directory is before it, along
965 // with that directory (leading .. and ../ are kept)
966 // ---------------------------------------------------------------------------
969 void wxURI::Normalize(wxChar
* s
, bool bIgnoreLeads
)
979 if (*cp
== wxT('.') && (*(cp
+1) == wxT('/') || *(cp
+1) == '\0')
980 && (bp
== cp
|| *(cp
-1) == wxT('/')))
988 else if (*cp
== wxT('.') && *(cp
+1) == wxT('.') &&
989 (*(cp
+2) == wxT('/') || *(cp
+2) == '\0')
990 && (bp
== cp
|| *(cp
-1) == wxT('/')))
992 //.. _or_ ../ - go up the tree
995 UpTree((const wxChar
*)bp
, (const wxChar
*&)s
);
1002 else if (!bIgnoreLeads
)
1014 if (*(cp
+2) == '\0')
1027 // ---------------------------------------------------------------------------
1030 // Parses 1 to 4 hex values. Returns true if the first character of the input
1031 // string is a valid hex character. It is the caller's responsability to move
1032 // the input string back to its original position on failure.
1033 // ---------------------------------------------------------------------------
1035 bool wxURI::ParseH16(const wxChar
*& uri
)
1041 if(IsHex(*++uri
) && IsHex(*++uri
) && IsHex(*++uri
))
1047 // ---------------------------------------------------------------------------
1050 // Parses a certain version of an IP address and moves the input string past
1051 // it. Returns true if the input string contains the proper version of an ip
1052 // address. It is the caller's responsability to move the input string back
1053 // to its original position on failure.
1054 // ---------------------------------------------------------------------------
1056 bool wxURI::ParseIPv4address(const wxChar
*& uri
)
1058 //IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1060 //dec-octet = DIGIT ; 0-9
1061 // / %x31-39 DIGIT ; 10-99
1062 // / "1" 2DIGIT ; 100-199
1063 // / "2" %x30-34 DIGIT ; 200-249
1064 // / "25" %x30-35 ; 250-255
1071 //each ip part must be between 0-255 (dupe of version in for loop)
1072 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
1073 //100 or less (note !)
1074 !( (*(uri
-2) < wxT('2')) ||
1076 (*(uri
-2) == wxT('2') &&
1077 (*(uri
-1) < wxT('5') || (*(uri
-1) == wxT('5') && *uri
<= wxT('5')))
1085 if(IsDigit(*uri
))++uri
;
1087 //compilers should unroll this loop
1088 for(; iIPv4
< 4; ++iIPv4
)
1090 if (*uri
!= wxT('.') || !IsDigit(*++uri
))
1093 //each ip part must be between 0-255
1094 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
1095 //100 or less (note !)
1096 !( (*(uri
-2) < wxT('2')) ||
1098 (*(uri
-2) == wxT('2') &&
1099 (*(uri
-1) < wxT('5') || (*(uri
-1) == wxT('5') && *uri
<= wxT('5')))
1106 if(IsDigit(*uri
))++uri
;
1112 bool wxURI::ParseIPv6address(const wxChar
*& uri
)
1114 // IPv6address = 6( h16 ":" ) ls32
1115 // / "::" 5( h16 ":" ) ls32
1116 // / [ h16 ] "::" 4( h16 ":" ) ls32
1117 // / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1118 // / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1119 // / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1120 // / [ *4( h16 ":" ) h16 ] "::" ls32
1121 // / [ *5( h16 ":" ) h16 ] "::" h16
1122 // / [ *6( h16 ":" ) h16 ] "::"
1124 size_t numPrefix
= 0,
1127 bool bEndHex
= false;
1129 for( ; numPrefix
< 6; ++numPrefix
)
1138 if(*uri
!= wxT(':'))
1144 if(!bEndHex
&& !ParseH16(uri
))
1151 if (*uri
== wxT(':'))
1153 if (*++uri
!= wxT(':'))
1163 if (*uri
!= wxT(':') || *(uri
+1) != wxT(':'))
1168 while (*--uri
!= wxT(':')) {}
1171 const wxChar
* uristart
= uri
;
1173 // ls32 = ( h16 ":" h16 ) / IPv4address
1174 if (ParseH16(uri
) && *uri
== wxT(':') && ParseH16(uri
))
1179 if (ParseIPv4address(uri
))
1191 maxPostfix
= 4 - numPrefix
;
1195 bool bAllowAltEnding
= maxPostfix
== 0;
1197 for(; maxPostfix
!= 0; --maxPostfix
)
1199 if(!ParseH16(uri
) || *uri
!= wxT(':'))
1205 const wxChar
* uristart
= uri
;
1207 // ls32 = ( h16 ":" h16 ) / IPv4address
1208 if (ParseH16(uri
) && *uri
== wxT(':') && ParseH16(uri
))
1213 if (ParseIPv4address(uri
))
1218 if (!bAllowAltEnding
)
1222 if(numPrefix
<= 5 && ParseH16(uri
))
1228 bool wxURI::ParseIPvFuture(const wxChar
*& uri
)
1230 // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1231 if (*++uri
!= wxT('v') || !IsHex(*++uri
))
1234 while (IsHex(*++uri
)) {}
1236 if (*uri
!= wxT('.') || !(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== wxT(':')))
1239 while(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== wxT(':')) {}
1245 // ---------------------------------------------------------------------------
1248 // Converts a character into a numeric hexidecimal value, or 0 if the
1249 // passed in character is not a valid hex character
1250 // ---------------------------------------------------------------------------
1253 wxChar
wxURI::CharToHex(const wxChar
& c
)
1255 if ((c
>= wxT('A')) && (c
<= wxT('Z'))) return wxChar(c
- wxT('A') + 0x0A);
1256 if ((c
>= wxT('a')) && (c
<= wxT('z'))) return wxChar(c
- wxT('a') + 0x0a);
1257 if ((c
>= wxT('0')) && (c
<= wxT('9'))) return wxChar(c
- wxT('0') + 0x00);
1262 // ---------------------------------------------------------------------------
1265 // Returns true if the passed in character meets the criteria of the method
1266 // ---------------------------------------------------------------------------
1268 //! unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1269 bool wxURI::IsUnreserved (const wxChar
& c
)
1270 { return IsAlpha(c
) || IsDigit(c
) ||
1274 c
== wxT('~') //tilde
1278 bool wxURI::IsReserved (const wxChar
& c
)
1280 return IsGenDelim(c
) || IsSubDelim(c
);
1283 //! gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
1284 bool wxURI::IsGenDelim (const wxChar
& c
)
1286 return c
== wxT(':') ||
1295 //! sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1296 //! / "*" / "+" / "," / ";" / "="
1297 bool wxURI::IsSubDelim (const wxChar
& c
)
1299 return c
== wxT('!') ||
1313 bool wxURI::IsHex(const wxChar
& c
)
1314 { return IsDigit(c
) || (c
>= wxT('a') && c
<= wxT('f')) || (c
>= wxT('A') && c
<= wxT('F')); }
1316 bool wxURI::IsAlpha(const wxChar
& c
)
1317 { return (c
>= wxT('a') && c
<= wxT('z')) || (c
>= wxT('A') && c
<= wxT('Z')); }
1319 bool wxURI::IsDigit(const wxChar
& c
)
1320 { return c
>= wxT('0') && c
<= wxT('9'); }