Exemple #1
0
        public override string ToString()
        {
            if (_username.Length == 0 && _password.Length > 0)
            {
                throw new UriFormatException(SR.net_uri_BadUserPassword);
            }

            if (_scheme.Length != 0)
            {
                UriParser?syntax = UriParser.GetSyntax(_scheme);
                if (syntax != null)
                {
                    _schemeDelimiter = syntax.InFact(UriSyntaxFlags.MustHaveAuthority) ||
                                       (_host.Length != 0 && syntax.NotAny(UriSyntaxFlags.MailToLikeUri) && syntax.InFact(UriSyntaxFlags.OptionalAuthority))
                            ? Uri.SchemeDelimiter
                            : ":";
                }
                else
                {
                    _schemeDelimiter = _host.Length != 0 ? Uri.SchemeDelimiter : ":";
                }
            }

            string result = _scheme.Length != 0 ? (_scheme + _schemeDelimiter) : string.Empty;

            return(result
                   + _username
                   + ((_password.Length > 0) ? (":" + _password) : string.Empty)
                   + ((_username.Length > 0) ? "@" : string.Empty)
                   + _host
                   + (((_port != -1) && (_host.Length > 0)) ? (":" + _port.ToString()) : string.Empty)
                   + (((_host.Length > 0) && (_path.Length != 0) && (_path[0] != '/')) ? "/" : string.Empty) + _path
                   + _query
                   + _fragment);
        }
Exemple #2
0
        //schemeStr must be in lower case!
        internal static UriParser FindOrFetchAsUnknownV1Syntax(string lwrCaseScheme)
        {
            // check may be other thread just added one
            UriParser?syntax = (UriParser?)s_table[lwrCaseScheme];

            if (syntax != null)
            {
                return(syntax);
            }
            syntax = (UriParser?)s_tempTable[lwrCaseScheme];
            if (syntax != null)
            {
                return(syntax);
            }
            lock (s_table)
            {
                if (s_tempTable.Count >= c_MaxCapacity)
                {
                    s_tempTable = new Hashtable(c_InitialTableSize);
                }
                syntax = new BuiltInUriParser(lwrCaseScheme, NoDefaultPort, UnknownV1SyntaxFlags);
                s_tempTable[lwrCaseScheme] = syntax;
                return(syntax);
            }
        }
Exemple #3
0
        private static void FetchSyntax(UriParser syntax, string lwrCaseSchemeName, int defaultPort)
        {
            if (syntax.SchemeName.Length != 0)
            {
                throw new InvalidOperationException(SR.Format(SR.net_uri_NeedFreshParser, syntax.SchemeName));
            }

            lock (s_table)
            {
                syntax._flags &= ~UriSyntaxFlags.V1_UnknownUri;
                UriParser?oldSyntax = (UriParser?)s_table[lwrCaseSchemeName];
                if (oldSyntax != null)
                {
                    throw new InvalidOperationException(SR.Format(SR.net_uri_AlreadyRegistered, oldSyntax.SchemeName));
                }

                oldSyntax = (UriParser?)s_tempTable[syntax.SchemeName];
                if (oldSyntax != null)
                {
                    // optimization on schemeName, will try to keep the first reference
                    lwrCaseSchemeName = oldSyntax._scheme;
                    s_tempTable.Remove(lwrCaseSchemeName);
                }

                syntax.OnRegister(lwrCaseSchemeName, defaultPort);
                syntax._scheme = lwrCaseSchemeName;
                syntax.CheckSetIsSimpleFlag();
                syntax._port = defaultPort;

                s_table[syntax.SchemeName] = syntax;
            }
        }
Exemple #4
0
        //
        // 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);
            }
        }
Exemple #5
0
        // Should never be used except by the below method
        private Uri(Flags flags, UriParser?uriParser, string uri)
        {
            _flags  = flags;
            _syntax = uriParser !;
            _string = uri;

            if (uriParser is null)
            {
                // Relative Uris are fully initialized after the call to this constructor
                // Absolute Uris will be initialized with a call to InitializeUri on the newly created instance
                DebugSetLeftCtor();
            }
        }
Exemple #6
0
        //
        // Is a Uri scheme known to System.Uri?
        //
        public static bool IsKnownScheme(string schemeName)
        {
            ArgumentNullException.ThrowIfNull(schemeName);

            if (!Uri.CheckSchemeName(schemeName))
            {
                throw new ArgumentOutOfRangeException(nameof(schemeName));
            }

            UriParser?syntax = UriParser.GetSyntax(schemeName.ToLowerInvariant());

            return(syntax != null && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri));
        }
Exemple #7
0
 // Should never be used except by the below method
 private Uri(Flags flags, UriParser?uriParser, string uri)
 {
     _flags  = flags;
     _syntax = uriParser !;
     _string = uri;
 }
Exemple #8
0
        internal static unsafe void UnescapeString(char *pStr, int start, int end, ref ValueStringBuilder dest,
                                                   char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery)
        {
            if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly)
            {
                dest.Append(pStr + start, end - start);
                return;
            }

            bool escapeReserved = false;
            bool iriParsing     = Uri.IriParsingStatic(syntax) &&
                                  ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape);

            for (int next = start; next < end;)
            {
                char ch = (char)0;

                for (; next < end; ++next)
                {
                    if ((ch = pStr[next]) == '%')
                    {
                        if ((unescapeMode & UnescapeMode.Unescape) == 0)
                        {
                            // re-escape, don't check anything else
                            escapeReserved = true;
                        }
                        else if (next + 2 < end)
                        {
                            ch = DecodeHexChars(pStr[next + 1], pStr[next + 2]);
                            // Unescape a good sequence if full unescape is requested
                            if (unescapeMode >= UnescapeMode.UnescapeAll)
                            {
                                if (ch == Uri.c_DummyChar)
                                {
                                    if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
                                    {
                                        // Should be a rare case where the app tries to feed an invalid escaped sequence
                                        throw new UriFormatException(SR.net_uri_BadString);
                                    }
                                    continue;
                                }
                            }
                            // re-escape % from an invalid sequence
                            else if (ch == Uri.c_DummyChar)
                            {
                                if ((unescapeMode & UnescapeMode.Escape) != 0)
                                {
                                    escapeReserved = true;
                                }
                                else
                                {
                                    continue;   // we should throw instead but since v1.0 would just print '%'
                                }
                            }
                            // Do not unescape '%' itself unless full unescape is requested
                            else if (ch == '%')
                            {
                                next += 2;
                                continue;
                            }
                            // Do not unescape a reserved char unless full unescape is requested
                            else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3)
                            {
                                next += 2;
                                continue;
                            }
                            // Do not unescape a dangerous char unless it's V1ToStringFlags mode
                            else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch))
                            {
                                next += 2;
                                continue;
                            }
                            else if (iriParsing && ((ch <= '\x9F' && IsNotSafeForUnescape(ch)) ||
                                                    (ch > '\x9F' && !IriHelper.CheckIriUnicodeRange(ch, isQuery))))
                            {
                                // check if unenscaping gives a char outside iri range
                                // if it does then keep it escaped
                                next += 2;
                                continue;
                            }
                            // unescape escaped char or escape %
                            break;
                        }
                        else if (unescapeMode >= UnescapeMode.UnescapeAll)
                        {
                            if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
                            {
                                // Should be a rare case where the app tries to feed an invalid escaped sequence
                                throw new UriFormatException(SR.net_uri_BadString);
                            }
                            // keep a '%' as part of a bogus sequence
                            continue;
                        }
                        else
                        {
                            escapeReserved = true;
                        }
                        // escape (escapeReserved==true) or otherwise unescape the sequence
                        break;
                    }
                    else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll))
                             == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll))
                    {
                        continue;
                    }
                    else if ((unescapeMode & UnescapeMode.Escape) != 0)
                    {
                        // Could actually escape some of the characters
                        if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3)
                        {
                            // found an unescaped reserved character -> escape it
                            escapeReserved = true;
                            break;
                        }
                        else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 &&
                                 (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F')))
                        {
                            // found an unescaped reserved character -> escape it
                            escapeReserved = true;
                            break;
                        }
                    }
                }

                //copy off previous characters from input
                while (start < next)
                {
                    dest.Append(pStr[start++]);
                }

                if (next != end)
                {
                    if (escapeReserved)
                    {
                        EscapeAsciiChar((byte)pStr[next], ref dest);
                        escapeReserved = false;
                        next++;
                    }
                    else if (ch <= 127)
                    {
                        dest.Append(ch);
                        next += 3;
                    }
                    else
                    {
                        // Unicode
                        int charactersRead = PercentEncodingHelper.UnescapePercentEncodedUTF8Sequence(
                            pStr + next,
                            end - next,
                            ref dest,
                            isQuery,
                            iriParsing);

                        Debug.Assert(charactersRead > 0);
                        next += charactersRead;
                    }

                    start = next;
                }
            }
        }
Exemple #9
0
 internal static unsafe void UnescapeString(ReadOnlySpan <char> input, ref ValueStringBuilder dest,
                                            char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery)
 {
     fixed(char *pStr = &MemoryMarshal.GetReference(input))
     {
         UnescapeString(pStr, 0, input.Length, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
     }
 }
Exemple #10
0
 //
 // This method will assume that any good Escaped Sequence will be unescaped in the output
 // - Assumes Dest.Length - detPosition >= end-start
 // - UnescapeLevel controls various modes of operation
 // - Any "bad" escape sequence will remain as is or '%' will be escaped.
 // - destPosition tells the starting index in dest for placing the result.
 //   On return destPosition tells the last character + 1 position in the "dest" array.
 // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel
 // - It is a RARE case when Unescape actually needs escaping some characters mentioned above.
 //   For this reason it returns a char[] that is usually the same ref as the input "dest" value.
 //
 internal static unsafe void UnescapeString(string input, int start, int end, ref ValueStringBuilder dest,
                                            char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery)
 {
     fixed(char *pStr = input)
     {
         UnescapeString(pStr, start, end, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery);
     }
 }
Exemple #11
0
        internal static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition,
                                                     char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery)
        {
            ValueStringBuilder vsb = new ValueStringBuilder(dest.Length);

            vsb.Append(dest.AsSpan(0, destPosition));
            UnescapeString(pStr, start, end, ref vsb, rsvd1, rsvd2, rsvd3, unescapeMode,
                           syntax, isQuery);

            if (vsb.Length > dest.Length)
            {
                dest = vsb.AsSpan().ToArray();
            }
            else
            {
                vsb.AsSpan(destPosition).TryCopyTo(dest.AsSpan(destPosition));
            }
            destPosition = vsb.Length;
            vsb.Dispose();
            return(dest);
        }
Exemple #12
0
 internal static unsafe char[] UnescapeString(string input, int start, int end, char[] dest,
                                              ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax,
                                              bool isQuery)
 {
     fixed(char *pStr = input)
     {
         return(UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode,
                               syntax, isQuery));
     }
 }
Exemple #13
0
        internal static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition,
                                                     char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery)
        {
            byte[]? bytes = null;
            byte escapedReallocations = 0;
            bool escapeReserved       = false;
            int  next       = start;
            bool iriParsing = Uri.IriParsingStatic(syntax) &&
                              ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape);

            char[]? unescapedChars = null;

            while (true)
            {
                // we may need to re-pin dest[]
                fixed(char *pDest = dest)
                {
                    if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly)
                    {
                        while (start < end)
                        {
                            pDest[destPosition++] = pStr[start++];
                        }
                        return(dest);
                    }

                    while (true)
                    {
                        char ch = (char)0;

                        for (; next < end; ++next)
                        {
                            if ((ch = pStr[next]) == '%')
                            {
                                if ((unescapeMode & UnescapeMode.Unescape) == 0)
                                {
                                    // re-escape, don't check anything else
                                    escapeReserved = true;
                                }
                                else if (next + 2 < end)
                                {
                                    ch = EscapedAscii(pStr[next + 1], pStr[next + 2]);
                                    // Unescape a good sequence if full unescape is requested
                                    if (unescapeMode >= UnescapeMode.UnescapeAll)
                                    {
                                        if (ch == Uri.c_DummyChar)
                                        {
                                            if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
                                            {
                                                // Should be a rare case where the app tries to feed an invalid escaped sequence
                                                throw new UriFormatException(SR.net_uri_BadString);
                                            }
                                            continue;
                                        }
                                    }
                                    // re-escape % from an invalid sequence
                                    else if (ch == Uri.c_DummyChar)
                                    {
                                        if ((unescapeMode & UnescapeMode.Escape) != 0)
                                        {
                                            escapeReserved = true;
                                        }
                                        else
                                        {
                                            continue;   // we should throw instead but since v1.0 would just print '%'
                                        }
                                    }
                                    // Do not unescape '%' itself unless full unescape is requested
                                    else if (ch == '%')
                                    {
                                        next += 2;
                                        continue;
                                    }
                                    // Do not unescape a reserved char unless full unescape is requested
                                    else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3)
                                    {
                                        next += 2;
                                        continue;
                                    }
                                    // Do not unescape a dangerous char unless it's V1ToStringFlags mode
                                    else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch))
                                    {
                                        next += 2;
                                        continue;
                                    }
                                    else if (iriParsing && ((ch <= '\x9F' && IsNotSafeForUnescape(ch)) ||
                                                            (ch > '\x9F' && !IriHelper.CheckIriUnicodeRange(ch, isQuery))))
                                    {
                                        // check if unenscaping gives a char outside iri range
                                        // if it does then keep it escaped
                                        next += 2;
                                        continue;
                                    }
                                    // unescape escaped char or escape %
                                    break;
                                }
                                else if (unescapeMode >= UnescapeMode.UnescapeAll)
                                {
                                    if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow)
                                    {
                                        // Should be a rare case where the app tries to feed an invalid escaped sequence
                                        throw new UriFormatException(SR.net_uri_BadString);
                                    }
                                    // keep a '%' as part of a bogus sequence
                                    continue;
                                }
                                else
                                {
                                    escapeReserved = true;
                                }
                                // escape (escapeReserved==true) or otherwise unescape the sequence
                                break;
                            }
                            else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll))
                                     == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll))
                            {
                                continue;
                            }
                            else if ((unescapeMode & UnescapeMode.Escape) != 0)
                            {
                                // Could actually escape some of the characters
                                if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3)
                                {
                                    // found an unescaped reserved character -> escape it
                                    escapeReserved = true;
                                    break;
                                }
                                else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 &&
                                         (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F')))
                                {
                                    // found an unescaped reserved character -> escape it
                                    escapeReserved = true;
                                    break;
                                }
                            }
                        }

                        //copy off previous characters from input
                        while (start < next)
                        {
                            pDest[destPosition++] = pStr[start++];
                        }

                        if (next != end)
                        {
                            if (escapeReserved)
                            {
                                //escape that char
                                // Since this should be _really_ rare case, reallocate with constant size increase of 30 rsvd-type characters.
                                if (escapedReallocations == 0)
                                {
                                    escapedReallocations = 30;
                                    char[] newDest = new char[dest.Length + escapedReallocations * 3];
                                    fixed(char *pNewDest = &newDest[0])
                                    {
                                        for (int i = 0; i < destPosition; ++i)
                                        {
                                            pNewDest[i] = pDest[i];
                                        }
                                    }

                                    dest = newDest;
                                    // re-pin new dest[] array
                                    goto dest_fixed_loop_break;
                                }
                                else
                                {
                                    --escapedReallocations;
                                    EscapeAsciiChar(pStr[next], dest, ref destPosition);
                                    escapeReserved = false;
                                    start          = ++next;
                                    continue;
                                }
                            }

                            // unescaping either one Ascii or possibly multiple Unicode

                            if (ch <= '\x7F')
                            {
                                //ASCII
                                dest[destPosition++] = ch;
                                next += 3;
                                start = next;
                                continue;
                            }

                            // Unicode

                            int byteCount = 1;
                            // lazy initialization of max size, will reuse the array for next sequences
                            if ((object?)bytes == null)
                            {
                                bytes = new byte[end - next];
                            }

                            bytes[0] = (byte)ch;
                            next    += 3;
                            while (next < end)
                            {
                                // Check on exit criterion
                                if ((ch = pStr[next]) != '%' || next + 2 >= end)
                                {
                                    break;
                                }

                                // already made sure we have 3 characters in str
                                ch = EscapedAscii(pStr[next + 1], pStr[next + 2]);

                                //invalid hex sequence ?
                                if (ch == Uri.c_DummyChar)
                                {
                                    break;
                                }
                                // character is not part of a UTF-8 sequence ?
                                else if (ch < '\x80')
                                {
                                    break;
                                }
                                else
                                {
                                    //a UTF-8 sequence
                                    bytes[byteCount++] = (byte)ch;
                                    next += 3;
                                }
                            }

                            if (unescapedChars == null || unescapedChars.Length < bytes.Length)
                            {
                                unescapedChars = new char[bytes.Length];
                            }

                            int charCount = s_noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0);

                            start = next;

                            // match exact bytes
                            // Do not unescape chars not allowed by Iri
                            // need to check for invalid utf sequences that may not have given any chars

                            MatchUTF8Sequence(pDest, dest, ref destPosition, unescapedChars.AsSpan(0, charCount), charCount, bytes,
                                              byteCount, isQuery, iriParsing);
                        }

                        if (next == end)
                        {
                            goto done;
                        }
                    }
                    dest_fixed_loop_break :;
                }
            }

            done : return(dest);
        }
Exemple #14
0
 internal static bool IriParsingStatic(UriParser?syntax)
 {
     throw new NotImplementedException();
 }