diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index 5128aaf44bf200..7f5ea9df6966ee 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -700,41 +700,32 @@ private static void GetCombinedString(Uri baseUri, string relativeStr, } } - private static UriFormatException? GetException(ParsingError err) + private static UriFormatException GetException(ParsingError err) { - switch (err) + Debug.Assert(err != ParsingError.None); + + string message = err switch { - case ParsingError.None: - return null; // Could be OK for Relative Uri - case ParsingError.BadFormat: - return new UriFormatException(SR.net_uri_BadFormat); - case ParsingError.BadScheme: - return new UriFormatException(SR.net_uri_BadScheme); - case ParsingError.BadAuthority: - return new UriFormatException(SR.net_uri_BadAuthority); - case ParsingError.EmptyUriString: - return new UriFormatException(SR.net_uri_EmptyUri); + ParsingError.BadFormat => SR.net_uri_BadFormat, + ParsingError.BadScheme => SR.net_uri_BadScheme, + ParsingError.BadAuthority => SR.net_uri_BadAuthority, + ParsingError.EmptyUriString => SR.net_uri_EmptyUri, + // Fatal - case ParsingError.SchemeLimit: - return new UriFormatException(SR.net_uri_SchemeLimit); - case ParsingError.MustRootedPath: - return new UriFormatException(SR.net_uri_MustRootedPath); + ParsingError.SchemeLimit => SR.net_uri_SchemeLimit, + ParsingError.MustRootedPath => SR.net_uri_MustRootedPath, + // Derived class controllable - case ParsingError.BadHostName: - return new UriFormatException(SR.net_uri_BadHostName); - case ParsingError.NonEmptyHost: //unix-only - return new UriFormatException(SR.net_uri_BadFormat); - case ParsingError.BadPort: - return new UriFormatException(SR.net_uri_BadPort); - case ParsingError.BadAuthorityTerminator: - return new UriFormatException(SR.net_uri_BadAuthorityTerminator); - case ParsingError.CannotCreateRelative: - return new UriFormatException(SR.net_uri_CannotCreateRelative); - default: - break; - } - return new UriFormatException(SR.net_uri_BadFormat); + ParsingError.BadHostName => SR.net_uri_BadHostName, + ParsingError.BadPort => SR.net_uri_BadPort, + ParsingError.BadAuthorityTerminator => SR.net_uri_BadAuthorityTerminator, + ParsingError.CannotCreateRelative => SR.net_uri_CannotCreateRelative, + + _ => throw new UnreachableException() + }; + + return new UriFormatException(message); } public string AbsolutePath diff --git a/src/libraries/System.Private.Uri/src/System/UriEnumTypes.cs b/src/libraries/System.Private.Uri/src/System/UriEnumTypes.cs index 17d9456ba77328..d127dfbf60af9b 100644 --- a/src/libraries/System.Private.Uri/src/System/UriEnumTypes.cs +++ b/src/libraries/System.Private.Uri/src/System/UriEnumTypes.cs @@ -73,7 +73,6 @@ internal enum ParsingError // derived class controlled BadHostName, - NonEmptyHost, // unix only BadPort, BadAuthorityTerminator, diff --git a/src/libraries/System.Private.Uri/src/System/UriExt.cs b/src/libraries/System.Private.Uri/src/System/UriExt.cs index e5fc3f1532dc57..51dcb3694dc2f0 100644 --- a/src/libraries/System.Private.Uri/src/System/UriExt.cs +++ b/src/libraries/System.Private.Uri/src/System/UriExt.cs @@ -21,7 +21,7 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre { DebugAssertInCtor(); - if ((int)uriKind < (int)UriKind.RelativeOrAbsolute || (int)uriKind > (int)UriKind.Relative) + if (uriKind is < UriKind.RelativeOrAbsolute or > UriKind.Relative) { throw new ArgumentException(SR.Format(SR.net_uri_InvalidUriKind, uriKind)); } @@ -38,176 +38,137 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre ParsingError err = ParseScheme(_string, ref _flags, ref _syntax!); - InitializeUri(err, uriKind, out UriFormatException? e); + UriFormatException? e = InitializeUri(err, uriKind); if (e != null) throw e; } - private void InitializeUri(ParsingError err, UriKind uriKind, out UriFormatException? e) + private UriFormatException? InitializeUri(ParsingError err, UriKind uriKind) { DebugAssertInCtor(); + Debug.Assert((err is ParsingError.None) == (_syntax is not null)); + + bool hasUnicode = false; - if (err == ParsingError.None) + if (IriParsing && CheckForUnicodeOrEscapedUnreserved(_string)) + { + _flags |= Flags.HasUnicode; + hasUnicode = true; + _originalUnicodeString = _string; // original string location changed + } + + if (err != ParsingError.None) { - if (IsImplicitFile) + // If we encountered any parsing errors that indicate this may be a relative Uri, + // and we'll allow relative Uri's, then create one. + if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris) { - // V1 compat - // A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and - // uriKind != Absolute - // A relative Uri wins over implicit Unix path unless uriKind == Absolute - if (NotAny(Flags.DosPath) && - uriKind != UriKind.Absolute && - ((uriKind == UriKind.Relative || (_string.Length >= 2 && (_string[0] != '\\' || _string[1] != '\\'))) - || (!OperatingSystem.IsWindows() && InFact(Flags.UnixPath)))) - { - _syntax = null!; //make it be relative Uri - _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri - e = null; - return; - // Otherwise an absolute file Uri wins when it's of the form "\\something" - } - // - // V1 compat issue - // We should support relative Uris of the form c:\bla or c:/bla - // - else if (uriKind == UriKind.Relative && InFact(Flags.DosPath)) + _flags &= Flags.UserEscaped | Flags.HasUnicode; // the only flags that makes sense for a relative uri + if (hasUnicode) { - _syntax = null!; //make it be relative Uri - _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri - e = null; - return; - // Otherwise an absolute file Uri wins when it's of the form "c:\something" + // Iri'ze and then normalize relative uris + _string = EscapeUnescapeIri(_originalUnicodeString, 0, _originalUnicodeString.Length, isQuery: false); } + return null; } - } - else if (err > ParsingError.LastErrorOkayForRelativeUris) - { - //This is a fatal error based solely on scheme name parsing + + // This is a fatal error based solely on scheme name parsing _string = null!; // make it be invalid Uri - e = GetException(err); - return; + return GetException(err); } - bool hasUnicode = false; + Debug.Assert(_syntax is not null); - if (IriParsing && CheckForUnicodeOrEscapedUnreserved(_string)) + if (IsImplicitFile) { - _flags |= Flags.HasUnicode; - hasUnicode = true; - // switch internal strings - _originalUnicodeString = _string; // original string location changed + if (uriKind == UriKind.Relative) + { + _syntax = null!; // make it be relative Uri + _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri + return null; + } + + // V1 compat + // A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and + // uriKind != Absolute + // A relative Uri wins over implicit Unix path unless uriKind == Absolute + if (NotAny(Flags.DosPath) && uriKind == UriKind.RelativeOrAbsolute && + ((_string.Length >= 2 && (_string[0] != '\\' || _string[1] != '\\')) + || (!OperatingSystem.IsWindows() && InFact(Flags.UnixPath)))) + { + _syntax = null!; //make it be relative Uri + _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri + return null; + // Otherwise an absolute file Uri wins when it's of the form "\\something" + } } - if (_syntax != null) + if (_syntax.IsSimple) { - if (_syntax.IsSimple) + if ((err = PrivateParseMinimal()) != ParsingError.None) { - if ((err = PrivateParseMinimal()) != ParsingError.None) - { - if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris) - { - // RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri. - _syntax = null!; // convert to relative uri - e = null; - _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri - return; - } - else - e = GetException(err); - } - else if (uriKind == UriKind.Relative) + if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris) { - // Here we know that we can create an absolute Uri, but the user has requested only a relative one - e = GetException(ParsingError.CannotCreateRelative); + // RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri. + _syntax = null!; // convert to relative uri + _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri + return null; } - else - e = null; - // will return from here - if (e is null && hasUnicode) - { - // In this scenario we need to parse the whole string - try - { - EnsureParseRemaining(); - } - catch (UriFormatException ex) - { - e = ex; - } - } + return GetException(err); } - else + + if (uriKind == UriKind.Relative) { - // offer custom parser to create a parsing context - _syntax = _syntax.InternalOnNewUri(); + // Here we know that we can create an absolute Uri, but the user has requested only a relative one + return GetException(ParsingError.CannotCreateRelative); + } + } + else + { + // offer custom parser to create a parsing context + _syntax = _syntax.InternalOnNewUri(); - // in case they won't call us - _flags |= Flags.UserDrivenParsing; + // in case they won't call us + _flags |= Flags.UserDrivenParsing; - // Ask a registered type to validate this uri - _syntax.InternalValidate(this, out e); + // Ask a registered type to validate this uri + _syntax.InternalValidate(this, out UriFormatException? e); - if (e != null) - { - // Can we still take it as a relative Uri? - if (uriKind != UriKind.Absolute && err != ParsingError.None - && err <= ParsingError.LastErrorOkayForRelativeUris) - { - _syntax = null!; // convert it to relative - e = null; - _flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri - } - } - else // e == null - { - if (err != ParsingError.None || InFact(Flags.ErrorOrParsingRecursion)) - { - // User parser took over on an invalid Uri - // we use = here to clear all parsing flags for a uri that we think is invalid. - _flags = Flags.UserDrivenParsing | (_flags & Flags.UserEscaped); - } - else if (uriKind == UriKind.Relative) - { - // Here we know that custom parser can create an absolute Uri, but the user has requested only a - // relative one - e = GetException(ParsingError.CannotCreateRelative); - } + if (e is not null) + { + return e; + } - if (e is null && hasUnicode) - { - // In this scenario we need to parse the whole string - try - { - EnsureParseRemaining(); - } - catch (UriFormatException ex) - { - e = ex; - } - } - } - // will return from here + if (InFact(Flags.ErrorOrParsingRecursion)) + { + // User parser took over on an invalid Uri + // we use = here to clear all parsing flags for a uri that we think is invalid. + _flags = Flags.UserDrivenParsing | (_flags & Flags.UserEscaped); } - } - // If we encountered any parsing errors that indicate this may be a relative Uri, - // and we'll allow relative Uri's, then create one. - else if (err != ParsingError.None && uriKind != UriKind.Absolute - && err <= ParsingError.LastErrorOkayForRelativeUris) - { - e = null; - _flags &= (Flags.UserEscaped | Flags.HasUnicode); // the only flags that makes sense for a relative uri - if (hasUnicode) + else if (uriKind == UriKind.Relative) { - // Iri'ze and then normalize relative uris - _string = EscapeUnescapeIri(_originalUnicodeString, 0, _originalUnicodeString.Length, isQuery: false); + // Here we know that custom parser can create an absolute Uri, but the user has requested only a + // relative one + return GetException(ParsingError.CannotCreateRelative); } } - else + + if (hasUnicode) { - _string = null!; // make it be invalid Uri - e = GetException(err); + // In this scenario we need to parse the whole string + try + { + EnsureParseRemaining(); + } + catch (UriFormatException ex) + { + return ex; + } } + + // We have a valid absolute Uri. + return null; } /// SearchValues for all ASCII characters other than % @@ -742,7 +703,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri) // Validate instance using ether built in or a user Parser try { - result.InitializeUri(err, uriKind, out e); + e = result.InitializeUri(err, uriKind); if (e == null) {