internal void InternalValidate(Uri thisUri, out UriFormatException?parsingError) { thisUri.DebugAssertInCtor(); InitializeAndValidate(thisUri, out parsingError); // InitializeAndValidate should not be called outside of the constructor Debug.Assert(sizeof(Uri.Flags) == sizeof(ulong)); Interlocked.Or(ref Unsafe.As <Uri.Flags, ulong>(ref thisUri._flags), (ulong)Uri.Flags.CustomParser_ParseMinimalAlreadyCalled); }
// // Returns true if the string represents a valid argument to the Uri ctor // If uriKind != AbsoluteUri then certain parsing errors are ignored but Uri usage is limited // public static bool TryCreate(string?uriString, UriKind uriKind, [NotNullWhen(true)] out Uri?result) { if ((object?)uriString == null) { result = null; return(false); } UriFormatException?e = null; result = CreateHelper(uriString, false, uriKind, ref e); return((object?)e == null && result != null); }
// // Returns true if the string represents a valid argument to the Uri ctor // If uriKind != AbsoluteUri then certain parsing errors are ignored but Uri usage is limited // public static bool TryCreate(string?uriString, UriKind uriKind, [NotNullWhen(true)] out Uri?result) { if (uriString is null) { result = null; return(false); } UriFormatException?e = null; result = CreateHelper(uriString, false, uriKind, ref e); result?.DebugSetLeftCtor(); return(e is null && result != null); }
public static bool TryCreate(Uri?baseUri, Uri?relativeUri, [NotNullWhen(true)] out Uri?result) { result = null; if (baseUri is null || relativeUri is null) { return(false); } if (baseUri.IsNotAbsoluteUri) { return(false); } UriFormatException?e = null; string? newUriString = null; bool dontEscape; if (baseUri.Syntax.IsSimple) { dontEscape = relativeUri.UserEscaped; result = ResolveHelper(baseUri, relativeUri, ref newUriString, ref dontEscape); } else { dontEscape = false; newUriString = baseUri.Syntax.InternalResolve(baseUri, relativeUri, out e); if (e != null) { return(false); } } if (result is null) { result = CreateHelper(newUriString !, dontEscape, UriKind.Absolute, ref e); } result?.DebugSetLeftCtor(); return(e is null && result != null && result.IsAbsoluteUri); }
// // Parses and validates a Uri object, is called at the Uri ctor time. // // This method returns a non null parsingError if Uri being created is invalid: // protected virtual void InitializeAndValidate(Uri uri, out UriFormatException?parsingError) { if (uri._syntax is null) { throw new InvalidOperationException(SR.net_uri_NotAbsolute); } if (!ReferenceEquals(uri._syntax, this)) { throw new InvalidOperationException(SR.Format(SR.net_uri_UserDrivenParsing, uri._syntax.GetType())); } Debug.Assert(sizeof(Uri.Flags) == sizeof(ulong)); // If ParseMinimal is called multiple times this Uri instance may be corrupted, throw an exception instead ulong previous = Interlocked.Or(ref Unsafe.As <Uri.Flags, ulong>(ref uri._flags), (ulong)Uri.Flags.CustomParser_ParseMinimalAlreadyCalled); if (((Uri.Flags)previous & Uri.Flags.CustomParser_ParseMinimalAlreadyCalled) != 0) { throw new InvalidOperationException(SR.net_uri_InitializeCalledAlreadyOrTooLate); } parsingError = uri.ParseMinimal(); }
// // a Uri.TryCreate() method goes through here. // internal static Uri?CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException?e) { // if (!Enum.IsDefined(typeof(UriKind), uriKind)) -- We currently believe that Enum.IsDefined() is too slow // to be used here. if ((int)uriKind < (int)UriKind.RelativeOrAbsolute || (int)uriKind > (int)UriKind.Relative) { throw new ArgumentException(SR.Format(SR.net_uri_InvalidUriKind, uriKind)); } UriParser? syntax = null; Flags flags = Flags.Zero; ParsingError err = ParseScheme(uriString, ref flags, ref syntax); if (dontEscape) { flags |= Flags.UserEscaped; } // We won't use User factory for these errors if (err != ParsingError.None) { // If it looks as a relative Uri, custom factory is ignored if (uriKind != UriKind.Absolute && err <= ParsingError.LastRelativeUriOkErrIndex) { return(new Uri((flags & Flags.UserEscaped), null, uriString)); } return(null); } // Cannot be relative Uri if came here Debug.Assert(syntax != null); Uri result = new Uri(flags, syntax, uriString); // Validate instance using ether built in or a user Parser try { result.InitializeUri(err, uriKind, out e); if (e == null) { result.DebugSetLeftCtor(); return(result); } return(null); } catch (UriFormatException ee) { Debug.Assert(!syntax !.IsSimple, "A UriPraser threw on InitializeAndValidate."); e = ee; // A precaution since custom Parser should never throw in this case. return(null); } }
private void InitializeUri(ParsingError err, UriKind uriKind, out UriFormatException?e) { DebugAssertInCtor(); if (err == ParsingError.None) { if (IsImplicitFile) { // 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] != '\\'))) || (!IsWindowsSystem && 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)) { _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" } } } else if (err > ParsingError.LastRelativeUriOkErrIndex) { //This is a fatal error based solely on scheme name parsing _string = null !; // make it be invalid Uri e = GetException(err); return; } bool hasUnicode = false; if (IriParsing && CheckForUnicodeOrEscapedUnreserved(_string)) { _flags |= Flags.HasUnicode; hasUnicode = true; // switch internal strings _originalUnicodeString = _string; // original string location changed } if (_syntax != null) { if (_syntax.IsSimple) { if ((err = PrivateParseMinimal()) != ParsingError.None) { if (uriKind != UriKind.Absolute && err <= ParsingError.LastRelativeUriOkErrIndex) { // 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) { // Here we know that we can create an absolute Uri, but the user has requested only a relative one e = GetException(ParsingError.CannotCreateRelative); } else { e = null; } // will return from here if (hasUnicode) { // In this scenario we need to parse the whole string try { EnsureParseRemaining(); } catch (UriFormatException ex) { e = ex; return; } } } else { // offer custom parser to create a parsing context _syntax = _syntax.InternalOnNewUri(); // in case they won't call us _flags |= Flags.UserDrivenParsing; // Ask a registered type to validate this uri _syntax.InternalValidate(this, out e); if (e != null) { // Can we still take it as a relative Uri? if (uriKind != UriKind.Absolute && err != ParsingError.None && err <= ParsingError.LastRelativeUriOkErrIndex) { _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 (hasUnicode) { // In this scenario we need to parse the whole string try { EnsureParseRemaining(); } catch (UriFormatException ex) { e = ex; return; } } } // will return from here } } // 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.LastRelativeUriOkErrIndex) { e = null; _flags &= (Flags.UserEscaped | Flags.HasUnicode); // the only flags that makes sense for a relative uri if (hasUnicode) { // Iri'ze and then normalize relative uris _string = EscapeUnescapeIri(_originalUnicodeString, 0, _originalUnicodeString.Length, (UriComponents)0); if (_string.Length > ushort.MaxValue) { err = ParsingError.SizeLimit; return; } } } else { _string = null !; // make it be invalid Uri e = GetException(err); } }
// // Resolves into either baseUri or relativeUri according to conditions OR if not possible it uses newUriString // to return combined URI strings from both Uris // otherwise if e != null on output the operation has failed // internal static Uri?ResolveHelper(Uri baseUri, Uri?relativeUri, ref string?newUriString, ref bool userEscaped, out UriFormatException?e) { Debug.Assert(!baseUri.IsNotAbsoluteUri && !baseUri.UserDrivenParsing, "Uri::ResolveHelper()|baseUri is not Absolute or is controlled by User Parser."); e = null; string relativeStr = string.Empty; if ((object?)relativeUri != null) { if (relativeUri.IsAbsoluteUri) { return(relativeUri); } relativeStr = relativeUri.OriginalString; userEscaped = relativeUri.UserEscaped; } else { relativeStr = string.Empty; } // Here we can assert that passed "relativeUri" is indeed a relative one if (relativeStr.Length > 0 && (UriHelper.IsLWS(relativeStr[0]) || UriHelper.IsLWS(relativeStr[relativeStr.Length - 1]))) { relativeStr = relativeStr.Trim(UriHelper.s_WSchars); } if (relativeStr.Length == 0) { newUriString = baseUri.GetParts(UriComponents.AbsoluteUri, baseUri.UserEscaped ? UriFormat.UriEscaped : UriFormat.SafeUnescaped); return(null); } // Check for a simple fragment in relative part if (relativeStr[0] == '#' && !baseUri.IsImplicitFile && baseUri.Syntax !.InFact(UriSyntaxFlags.MayHaveFragment)) { newUriString = baseUri.GetParts(UriComponents.AbsoluteUri & ~UriComponents.Fragment, UriFormat.UriEscaped) + relativeStr; return(null); } // Check for a simple query in relative part if (relativeStr[0] == '?' && !baseUri.IsImplicitFile && baseUri.Syntax !.InFact(UriSyntaxFlags.MayHaveQuery)) { newUriString = baseUri.GetParts(UriComponents.AbsoluteUri & ~UriComponents.Query & ~UriComponents.Fragment, UriFormat.UriEscaped) + relativeStr; return(null); } // Check on the DOS path in the relative Uri (a special case) if (relativeStr.Length >= 3 && (relativeStr[1] == ':' || relativeStr[1] == '|') && UriHelper.IsAsciiLetter(relativeStr[0]) && (relativeStr[2] == '\\' || relativeStr[2] == '/')) { if (baseUri.IsImplicitFile) { // It could have file:/// prepended to the result but we want to keep it as *Implicit* File Uri newUriString = relativeStr; return(null); } else if (baseUri.Syntax !.InFact(UriSyntaxFlags.AllowDOSPath)) { // The scheme is not changed just the path gets replaced string prefix; if (baseUri.InFact(Flags.AuthorityFound)) { prefix = baseUri.Syntax.InFact(UriSyntaxFlags.PathIsRooted) ? ":///" : "://"; } else { prefix = baseUri.Syntax.InFact(UriSyntaxFlags.PathIsRooted) ? ":/" : ":"; } newUriString = baseUri.Scheme + prefix + relativeStr; return(null); } // If we are here then input like "http://host/path/" + "C:\x" will produce the result http://host/path/c:/x } ParsingError err = GetCombinedString(baseUri, relativeStr, userEscaped, ref newUriString); if (err != ParsingError.None) { e = GetException(err); return(null); } if ((object?)newUriString == (object)baseUri._string) { return(baseUri); } return(null); }
internal string?InternalResolve(Uri thisBaseUri, Uri uriLink, out UriFormatException?parsingError) { return(Resolve(thisBaseUri, uriLink, out parsingError)); }
internal void InternalValidate(Uri thisUri, out UriFormatException?parsingError) { InitializeAndValidate(thisUri, out parsingError); }
// // Parses and validates a Uri object, is called at the Uri ctor time. // // This method returns a non null parsingError if Uri being created is invalid: // protected virtual void InitializeAndValidate(Uri uri, out UriFormatException?parsingError) { parsingError = uri.ParseMinimal(); }