]>
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"
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
) : wxObject(), m_hostType(wxURI_REGNAME
), m_fields(0)
70 // ---------------------------------------------------------------------------
71 // Destructor and cleanup
72 // ---------------------------------------------------------------------------
81 m_scheme
= m_userinfo
= m_server
= m_port
= m_path
=
82 m_query
= m_fragment
= wxEmptyString
;
84 m_hostType
= wxURI_REGNAME
;
89 // ---------------------------------------------------------------------------
92 // This creates the URI - all we do here is call the main parsing method
93 // ---------------------------------------------------------------------------
95 const wxChar
* wxURI::Create(const wxString
& uri
)
100 // FIXME-UTF8: rewrite ParseXXX() methods using iterators
101 // NB: using wxWxCharBuffer instead of just c_str() avoids keeping
102 // converted string in memory for longer than needed
103 return Parse(wxWxCharBuffer(uri
.c_str()));
106 // ---------------------------------------------------------------------------
109 // TranslateEscape unencodes a 3 character URL escape sequence
111 // Escape encodes an invalid URI character into a 3 character sequence
113 // IsEscape determines if the input string contains an escape sequence,
114 // if it does, then it moves the input string past the escape sequence
116 // Unescape unencodes all 3 character URL escape sequences in a wxString
117 // ---------------------------------------------------------------------------
119 wxUniChar
wxURI::TranslateEscape(const wxString::const_iterator
& s
)
124 wxASSERT_MSG( IsHex(c1
) && IsHex(c2
), wxT("Invalid escape sequence!"));
126 return wx_truncate_cast(wxChar
, (CharToHex(c1
) << 4 ) | CharToHex(c2
));
129 wxString
wxURI::Unescape(const wxString
& uri
)
133 for (wxString::const_iterator i
= uri
.begin(); i
!= uri
.end(); ++i
)
135 if ( *i
== wxT('%') )
137 new_uri
+= wxURI::TranslateEscape(i
+ 1);
147 void wxURI::Escape(wxString
& s
, const wxChar
& c
)
149 const wxChar
* hdig
= wxT("0123456789abcdef");
151 s
+= hdig
[(c
>> 4) & 15];
155 bool wxURI::IsEscape(const wxChar
*& uri
)
157 // pct-encoded = "%" HEXDIG HEXDIG
158 if(*uri
== wxT('%') && IsHex(*(uri
+1)) && IsHex(*(uri
+2)))
164 // ---------------------------------------------------------------------------
168 // Gets the username and password via the old URL method.
169 // ---------------------------------------------------------------------------
170 wxString
wxURI::GetUser() const
172 size_t dwPasswordPos
= m_userinfo
.find(':');
174 if (dwPasswordPos
== wxString::npos
)
177 return m_userinfo(0, dwPasswordPos
);
180 wxString
wxURI::GetPassword() const
182 size_t dwPasswordPos
= m_userinfo
.find(':');
184 if (dwPasswordPos
== wxString::npos
)
187 return m_userinfo(dwPasswordPos
+1, m_userinfo
.length() + 1);
190 // ---------------------------------------------------------------------------
193 // BuildURI() builds the entire URI into a useable
194 // representation, including proper identification characters such as slashes
196 // BuildUnescapedURI() does the same thing as BuildURI(), only it unescapes
197 // the components that accept escape sequences
198 // ---------------------------------------------------------------------------
200 wxString
wxURI::BuildURI() const
205 ret
= ret
+ m_scheme
+ wxT(":");
212 ret
= ret
+ m_userinfo
+ wxT("@");
217 ret
= ret
+ wxT(":") + m_port
;
223 ret
= ret
+ wxT("?") + m_query
;
226 ret
= ret
+ wxT("#") + m_fragment
;
231 wxString
wxURI::BuildUnescapedURI() const
236 ret
= ret
+ m_scheme
+ wxT(":");
243 ret
= ret
+ wxURI::Unescape(m_userinfo
) + wxT("@");
245 if (m_hostType
== wxURI_REGNAME
)
246 ret
+= wxURI::Unescape(m_server
);
251 ret
= ret
+ wxT(":") + m_port
;
254 ret
+= wxURI::Unescape(m_path
);
257 ret
= ret
+ wxT("?") + wxURI::Unescape(m_query
);
260 ret
= ret
+ wxT("#") + wxURI::Unescape(m_fragment
);
265 // ---------------------------------------------------------------------------
267 // ---------------------------------------------------------------------------
269 wxURI
& wxURI::Assign(const wxURI
& uri
)
272 m_fields
= uri
.m_fields
;
274 //ref over components
275 m_scheme
= uri
.m_scheme
;
276 m_userinfo
= uri
.m_userinfo
;
277 m_server
= uri
.m_server
;
278 m_hostType
= uri
.m_hostType
;
281 m_query
= uri
.m_query
;
282 m_fragment
= uri
.m_fragment
;
287 wxURI
& wxURI::operator = (const wxURI
& uri
)
292 wxURI
& wxURI::operator = (const wxString
& string
)
298 // ---------------------------------------------------------------------------
300 // ---------------------------------------------------------------------------
302 bool wxURI::operator == (const wxURI
& uri
) const
306 if(m_scheme
!= uri
.m_scheme
)
309 else if (uri
.HasScheme())
317 if (m_userinfo
!= uri
.m_userinfo
)
320 else if (uri
.HasUserInfo())
323 if (m_server
!= uri
.m_server
||
324 m_hostType
!= uri
.m_hostType
)
329 if(m_port
!= uri
.m_port
)
332 else if (uri
.HasPort())
335 else if (uri
.HasServer())
341 if(m_path
!= uri
.m_path
)
344 else if (uri
.HasPath())
349 if (m_query
!= uri
.m_query
)
352 else if (uri
.HasQuery())
357 if (m_fragment
!= uri
.m_fragment
)
360 else if (uri
.HasFragment())
366 // ---------------------------------------------------------------------------
369 // if there is no authority or scheme, it is a reference
370 // ---------------------------------------------------------------------------
372 bool wxURI::IsReference() const
373 { return !HasScheme() || !HasServer(); }
375 // ---------------------------------------------------------------------------
378 // Master URI parsing method. Just calls the individual parsing methods
380 // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
381 // URI-reference = URI / relative
382 // ---------------------------------------------------------------------------
384 const wxChar
* wxURI::Parse(const wxChar
*uri
)
386 uri
= ParseScheme(uri
);
387 uri
= ParseAuthority(uri
);
388 uri
= ParsePath(uri
);
389 uri
= ParseQuery(uri
);
390 return ParseFragment(uri
);
393 // ---------------------------------------------------------------------------
396 // Individual parsers for each URI component
397 // ---------------------------------------------------------------------------
399 const wxChar
* wxURI::ParseScheme(const wxChar
*uri
)
401 wxASSERT(uri
!= NULL
);
403 //copy of the uri - used for figuring out
404 //length of each component
405 const wxChar
* uricopy
= uri
;
407 //Does the uri have a scheme (first character alpha)?
412 //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
413 while (IsAlpha(*uri
) || IsDigit(*uri
) ||
422 if (*uri
== wxT(':'))
424 //mark the scheme as valid
425 m_fields
|= wxURI_SCHEME
;
427 //move reference point up to input buffer
431 //relative uri with relative path reference
432 m_scheme
= wxEmptyString
;
435 //relative uri with _possible_ relative path reference
440 const wxChar
* wxURI::ParseAuthority(const wxChar
* uri
)
442 // authority = [ userinfo "@" ] host [ ":" port ]
443 if (*uri
== wxT('/') && *(uri
+1) == wxT('/'))
445 //skip past the two slashes
448 // ############# DEVIATION FROM RFC #########################
449 // Don't parse the server component for file URIs
450 if(m_scheme
!= wxT("file"))
453 uri
= ParseUserInfo(uri
);
454 uri
= ParseServer(uri
);
455 return ParsePort(uri
);
462 const wxChar
* wxURI::ParseUserInfo(const wxChar
* uri
)
464 wxASSERT(uri
!= NULL
);
466 //copy of the uri - used for figuring out
467 //length of each component
468 const wxChar
* uricopy
= uri
;
470 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
471 while(*uri
&& *uri
!= wxT('@') && *uri
!= wxT('/') && *uri
!= wxT('#') && *uri
!= wxT('?'))
473 if(IsUnreserved(*uri
) ||
474 IsSubDelim(*uri
) || *uri
== wxT(':'))
475 m_userinfo
+= *uri
++;
476 else if (IsEscape(uri
))
478 m_userinfo
+= *uri
++;
479 m_userinfo
+= *uri
++;
480 m_userinfo
+= *uri
++;
483 Escape(m_userinfo
, *uri
++);
489 m_fields
|= wxURI_USERINFO
;
494 m_userinfo
= wxEmptyString
;
499 const wxChar
* wxURI::ParseServer(const wxChar
* uri
)
501 wxASSERT(uri
!= NULL
);
503 //copy of the uri - used for figuring out
504 //length of each component
505 const wxChar
* uricopy
= uri
;
507 // host = IP-literal / IPv4address / reg-name
508 // IP-literal = "[" ( IPv6address / IPvFuture ) "]"
509 if (*uri
== wxT('['))
511 ++uri
; //some compilers don't support *&ing a ++*
512 if (ParseIPv6address(uri
) && *uri
== wxT(']'))
515 m_hostType
= wxURI_IPV6ADDRESS
;
517 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
518 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
519 theBuffer
.SetLength(uri
-uricopy
);
525 ++uri
; //some compilers don't support *&ing a ++*
526 if (ParseIPvFuture(uri
) && *uri
== wxT(']'))
529 m_hostType
= wxURI_IPVFUTURE
;
531 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
532 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
533 theBuffer
.SetLength(uri
-uricopy
);
541 if (ParseIPv4address(uri
))
543 m_hostType
= wxURI_IPV4ADDRESS
;
545 wxStringBufferLength
theBuffer(m_server
, uri
- uricopy
);
546 wxTmemcpy(theBuffer
, uricopy
, uri
-uricopy
);
547 theBuffer
.SetLength(uri
-uricopy
);
553 if(m_hostType
== wxURI_REGNAME
)
556 // reg-name = *( unreserved / pct-encoded / sub-delims )
557 while(*uri
&& *uri
!= wxT('/') && *uri
!= wxT(':') && *uri
!= wxT('#') && *uri
!= wxT('?'))
559 if(IsUnreserved(*uri
) || IsSubDelim(*uri
))
561 else if (IsEscape(uri
))
568 Escape(m_server
, *uri
++);
572 //mark the server as valid
573 m_fields
|= wxURI_SERVER
;
579 const wxChar
* wxURI::ParsePort(const wxChar
* uri
)
581 wxASSERT(uri
!= NULL
);
592 //mark the port as valid
593 m_fields
|= wxURI_PORT
;
599 const wxChar
* wxURI::ParsePath(const wxChar
* uri
, bool bReference
, bool bNormalize
)
601 wxASSERT(uri
!= NULL
);
603 //copy of the uri - used for figuring out
604 //length of each component
605 const wxChar
* uricopy
= uri
;
607 /// hier-part = "//" authority path-abempty
612 /// relative-part = "//" authority path-abempty
617 /// path-abempty = *( "/" segment )
618 /// path-absolute = "/" [ segment-nz *( "/" segment ) ]
619 /// path-noscheme = segment-nz-nc *( "/" segment )
620 /// path-rootless = segment-nz *( "/" segment )
621 /// path-empty = 0<pchar>
624 /// segment-nz = 1*pchar
625 /// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
626 /// ; non-zero-length segment without any colon ":"
628 /// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
629 if (*uri
== wxT('/'))
633 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
635 if( IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
636 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/'))
638 else if (IsEscape(uri
))
645 Escape(m_path
, *uri
++);
650 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
651 #if wxUSE_STL || wxUSE_UNICODE_UTF8
652 // FIXME-UTF8: have some wxReadWriteStringBuffer instead?
653 wxTmemcpy(theBuffer
, m_path
.c_str(), m_path
.length()+1);
655 Normalize(theBuffer
, true);
656 theBuffer
.SetLength(wxStrlen(theBuffer
));
658 //mark the path as valid
659 m_fields
|= wxURI_PATH
;
661 else if(*uri
) //Relative path
666 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
668 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
669 *uri
== wxT('@') || *uri
== wxT('/'))
671 else if (IsEscape(uri
))
678 Escape(m_path
, *uri
++);
683 while(*uri
&& *uri
!= wxT('#') && *uri
!= wxT('?'))
685 if(IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
686 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/'))
688 else if (IsEscape(uri
))
695 Escape(m_path
, *uri
++);
703 wxStringBufferLength
theBuffer(m_path
, m_path
.length() + 1);
704 #if wxUSE_STL || wxUSE_UNICODE_UTF8
705 // FIXME-UTF8: have some wxReadWriteStringBuffer instead?
706 wxTmemcpy(theBuffer
, m_path
.c_str(), m_path
.length()+1);
708 Normalize(theBuffer
);
709 theBuffer
.SetLength(wxStrlen(theBuffer
));
712 //mark the path as valid
713 m_fields
|= wxURI_PATH
;
721 const wxChar
* wxURI::ParseQuery(const wxChar
* uri
)
723 wxASSERT(uri
!= NULL
);
725 // query = *( pchar / "/" / "?" )
726 if (*uri
== wxT('?'))
729 while(*uri
&& *uri
!= wxT('#'))
731 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
732 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/') || *uri
== wxT('?'))
734 else if (IsEscape(uri
))
741 Escape(m_query
, *uri
++);
744 //mark the server as valid
745 m_fields
|= wxURI_QUERY
;
752 const wxChar
* wxURI::ParseFragment(const wxChar
* uri
)
754 wxASSERT(uri
!= NULL
);
756 // fragment = *( pchar / "/" / "?" )
757 if (*uri
== wxT('#'))
762 if (IsUnreserved(*uri
) || IsSubDelim(*uri
) ||
763 *uri
== wxT(':') || *uri
== wxT('@') || *uri
== wxT('/') || *uri
== wxT('?'))
764 m_fragment
+= *uri
++;
765 else if (IsEscape(uri
))
767 m_fragment
+= *uri
++;
768 m_fragment
+= *uri
++;
769 m_fragment
+= *uri
++;
772 Escape(m_fragment
, *uri
++);
775 //mark the server as valid
776 m_fields
|= wxURI_FRAGMENT
;
782 // ---------------------------------------------------------------------------
785 // Builds missing components of this uri from a base uri
787 // A version of the algorithm outlined in the RFC is used here
788 // (it is shown in comments)
790 // Note that an empty URI inherits all components
791 // ---------------------------------------------------------------------------
793 void wxURI::Resolve(const wxURI
& base
, int flags
)
795 wxASSERT_MSG(!base
.IsReference(),
796 wxT("wxURI to inherit from must not be a reference!"));
798 // If we arn't being strict, enable the older (pre-RFC2396)
799 // loophole that allows this uri to inherit other
800 // properties from the base uri - even if the scheme
802 if ( !(flags
& wxURI_STRICT
) &&
803 HasScheme() && base
.HasScheme() &&
804 m_scheme
== base
.m_scheme
)
806 m_fields
-= wxURI_SCHEME
;
810 // Do nothing if this is an absolute wxURI
811 // if defined(R.scheme) then
812 // T.scheme = R.scheme;
813 // T.authority = R.authority;
814 // T.path = remove_dot_segments(R.path);
815 // T.query = R.query;
821 //No scheme - inherit
822 m_scheme
= base
.m_scheme
;
823 m_fields
|= wxURI_SCHEME
;
825 // All we need to do for relative URIs with an
826 // authority component is just inherit the scheme
827 // if defined(R.authority) then
828 // T.authority = R.authority;
829 // T.path = remove_dot_segments(R.path);
830 // T.query = R.query;
836 //No authority - inherit
837 if (base
.HasUserInfo())
839 m_userinfo
= base
.m_userinfo
;
840 m_fields
|= wxURI_USERINFO
;
843 m_server
= base
.m_server
;
844 m_hostType
= base
.m_hostType
;
845 m_fields
|= wxURI_SERVER
;
849 m_port
= base
.m_port
;
850 m_fields
|= wxURI_PORT
;
854 // Simple path inheritance from base
857 // T.path = Base.path;
858 m_path
= base
.m_path
;
859 m_fields
|= wxURI_PATH
;
862 // if defined(R.query) then
863 // T.query = R.query;
865 // T.query = Base.query;
869 m_query
= base
.m_query
;
870 m_fields
|= wxURI_QUERY
;
875 // if (R.path starts-with "/") then
876 // T.path = remove_dot_segments(R.path);
878 // T.path = merge(Base.path, R.path);
879 // T.path = remove_dot_segments(T.path);
881 // T.query = R.query;
882 if (m_path
[0u] != wxT('/'))
885 wxString::const_iterator op
= m_path
.begin();
886 wxString::const_iterator bp
= base
.m_path
.begin() + base
.m_path
.length();
888 //not a ending directory? move up
889 if (base
.m_path
[0] && *(bp
-1) != wxT('/'))
890 UpTree(base
.m_path
.begin(), bp
);
892 //normalize directories
893 while(*op
== wxT('.') && *(op
+1) == wxT('.') &&
894 (*(op
+2) == '\0' || *(op
+2) == wxT('/')) )
896 UpTree(base
.m_path
.begin(), bp
);
904 m_path
= base
.m_path
.substr(0, bp
- base
.m_path
.begin()) +
905 m_path
.substr((op
- m_path
.begin()), m_path
.length());
909 //T.fragment = R.fragment;
912 // ---------------------------------------------------------------------------
915 // Moves a URI path up a directory
916 // ---------------------------------------------------------------------------
919 void wxURI::UpTree(wxString::const_iterator uristart
,
920 wxString::const_iterator
& uri
)
922 if (uri
!= uristart
&& *(uri
-1) == wxT('/'))
927 for(;uri
!= uristart
; --uri
)
929 if (*uri
== wxT('/'))
937 if (uri
== uristart
&& *uri
== wxT('/'))
942 // FIXME-UTF8: fix Normalize() to use iterators instead of having this method!
943 /*static*/ void wxURI::UpTree(const wxChar
* uristart
, const wxChar
*& uri
)
945 if (uri
!= uristart
&& *(uri
-1) == wxT('/'))
950 for(;uri
!= uristart
; --uri
)
952 if (*uri
== wxT('/'))
960 if (uri
== uristart
&& *uri
== wxT('/'))
966 // ---------------------------------------------------------------------------
969 // Normalizes directories in-place
971 // I.E. ./ and . are ignored
973 // ../ and .. are removed if a directory is before it, along
974 // with that directory (leading .. and ../ are kept)
975 // ---------------------------------------------------------------------------
978 void wxURI::Normalize(wxChar
* s
, bool bIgnoreLeads
)
988 if (*cp
== wxT('.') && (*(cp
+1) == wxT('/') || *(cp
+1) == '\0')
989 && (bp
== cp
|| *(cp
-1) == wxT('/')))
997 else if (*cp
== wxT('.') && *(cp
+1) == wxT('.') &&
998 (*(cp
+2) == wxT('/') || *(cp
+2) == '\0')
999 && (bp
== cp
|| *(cp
-1) == wxT('/')))
1001 //.. _or_ ../ - go up the tree
1004 UpTree((const wxChar
*)bp
, (const wxChar
*&)s
);
1006 if (*(cp
+2) == '\0')
1011 else if (!bIgnoreLeads
)
1023 if (*(cp
+2) == '\0')
1036 // ---------------------------------------------------------------------------
1039 // Parses 1 to 4 hex values. Returns true if the first character of the input
1040 // string is a valid hex character. It is the caller's responsability to move
1041 // the input string back to its original position on failure.
1042 // ---------------------------------------------------------------------------
1044 bool wxURI::ParseH16(const wxChar
*& uri
)
1050 if(IsHex(*++uri
) && IsHex(*++uri
) && IsHex(*++uri
))
1056 // ---------------------------------------------------------------------------
1059 // Parses a certain version of an IP address and moves the input string past
1060 // it. Returns true if the input string contains the proper version of an ip
1061 // address. It is the caller's responsability to move the input string back
1062 // to its original position on failure.
1063 // ---------------------------------------------------------------------------
1065 bool wxURI::ParseIPv4address(const wxChar
*& uri
)
1067 //IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1069 //dec-octet = DIGIT ; 0-9
1070 // / %x31-39 DIGIT ; 10-99
1071 // / "1" 2DIGIT ; 100-199
1072 // / "2" %x30-34 DIGIT ; 200-249
1073 // / "25" %x30-35 ; 250-255
1080 //each ip part must be between 0-255 (dupe of version in for loop)
1081 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
1082 //100 or less (note !)
1083 !( (*(uri
-2) < wxT('2')) ||
1085 (*(uri
-2) == wxT('2') &&
1086 (*(uri
-1) < wxT('5') || (*(uri
-1) == wxT('5') && *uri
<= wxT('5')))
1094 if(IsDigit(*uri
))++uri
;
1096 //compilers should unroll this loop
1097 for(; iIPv4
< 4; ++iIPv4
)
1099 if (*uri
!= wxT('.') || !IsDigit(*++uri
))
1102 //each ip part must be between 0-255
1103 if( IsDigit(*++uri
) && IsDigit(*++uri
) &&
1104 //100 or less (note !)
1105 !( (*(uri
-2) < wxT('2')) ||
1107 (*(uri
-2) == wxT('2') &&
1108 (*(uri
-1) < wxT('5') || (*(uri
-1) == wxT('5') && *uri
<= wxT('5')))
1115 if(IsDigit(*uri
))++uri
;
1121 bool wxURI::ParseIPv6address(const wxChar
*& uri
)
1123 // IPv6address = 6( h16 ":" ) ls32
1124 // / "::" 5( h16 ":" ) ls32
1125 // / [ h16 ] "::" 4( h16 ":" ) ls32
1126 // / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1127 // / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1128 // / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1129 // / [ *4( h16 ":" ) h16 ] "::" ls32
1130 // / [ *5( h16 ":" ) h16 ] "::" h16
1131 // / [ *6( h16 ":" ) h16 ] "::"
1133 size_t numPrefix
= 0,
1136 bool bEndHex
= false;
1138 for( ; numPrefix
< 6; ++numPrefix
)
1147 if(*uri
!= wxT(':'))
1153 if(!bEndHex
&& !ParseH16(uri
))
1160 if (*uri
== wxT(':'))
1162 if (*++uri
!= wxT(':'))
1172 if (*uri
!= wxT(':') || *(uri
+1) != wxT(':'))
1177 while (*--uri
!= wxT(':')) {}
1180 const wxChar
* uristart
= uri
;
1182 // ls32 = ( h16 ":" h16 ) / IPv4address
1183 if (ParseH16(uri
) && *uri
== wxT(':') && ParseH16(uri
))
1188 if (ParseIPv4address(uri
))
1200 maxPostfix
= 4 - numPrefix
;
1204 bool bAllowAltEnding
= maxPostfix
== 0;
1206 for(; maxPostfix
!= 0; --maxPostfix
)
1208 if(!ParseH16(uri
) || *uri
!= wxT(':'))
1214 const wxChar
* uristart
= uri
;
1216 // ls32 = ( h16 ":" h16 ) / IPv4address
1217 if (ParseH16(uri
) && *uri
== wxT(':') && ParseH16(uri
))
1222 if (ParseIPv4address(uri
))
1227 if (!bAllowAltEnding
)
1231 if(numPrefix
<= 5 && ParseH16(uri
))
1237 bool wxURI::ParseIPvFuture(const wxChar
*& uri
)
1239 // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1240 if (*++uri
!= wxT('v') || !IsHex(*++uri
))
1243 while (IsHex(*++uri
)) {}
1245 if (*uri
!= wxT('.') || !(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== wxT(':')))
1248 while(IsUnreserved(*++uri
) || IsSubDelim(*uri
) || *uri
== wxT(':')) {}
1254 // ---------------------------------------------------------------------------
1257 // Converts a character into a numeric hexidecimal value, or 0 if the
1258 // passed in character is not a valid hex character
1259 // ---------------------------------------------------------------------------
1262 wxChar
wxURI::CharToHex(const wxChar
& c
)
1264 if ((c
>= wxT('A')) && (c
<= wxT('Z'))) return wxChar(c
- wxT('A') + 0x0A);
1265 if ((c
>= wxT('a')) && (c
<= wxT('z'))) return wxChar(c
- wxT('a') + 0x0a);
1266 if ((c
>= wxT('0')) && (c
<= wxT('9'))) return wxChar(c
- wxT('0') + 0x00);
1271 // ---------------------------------------------------------------------------
1274 // Returns true if the passed in character meets the criteria of the method
1275 // ---------------------------------------------------------------------------
1277 //! unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1278 bool wxURI::IsUnreserved (const wxChar
& c
)
1279 { return IsAlpha(c
) || IsDigit(c
) ||
1283 c
== wxT('~') //tilde
1287 bool wxURI::IsReserved (const wxChar
& c
)
1289 return IsGenDelim(c
) || IsSubDelim(c
);
1292 //! gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
1293 bool wxURI::IsGenDelim (const wxChar
& c
)
1295 return c
== wxT(':') ||
1304 //! sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1305 //! / "*" / "+" / "," / ";" / "="
1306 bool wxURI::IsSubDelim (const wxChar
& c
)
1308 return c
== wxT('!') ||
1322 bool wxURI::IsHex(const wxChar
& c
)
1323 { return IsDigit(c
) || (c
>= wxT('a') && c
<= wxT('f')) || (c
>= wxT('A') && c
<= wxT('F')); }
1325 bool wxURI::IsAlpha(const wxChar
& c
)
1326 { return (c
>= wxT('a') && c
<= wxT('z')) || (c
>= wxT('A') && c
<= wxT('Z')); }
1328 bool wxURI::IsDigit(const wxChar
& c
)
1329 { return c
>= wxT('0') && c
<= wxT('9'); }