@@ -21,7 +21,7 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre
2121 {
2222 DebugAssertInCtor ( ) ;
2323
24- if ( ( int ) uriKind < ( int ) UriKind . RelativeOrAbsolute || ( int ) uriKind > ( int ) UriKind . Relative )
24+ if ( uriKind is < UriKind . RelativeOrAbsolute or > UriKind . Relative )
2525 {
2626 throw new ArgumentException ( SR . Format ( SR . net_uri_InvalidUriKind , uriKind ) ) ;
2727 }
@@ -38,176 +38,137 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre
3838
3939 ParsingError err = ParseScheme ( _string , ref _flags , ref _syntax ! ) ;
4040
41- InitializeUri ( err , uriKind , out UriFormatException ? e ) ;
41+ UriFormatException ? e = InitializeUri ( err , uriKind ) ;
4242 if ( e != null )
4343 throw e ;
4444 }
4545
46- private void InitializeUri ( ParsingError err , UriKind uriKind , out UriFormatException ? e )
46+ private UriFormatException ? InitializeUri ( ParsingError err , UriKind uriKind )
4747 {
4848 DebugAssertInCtor ( ) ;
49+ Debug . Assert ( ( err is ParsingError . None ) == ( _syntax is not null ) ) ;
50+
51+ bool hasUnicode = false ;
4952
50- if ( err == ParsingError . None )
53+ if ( IriParsing && CheckForUnicodeOrEscapedUnreserved ( _string ) )
54+ {
55+ _flags |= Flags . HasUnicode ;
56+ hasUnicode = true ;
57+ _originalUnicodeString = _string ; // original string location changed
58+ }
59+
60+ if ( err != ParsingError . None )
5161 {
52- if ( IsImplicitFile )
62+ // If we encountered any parsing errors that indicate this may be a relative Uri,
63+ // and we'll allow relative Uri's, then create one.
64+ if ( uriKind != UriKind . Absolute && err <= ParsingError . LastErrorOkayForRelativeUris )
5365 {
54- // V1 compat
55- // A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and
56- // uriKind != Absolute
57- // A relative Uri wins over implicit Unix path unless uriKind == Absolute
58- if ( NotAny ( Flags . DosPath ) &&
59- uriKind != UriKind . Absolute &&
60- ( ( uriKind == UriKind . Relative || ( _string . Length >= 2 && ( _string [ 0 ] != '\\ ' || _string [ 1 ] != '\\ ' ) ) )
61- || ( ! OperatingSystem . IsWindows ( ) && InFact ( Flags . UnixPath ) ) ) )
62- {
63- _syntax = null ! ; //make it be relative Uri
64- _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
65- e = null ;
66- return ;
67- // Otherwise an absolute file Uri wins when it's of the form "\\something"
68- }
69- //
70- // V1 compat issue
71- // We should support relative Uris of the form c:\bla or c:/bla
72- //
73- else if ( uriKind == UriKind . Relative && InFact ( Flags . DosPath ) )
66+ _flags &= Flags . UserEscaped | Flags . HasUnicode ; // the only flags that makes sense for a relative uri
67+ if ( hasUnicode )
7468 {
75- _syntax = null ! ; //make it be relative Uri
76- _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
77- e = null ;
78- return ;
79- // Otherwise an absolute file Uri wins when it's of the form "c:\something"
69+ // Iri'ze and then normalize relative uris
70+ _string = EscapeUnescapeIri ( _originalUnicodeString , 0 , _originalUnicodeString . Length , isQuery : false ) ;
8071 }
72+ return null ;
8173 }
82- }
83- else if ( err > ParsingError . LastErrorOkayForRelativeUris )
84- {
85- //This is a fatal error based solely on scheme name parsing
74+
75+ // This is a fatal error based solely on scheme name parsing
8676 _string = null ! ; // make it be invalid Uri
87- e = GetException ( err ) ;
88- return ;
77+ return GetException ( err ) ;
8978 }
9079
91- bool hasUnicode = false ;
80+ Debug . Assert ( _syntax is not null ) ;
9281
93- if ( IriParsing && CheckForUnicodeOrEscapedUnreserved ( _string ) )
82+ if ( IsImplicitFile )
9483 {
95- _flags |= Flags . HasUnicode ;
96- hasUnicode = true ;
97- // switch internal strings
98- _originalUnicodeString = _string ; // original string location changed
84+ if ( uriKind == UriKind . Relative )
85+ {
86+ _syntax = null ! ; // make it be relative Uri
87+ _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
88+ return null ;
89+ }
90+
91+ // V1 compat
92+ // A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and
93+ // uriKind != Absolute
94+ // A relative Uri wins over implicit Unix path unless uriKind == Absolute
95+ if ( NotAny ( Flags . DosPath ) && uriKind == UriKind . RelativeOrAbsolute &&
96+ ( ( _string . Length >= 2 && ( _string [ 0 ] != '\\ ' || _string [ 1 ] != '\\ ' ) )
97+ || ( ! OperatingSystem . IsWindows ( ) && InFact ( Flags . UnixPath ) ) ) )
98+ {
99+ _syntax = null ! ; //make it be relative Uri
100+ _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
101+ return null ;
102+ // Otherwise an absolute file Uri wins when it's of the form "\\something"
103+ }
99104 }
100105
101- if ( _syntax != null )
106+ if ( _syntax . IsSimple )
102107 {
103- if ( _syntax . IsSimple )
108+ if ( ( err = PrivateParseMinimal ( ) ) != ParsingError . None )
104109 {
105- if ( ( err = PrivateParseMinimal ( ) ) != ParsingError . None )
106- {
107- if ( uriKind != UriKind . Absolute && err <= ParsingError . LastErrorOkayForRelativeUris )
108- {
109- // RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri.
110- _syntax = null ! ; // convert to relative uri
111- e = null ;
112- _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
113- return ;
114- }
115- else
116- e = GetException ( err ) ;
117- }
118- else if ( uriKind == UriKind . Relative )
110+ if ( uriKind != UriKind . Absolute && err <= ParsingError . LastErrorOkayForRelativeUris )
119111 {
120- // Here we know that we can create an absolute Uri, but the user has requested only a relative one
121- e = GetException ( ParsingError . CannotCreateRelative ) ;
112+ // RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri.
113+ _syntax = null ! ; // convert to relative uri
114+ _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
115+ return null ;
122116 }
123- else
124- e = null ;
125- // will return from here
126117
127- if ( e is null && hasUnicode )
128- {
129- // In this scenario we need to parse the whole string
130- try
131- {
132- EnsureParseRemaining ( ) ;
133- }
134- catch ( UriFormatException ex )
135- {
136- e = ex ;
137- }
138- }
118+ return GetException ( err ) ;
139119 }
140- else
120+
121+ if ( uriKind == UriKind . Relative )
141122 {
142- // offer custom parser to create a parsing context
143- _syntax = _syntax . InternalOnNewUri ( ) ;
123+ // Here we know that we can create an absolute Uri, but the user has requested only a relative one
124+ return GetException ( ParsingError . CannotCreateRelative ) ;
125+ }
126+ }
127+ else
128+ {
129+ // offer custom parser to create a parsing context
130+ _syntax = _syntax . InternalOnNewUri ( ) ;
144131
145- // in case they won't call us
146- _flags |= Flags . UserDrivenParsing ;
132+ // in case they won't call us
133+ _flags |= Flags . UserDrivenParsing ;
147134
148- // Ask a registered type to validate this uri
149- _syntax . InternalValidate ( this , out e ) ;
135+ // Ask a registered type to validate this uri
136+ _syntax . InternalValidate ( this , out UriFormatException ? e ) ;
150137
151- if ( e != null )
152- {
153- // Can we still take it as a relative Uri?
154- if ( uriKind != UriKind . Absolute && err != ParsingError . None
155- && err <= ParsingError . LastErrorOkayForRelativeUris )
156- {
157- _syntax = null ! ; // convert it to relative
158- e = null ;
159- _flags &= Flags . UserEscaped ; // the only flag that makes sense for a relative uri
160- }
161- }
162- else // e == null
163- {
164- if ( err != ParsingError . None || InFact ( Flags . ErrorOrParsingRecursion ) )
165- {
166- // User parser took over on an invalid Uri
167- // we use = here to clear all parsing flags for a uri that we think is invalid.
168- _flags = Flags . UserDrivenParsing | ( _flags & Flags . UserEscaped ) ;
169- }
170- else if ( uriKind == UriKind . Relative )
171- {
172- // Here we know that custom parser can create an absolute Uri, but the user has requested only a
173- // relative one
174- e = GetException ( ParsingError . CannotCreateRelative ) ;
175- }
138+ if ( e is not null )
139+ {
140+ return e ;
141+ }
176142
177- if ( e is null && hasUnicode )
178- {
179- // In this scenario we need to parse the whole string
180- try
181- {
182- EnsureParseRemaining ( ) ;
183- }
184- catch ( UriFormatException ex )
185- {
186- e = ex ;
187- }
188- }
189- }
190- // will return from here
143+ if ( InFact ( Flags . ErrorOrParsingRecursion ) )
144+ {
145+ // User parser took over on an invalid Uri
146+ // we use = here to clear all parsing flags for a uri that we think is invalid.
147+ _flags = Flags . UserDrivenParsing | ( _flags & Flags . UserEscaped ) ;
191148 }
192- }
193- // If we encountered any parsing errors that indicate this may be a relative Uri,
194- // and we'll allow relative Uri's, then create one.
195- else if ( err != ParsingError . None && uriKind != UriKind . Absolute
196- && err <= ParsingError . LastErrorOkayForRelativeUris )
197- {
198- e = null ;
199- _flags &= ( Flags . UserEscaped | Flags . HasUnicode ) ; // the only flags that makes sense for a relative uri
200- if ( hasUnicode )
149+ else if ( uriKind == UriKind . Relative )
201150 {
202- // Iri'ze and then normalize relative uris
203- _string = EscapeUnescapeIri ( _originalUnicodeString , 0 , _originalUnicodeString . Length , isQuery : false ) ;
151+ // Here we know that custom parser can create an absolute Uri, but the user has requested only a
152+ // relative one
153+ return GetException ( ParsingError . CannotCreateRelative ) ;
204154 }
205155 }
206- else
156+
157+ if ( hasUnicode )
207158 {
208- _string = null ! ; // make it be invalid Uri
209- e = GetException ( err ) ;
159+ // In this scenario we need to parse the whole string
160+ try
161+ {
162+ EnsureParseRemaining ( ) ;
163+ }
164+ catch ( UriFormatException ex )
165+ {
166+ return ex ;
167+ }
210168 }
169+
170+ // We have a valid absolute Uri.
171+ return null ;
211172 }
212173
213174 /// <summary>SearchValues for all ASCII characters other than %</summary>
@@ -742,7 +703,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri)
742703 // Validate instance using ether built in or a user Parser
743704 try
744705 {
745- result . InitializeUri ( err , uriKind , out e ) ;
706+ e = result . InitializeUri ( err , uriKind ) ;
746707
747708 if ( e == null )
748709 {
0 commit comments