Beispiel #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) : string.Empty)
                   + (((_host.Length > 0) && (_path.Length != 0) && (_path[0] != '/')) ? "/" : string.Empty) + _path
                   + _query
                   + _fragment);
        }
        public override string ToString()
        {
            if ((this.m_username.Length == 0) && (this.m_password.Length > 0))
            {
                throw new UriFormatException(SR.GetString("net_uri_BadUserPassword"));
            }
            if (this.m_scheme.Length != 0)
            {
                UriParser syntax = UriParser.GetSyntax(this.m_scheme);
                if (syntax != null)
                {
                    this.m_schemeDelimiter = (syntax.InFact(UriSyntaxFlags.MustHaveAuthority) || (((this.m_host.Length != 0) && syntax.NotAny(UriSyntaxFlags.MailToLikeUri)) && syntax.InFact(UriSyntaxFlags.OptionalAuthority))) ? System.Uri.SchemeDelimiter : ":";
                }
                else
                {
                    this.m_schemeDelimiter = (this.m_host.Length != 0) ? System.Uri.SchemeDelimiter : ":";
                }
            }
            string str = (this.m_scheme.Length != 0) ? (this.m_scheme + this.m_schemeDelimiter) : string.Empty;

            string[] strArray = new string[] { str, this.m_username, (this.m_password.Length > 0) ? (":" + this.m_password) : string.Empty, (this.m_username.Length > 0) ? "@" : string.Empty, this.m_host, ((this.m_port != -1) && (this.m_host.Length > 0)) ? (":" + this.m_port) : string.Empty, (((this.m_host.Length > 0) && (this.m_path.Length != 0)) && (this.m_path[0] != '/')) ? "/" : string.Empty, this.m_path, this.m_query, this.m_fragment };
            return(string.Concat(strArray));
        }
 private static bool StaticIsFile(UriParser syntax)
 {
     return syntax.InFact(UriSyntaxFlags.FileLikeUri);
 }
 private static bool IriParsingStatic(UriParser syntax)
 {
     if (!s_IriParsing)
     {
         return false;
     }
     return (((syntax != null) && syntax.InFact(UriSyntaxFlags.AllowIriParsing)) || (syntax == null));
 }
 private unsafe ushort CheckAuthorityHelper(char* pString, ushort idx, ushort length, ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost)
 {
     char ch;
     int end = length;
     int num2 = idx;
     ushort index = idx;
     newHost = null;
     bool justNormalized = false;
     bool iriParsing = s_IriParsing && IriParsingStatic(syntax);
     bool hasUnicode = (flags & Flags.HasUnicode) != Flags.HostNotParsed;
     bool flag4 = (flags & (Flags.HostNotParsed | Flags.HostUnicodeNormalized)) == Flags.HostNotParsed;
     UriSyntaxFlags flags2 = syntax.Flags;
     if ((hasUnicode && iriParsing) && flag4)
     {
         newHost = this.m_originalUnicodeString.Substring(0, num2);
     }
     if ((((idx == length) || ((ch = pString[idx]) == '/')) || ((ch == '\\') && StaticIsFile(syntax))) || ((ch == '#') || (ch == '?')))
     {
         if (syntax.InFact(UriSyntaxFlags.AllowEmptyHost))
         {
             flags &= ~(Flags.HostNotParsed | Flags.UncPath);
             if (StaticInFact(flags, Flags.HostNotParsed | Flags.ImplicitFile))
             {
                 err = ParsingError.BadHostName;
             }
             else
             {
                 flags |= Flags.BasicHostType;
             }
         }
         else
         {
             err = ParsingError.BadHostName;
         }
         if ((hasUnicode && iriParsing) && flag4)
         {
             flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized;
         }
         return idx;
     }
     string userInfoString = null;
     if ((flags2 & UriSyntaxFlags.MayHaveUserInfo) != UriSyntaxFlags.None)
     {
         while (index < end)
         {
             if (((index == (end - 1)) || (pString[index] == '?')) || (((pString[index] == '#') || (pString[index] == '\\')) || (pString[index] == '/')))
             {
                 index = idx;
                 break;
             }
             if (pString[index] == '@')
             {
                 flags |= Flags.HasUserInfo;
                 if (iriParsing || (s_IdnScope != null))
                 {
                     if ((iriParsing && hasUnicode) && flag4)
                     {
                         userInfoString = this.EscapeUnescapeIri(pString, num2, index + 1, UriComponents.UserInfo);
                         try
                         {
                             userInfoString = userInfoString.Normalize(NormalizationForm.FormC);
                         }
                         catch (ArgumentException)
                         {
                             err = ParsingError.BadFormat;
                             return idx;
                         }
                         newHost = newHost + userInfoString;
                     }
                     else
                     {
                         userInfoString = new string(pString, num2, (index - num2) + 1);
                     }
                 }
                 index = (ushort) (index + 1);
                 ch = pString[index];
                 break;
             }
             index = (ushort) (index + 1);
         }
     }
     bool notCanonical = (flags2 & UriSyntaxFlags.SimpleUserSyntax) == UriSyntaxFlags.None;
     if (((ch == '[') && syntax.InFact(UriSyntaxFlags.AllowIPv6Host)) && IPv6AddressHelper.IsValid(pString, index + 1, ref end))
     {
         flags |= Flags.HostNotParsed | Flags.IPv6HostType;
         if (!s_ConfigInitialized)
         {
             InitializeUriConfig();
             this.m_iriParsing = s_IriParsing && IriParsingStatic(syntax);
         }
         if ((hasUnicode && iriParsing) && flag4)
         {
             newHost = newHost + new string(pString, index, end - index);
             flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized;
             justNormalized = true;
         }
     }
     else if (((ch <= '9') && (ch >= '0')) && (syntax.InFact(UriSyntaxFlags.AllowIPv4Host) && IPv4AddressHelper.IsValid(pString, index, ref end, false, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile))))
     {
         flags |= Flags.HostNotParsed | Flags.IPv4HostType;
         if ((hasUnicode && iriParsing) && flag4)
         {
             newHost = newHost + new string(pString, index, end - index);
             flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized;
             justNormalized = true;
         }
     }
     else if ((((flags2 & UriSyntaxFlags.AllowDnsHost) != UriSyntaxFlags.None) && !iriParsing) && DomainNameHelper.IsValid(pString, index, ref end, ref notCanonical, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile)))
     {
         flags |= Flags.DnsHostType;
         if (!notCanonical)
         {
             flags |= Flags.CanonicalDnsHost;
         }
         if (s_IdnScope != null)
         {
             if ((s_IdnScope == 1) && this.IsIntranet(new string(pString, 0, end)))
             {
                 flags |= Flags.HostNotParsed | Flags.IntranetUri;
             }
             if (this.AllowIdnStatic(syntax, flags))
             {
                 bool allAscii = true;
                 bool atLeastOneValidIdn = false;
                 string str2 = DomainNameHelper.UnicodeEquivalent(pString, index, end, ref allAscii, ref atLeastOneValidIdn);
                 if (atLeastOneValidIdn)
                 {
                     if (StaticNotAny(flags, Flags.HasUnicode))
                     {
                         this.m_originalUnicodeString = this.m_String;
                     }
                     flags |= Flags.HostNotParsed | Flags.IdnHost;
                     newHost = this.m_originalUnicodeString.Substring(0, num2) + userInfoString + str2;
                     flags |= Flags.CanonicalDnsHost;
                     this.m_DnsSafeHost = new string(pString, index, end - index);
                     justNormalized = true;
                 }
                 flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized;
             }
         }
     }
     else if ((((iriParsing || (s_IdnScope != null)) && ((flags2 & UriSyntaxFlags.AllowDnsHost) != UriSyntaxFlags.None)) && ((iriParsing && flag4) || this.AllowIdnStatic(syntax, flags))) && DomainNameHelper.IsValidByIri(pString, index, ref end, ref notCanonical, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile)))
     {
         this.CheckAuthorityHelperHandleDnsIri(pString, index, end, num2, iriParsing, hasUnicode, syntax, userInfoString, ref flags, ref justNormalized, ref newHost, ref err);
     }
     else if ((((s_IdnScope == null) && !s_IriParsing) && (((flags2 & UriSyntaxFlags.AllowUncHost) != UriSyntaxFlags.None) && UncNameHelper.IsValid(pString, index, ref end, StaticNotAny(flags, Flags.HostNotParsed | Flags.ImplicitFile)))) && ((end - index) <= 0x100))
     {
         flags |= Flags.HostNotParsed | Flags.UncHostType;
     }
     if (((end < length) && (pString[end] == '\\')) && (((flags & (Flags.BasicHostType | Flags.IPv4HostType)) != Flags.HostNotParsed) && !StaticIsFile(syntax)))
     {
         if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri))
         {
             err = ParsingError.BadHostName;
             flags |= Flags.BasicHostType | Flags.IPv4HostType;
             return (ushort) end;
         }
         flags &= ~(Flags.BasicHostType | Flags.IPv4HostType);
     }
     else if ((end < length) && (pString[end] == ':'))
     {
         if (!syntax.InFact(UriSyntaxFlags.MayHavePort))
         {
             flags &= ~(Flags.BasicHostType | Flags.IPv4HostType);
         }
         else
         {
             int num4 = 0;
             int startIndex = end;
             idx = (ushort) (end + 1);
             while (idx < length)
             {
                 ushort num6 = pString[idx] - '0';
                 if ((num6 >= 0) && (num6 <= 9))
                 {
                     num4 = (num4 * 10) + num6;
                     if (num4 > 0xffff)
                     {
                         break;
                     }
                 }
                 else
                 {
                     if (((num6 == 0xffff) || (num6 == 15)) || (num6 == 0xfff3))
                     {
                         break;
                     }
                     if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost) && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri))
                     {
                         flags &= ~(Flags.BasicHostType | Flags.IPv4HostType);
                         break;
                     }
                     err = ParsingError.BadPort;
                     return idx;
                 }
                 idx = (ushort) (idx + 1);
             }
             if (num4 > 0xffff)
             {
                 if (!syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost))
                 {
                     err = ParsingError.BadPort;
                     return idx;
                 }
                 flags &= ~(Flags.BasicHostType | Flags.IPv4HostType);
             }
             if ((iriParsing && hasUnicode) && justNormalized)
             {
                 newHost = newHost + new string(pString, startIndex, idx - startIndex);
             }
         }
     }
     if ((flags & (Flags.BasicHostType | Flags.IPv4HostType)) == Flags.HostNotParsed)
     {
         flags &= ~Flags.HasUserInfo;
         if (!syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost))
         {
             if (!syntax.InFact(UriSyntaxFlags.V1_UnknownUri))
             {
                 if (syntax.InFact(UriSyntaxFlags.MustHaveAuthority))
                 {
                     err = ParsingError.BadHostName;
                     flags |= Flags.BasicHostType | Flags.IPv4HostType;
                     return idx;
                 }
             }
             else
             {
                 bool flag8 = false;
                 int num7 = idx;
                 for (end = idx; end < length; end++)
                 {
                     if (flag8 && (((pString[end] == '/') || (pString[end] == '?')) || (pString[end] == '#')))
                     {
                         break;
                     }
                     if ((end < (idx + 2)) && (pString[end] == '.'))
                     {
                         flag8 = true;
                     }
                     else
                     {
                         err = ParsingError.BadHostName;
                         flags |= Flags.BasicHostType | Flags.IPv4HostType;
                         return idx;
                     }
                 }
                 flags |= Flags.BasicHostType;
                 if ((iriParsing && hasUnicode) && StaticNotAny(flags, Flags.HostNotParsed | Flags.HostUnicodeNormalized))
                 {
                     string str3 = new string(pString, num7, num7 - end);
                     try
                     {
                         newHost = newHost + str3.Normalize(NormalizationForm.FormC);
                     }
                     catch (ArgumentException)
                     {
                         err = ParsingError.BadFormat;
                         return idx;
                     }
                     flags |= Flags.HostNotParsed | Flags.HostUnicodeNormalized;
                 }
             }
         }
         else
         {
             flags |= Flags.BasicHostType;
             end = idx;
             while (end < length)
             {
                 if (((pString[end] == '/') || (pString[end] == '?')) || (pString[end] == '#'))
                 {
                     break;
                 }
                 end++;
             }
             this.CheckAuthorityHelperHandleAnyHostIri(pString, num2, end, iriParsing, hasUnicode, syntax, ref flags, ref newHost, ref err);
         }
     }
     return (ushort) end;
 }
 private static char[] Compress(char[] dest, ushort start, ref int destLength, UriParser syntax)
 {
     ushort num = 0;
     ushort num2 = 0;
     ushort num3 = 0;
     ushort num4 = 0;
     ushort index = (ushort) (((ushort) destLength) - 1);
     start = (ushort) (start - 1);
     while (index != start)
     {
         char ch = dest[index];
         if ((ch == '\\') && syntax.InFact(UriSyntaxFlags.ConvertPathSlashes))
         {
             dest[index] = ch = '/';
         }
         if (ch == '/')
         {
             num = (ushort) (num + 1);
         }
         else
         {
             if (num > 1)
             {
                 num2 = (ushort) (index + 1);
             }
             num = 0;
         }
         if (ch == '.')
         {
             num3 = (ushort) (num3 + 1);
             goto Label_017F;
         }
         if (num3 == 0)
         {
             goto Label_0148;
         }
         bool flag = syntax.NotAny(UriSyntaxFlags.CanonicalizeAsFilePath) && (((num3 > 2) || (ch != '/')) || (index == start));
         if (!flag && (ch == '/'))
         {
             if ((num2 != ((index + num3) + 1)) && ((num2 != 0) || (((index + num3) + 1) != destLength)))
             {
                 goto Label_0146;
             }
             num2 = (ushort) (((index + 1) + num3) + ((num2 == 0) ? 0 : 1));
             Buffer.BlockCopy(dest, num2 << 1, dest, (index + 1) << 1, (destLength - num2) << 1);
             destLength -= (num2 - index) - 1;
             num2 = index;
             if (num3 == 2)
             {
                 num4 = (ushort) (num4 + 1);
             }
             num3 = 0;
             goto Label_017F;
         }
         if ((!flag && (num4 == 0)) && ((num2 == ((index + num3) + 1)) || ((num2 == 0) && (((index + num3) + 1) == destLength))))
         {
             num3 = (ushort) ((index + 1) + num3);
             Buffer.BlockCopy(dest, num3 << 1, dest, (index + 1) << 1, (destLength - num3) << 1);
             destLength -= (num3 - index) - 1;
             num2 = 0;
             num3 = 0;
             goto Label_017F;
         }
     Label_0146:
         num3 = 0;
     Label_0148:
         if (ch == '/')
         {
             if (num4 != 0)
             {
                 num4 = (ushort) (num4 - 1);
                 num2 = (ushort) (num2 + 1);
                 Buffer.BlockCopy(dest, num2 << 1, dest, (index + 1) << 1, (destLength - num2) << 1);
                 destLength -= (num2 - index) - 1;
             }
             num2 = index;
         }
     Label_017F:
         index = (ushort) (index - 1);
     }
     start = (ushort) (start + 1);
     if (((((ushort) destLength) > start) && syntax.InFact(UriSyntaxFlags.CanonicalizeAsFilePath)) && (num <= 1))
     {
         if ((num4 != 0) && (dest[start] != '/'))
         {
             num2 = (ushort) (num2 + 1);
             Buffer.BlockCopy(dest, num2 << 1, dest, start << 1, (destLength - num2) << 1);
             destLength -= num2;
             return dest;
         }
         if ((num3 != 0) && ((num2 == (num3 + 1)) || ((num2 == 0) && ((num3 + 1) == destLength))))
         {
             num3 = (ushort) (num3 + ((num2 == 0) ? 0 : 1));
             Buffer.BlockCopy(dest, num3 << 1, dest, start << 1, (destLength - num3) << 1);
             destLength -= num3;
         }
     }
     return dest;
 }
Beispiel #7
0
        //
        // This will compress any "\" "/../" "/./" "///" "/..../" /XXX.../, etc found in the input
        //
        // The passed syntax controls whether to use aggressive compression or the one specified in RFC 2396
        //
        private static char[] Compress(char[] dest, ushort start, ref int destLength, UriParser syntax)
        {
            ushort slashCount = 0;
            ushort lastSlash = 0;
            ushort dotCount = 0;
            ushort removeSegments = 0;

            unchecked
            {
                //ushort i == -1 and start == -1 overflow is ok here
                ushort i = (ushort)((ushort)destLength - (ushort)1);
                start = (ushort)(start - 1);

                for (; i != start; --i)
                {
                    char ch = dest[i];
                    if (ch == '\\' && syntax.InFact(UriSyntaxFlags.ConvertPathSlashes))
                    {
                        dest[i] = ch = '/';
                    }

                    //
                    // compress multiple '/' for file URI
                    //
                    if (ch == '/')
                    {
                        ++slashCount;
                    }
                    else
                    {
                        if (slashCount > 1)
                        {
                            // else preserve repeated slashes
                            lastSlash = (ushort)(i + 1);
                        }
                        slashCount = 0;
                    }

                    if (ch == '.')
                    {
                        ++dotCount;
                        continue;
                    }
                    else if (dotCount != 0)
                    {
                        bool skipSegment = syntax.NotAny(UriSyntaxFlags.CanonicalizeAsFilePath)
                            && (dotCount > 2 || ch != '/' || i == start);

                        //
                        // Cases:
                        // /./                  = remove this segment 
                        // /../                 = remove this segment, mark next for removal
                        // /....x               = DO NOT TOUCH, leave as is
                        // x.../                = DO NOT TOUCH, leave as is, except for V2 legacy mode
                        //
                        if (!skipSegment && ch == '/')
                        {
                            if ((lastSlash == i + dotCount + 1 // "/..../"
                                    || (lastSlash == 0 && i + dotCount + 1 == destLength)) // "/..."
                                && (dotCount <= 2))
                            {
                                //
                                //  /./ or /.<eos> or /../ or /..<eos>
                                //
                                // just reusing a variable slot we perform //dest.Remove(i+1, dotCount + (lastSlash==0?0:1));
                                lastSlash = (ushort)(i + 1 + dotCount + (lastSlash == 0 ? 0 : 1));
                                Buffer.BlockCopy(dest, lastSlash << 1, dest, (i + 1) << 1, (destLength - lastSlash) << 1);
                                destLength -= (lastSlash - i - 1);

                                lastSlash = i;
                                if (dotCount == 2)
                                {
                                    //
                                    // We have 2 dots in between like /../ or /..<eos>,
                                    // Mark next segment for removal and remove this /../ or /..
                                    //
                                    ++removeSegments;
                                }
                                dotCount = 0;
                                continue;
                            }
                        }
                        // .NET 4.5 no longer removes trailing dots in a path segment x.../  or  x...<eos>
                        dotCount = 0;

                        //
                        // Here all other cases go such as
                        // x.[..]y or /.[..]x or (/x.[...][/] && removeSegments !=0)
                    }

                    //
                    // Now we may want to remove a segment because of previous /../
                    //
                    if (ch == '/')
                    {
                        if (removeSegments != 0)
                        {
                            --removeSegments;

                            // just reusing a variable slot we perform //dest.Remove(i+1, lastSlash - i);
                            lastSlash = (ushort)(lastSlash + 1);
                            Buffer.BlockCopy(dest, lastSlash << 1, dest, (i + 1) << 1, (destLength - lastSlash) << 1);
                            destLength -= (lastSlash - i - 1);
                        }
                        lastSlash = i;
                    }
                }

                start = (ushort)((ushort)start + (ushort)1);
            } //end of unchecked

            if ((ushort)destLength > start && syntax.InFact(UriSyntaxFlags.CanonicalizeAsFilePath))
            {
                if (slashCount <= 1)
                {
                    if (removeSegments != 0 && dest[start] != '/')
                    {
                        //remove first not rooted segment
                        lastSlash = (ushort)(lastSlash + 1);
                        Buffer.BlockCopy(dest, lastSlash << 1, dest, start << 1, (destLength - lastSlash) << 1);
                        destLength -= lastSlash;
                    }
                    else if (dotCount != 0)
                    {
                        // If final string starts with a segment looking like .[...]/ or .[...]<eos>
                        // then we remove this first segment
                        if (lastSlash == dotCount + 1 || (lastSlash == 0 && dotCount + 1 == destLength))
                        {
                            dotCount = (ushort)(dotCount + (lastSlash == 0 ? 0 : 1));
                            Buffer.BlockCopy(dest, dotCount << 1, dest, start << 1, (destLength - dotCount) << 1);
                            destLength -= dotCount;
                        }
                    }
                }
            }
            return dest;
        }
Beispiel #8
0
        //
        // Checks the syntax of an authority component. It may also get a userInfo if present
        // Returns an error if no/mailformed authority found
        // Does not NOT touch m_Info
        // Returns position of the Path component
        //
        // Must be called in the ctor only
        private unsafe ushort CheckAuthorityHelper(char* pString, ushort idx, ushort length,
            ref ParsingError err, ref Flags flags, UriParser syntax, ref string newHost)
        {
            int end = length;
            char ch;
            int startInput = idx;
            ushort start = idx;
            newHost = null;
            bool justNormalized = false;
            bool iriParsing = (s_IriParsing && IriParsingStatic(syntax)); // perf
            bool hasUnicode = ((flags & Flags.HasUnicode) != 0); // perf
            bool hostNotUnicodeNormalized = ((flags & Flags.HostUnicodeNormalized) == 0); // perf
            UriSyntaxFlags syntaxFlags = syntax.Flags;

            // need to build new Iri'zed string
            if (hasUnicode && iriParsing && hostNotUnicodeNormalized)
            {
                newHost = _originalUnicodeString.Substring(0, startInput);
            }

            //Special case is an empty authority
            if (idx == length || ((ch = pString[idx]) == '/' || (ch == '\\' && StaticIsFile(syntax)) || ch == '#' || ch == '?'))
            {
                if (syntax.InFact(UriSyntaxFlags.AllowEmptyHost))
                {
                    flags &= ~Flags.UncPath;    //UNC cannot have an empty hostname
                    if (StaticInFact(flags, Flags.ImplicitFile))
                        err = ParsingError.BadHostName;
                    else
                        flags |= Flags.BasicHostType;
                }
                else
                    err = ParsingError.BadHostName;

                if (hasUnicode && iriParsing && hostNotUnicodeNormalized)
                {
                    flags |= Flags.HostUnicodeNormalized;// no host
                }

                return idx;
            }

            string userInfoString = null;
            // Attempt to parse user info first

            if ((syntaxFlags & UriSyntaxFlags.MayHaveUserInfo) != 0)
            {
                for (; start < end; ++start)
                {
                    if (start == end - 1 || pString[start] == '?' || pString[start] == '#' || pString[start] == '\\' ||
                        pString[start] == '/')
                    {
                        start = idx;
                        break;
                    }
                    else if (pString[start] == '@')
                    {
                        flags |= Flags.HasUserInfo;

                        // Iri'ze userinfo
                        if (iriParsing || (s_IdnScope != UriIdnScope.None))
                        {
                            if (iriParsing && hasUnicode && hostNotUnicodeNormalized)
                            {
                                // Normalize user info
                                userInfoString = IriHelper.EscapeUnescapeIri(pString, startInput, start + 1, UriComponents.UserInfo);
                                newHost += userInfoString;
                            }
                            else
                            {
                                userInfoString = new string(pString, startInput, start - startInput + 1);
                            }
                        }
                        ++start;
                        ch = pString[start];
                        break;
                    }
                }
            }

            // DNS name only optimization
            // Fo an overridden parsing the optimization is suppressed since hostname can be changed to anything
            bool dnsNotCanonical = ((syntaxFlags & UriSyntaxFlags.SimpleUserSyntax) == 0);

            if (ch == '[' && syntax.InFact(UriSyntaxFlags.AllowIPv6Host)
                && IPv6AddressHelper.IsValid(pString, (int)start + 1, ref end))
            {
                flags |= Flags.IPv6HostType;

                _iriParsing = (s_IriParsing && IriParsingStatic(syntax));

                if (hasUnicode && iriParsing && hostNotUnicodeNormalized)
                {
                    newHost += new string(pString, start, end - start);
                    flags |= Flags.HostUnicodeNormalized;
                    justNormalized = true;
                }
            }
            else if (ch <= '9' && ch >= '0' && syntax.InFact(UriSyntaxFlags.AllowIPv4Host) &&
                IPv4AddressHelper.IsValid(pString, (int)start, ref end, false, StaticNotAny(flags, Flags.ImplicitFile), syntax.InFact(UriSyntaxFlags.V1_UnknownUri)))
            {
                flags |= Flags.IPv4HostType;

                if (hasUnicode && iriParsing && hostNotUnicodeNormalized)
                {
                    newHost += new string(pString, start, end - start);
                    flags |= Flags.HostUnicodeNormalized;
                    justNormalized = true;
                }
            }
            else if (((syntaxFlags & UriSyntaxFlags.AllowDnsHost) != 0) && !iriParsing &&
           DomainNameHelper.IsValid(pString, start, ref end, ref dnsNotCanonical, StaticNotAny(flags, Flags.ImplicitFile)))
            {
                // comes here if there are only ascii chars in host with original parsing and no Iri

                flags |= Flags.DnsHostType;
                if (!dnsNotCanonical)
                {
                    flags |= Flags.CanonicalDnsHost;
                }

                if ((s_IdnScope != UriIdnScope.None))
                {
                    // check if intranet
                    //
                    if ((s_IdnScope == UriIdnScope.AllExceptIntranet) && IsIntranet(new string(pString, 0, end)))
                    {
                        flags |= Flags.IntranetUri;
                    }
                    if (AllowIdnStatic(syntax, flags))
                    {
                        bool allAscii = true;
                        bool atLeastOneIdn = false;

                        string idnValue = DomainNameHelper.UnicodeEquivalent(pString, start, end, ref allAscii, ref atLeastOneIdn);

                        // did we find at least one valid idn
                        if (atLeastOneIdn)
                        {
                            // need to switch string here since we didn't know beforehand there was an idn host
                            if (StaticNotAny(flags, Flags.HasUnicode))
                                _originalUnicodeString = _string; // lazily switching strings
                            flags |= Flags.IdnHost;

                            // need to build string for this special scenario
                            newHost = _originalUnicodeString.Substring(0, startInput) + userInfoString + idnValue;
                            flags |= Flags.CanonicalDnsHost;
                            _dnsSafeHost = new string(pString, start, end - start);
                            justNormalized = true;
                        }
                        flags |= Flags.HostUnicodeNormalized;
                    }
                }
            }
            else if (((syntaxFlags & UriSyntaxFlags.AllowDnsHost) != 0)
                    && ((syntax.InFact(UriSyntaxFlags.AllowIriParsing) && hostNotUnicodeNormalized)
                            || syntax.InFact(UriSyntaxFlags.AllowIdn))
                    && DomainNameHelper.IsValidByIri(pString, start, ref end, ref dnsNotCanonical,
                                            StaticNotAny(flags, Flags.ImplicitFile)))
            {
                CheckAuthorityHelperHandleDnsIri(pString, start, end, startInput, iriParsing, hasUnicode, syntax,
                    userInfoString, ref flags, ref justNormalized, ref newHost, ref err);
            }
            else if ((syntaxFlags & UriSyntaxFlags.AllowUncHost) != 0)
            {
                //
                // This must remain as the last check before BasicHost type
                //
                if (UncNameHelper.IsValid(pString, start, ref end, StaticNotAny(flags, Flags.ImplicitFile)))
                {
                    if (end - start <= UncNameHelper.MaximumInternetNameLength)
                        flags |= Flags.UncHostType;
                }
            }

            // The deal here is that we won't allow '\' host terminator except for the File scheme
            // If we see '\' we try to make it a part of a Basic host
            if (end < length && pString[end] == '\\' && (flags & Flags.HostTypeMask) != Flags.HostNotParsed
                && !StaticIsFile(syntax))
            {
                if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri))
                {
                    err = ParsingError.BadHostName;
                    flags |= Flags.UnknownHostType;
                    return (ushort)end;
                }
                flags &= ~Flags.HostTypeMask;
            }
            // Here we have checked the syntax up to the end of host
            // The only thing that can cause an exception is the port value
            // Spend some (duplicated) cycles on that.
            else if (end < length && pString[end] == ':')
            {
                if (syntax.InFact(UriSyntaxFlags.MayHavePort))
                {
                    int port = 0;
                    int startPort = end;
                    for (idx = (ushort)(end + 1); idx < length; ++idx)
                    {
                        ushort val = (ushort)((ushort)pString[idx] - (ushort)'0');
                        if ((val >= 0) && (val <= 9))
                        {
                            if ((port = (port * 10 + val)) > 0xFFFF)
                                break;
                        }
                        else if (val == unchecked((ushort)('/' - '0')) || val == (ushort)('?' - '0')
                            || val == unchecked((ushort)('#' - '0')))
                        {
                            break;
                        }
                        else
                        {
                            // The second check is to keep compatibility with V1 until the UriParser is registered
                            if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost)
                                && syntax.NotAny(UriSyntaxFlags.V1_UnknownUri))
                            {
                                flags &= ~Flags.HostTypeMask;
                                break;
                            }
                            else
                            {
                                err = ParsingError.BadPort;
                                return idx;
                            }
                        }
                    }
                    // check on 0-ffff range
                    if (port > 0xFFFF)
                    {
                        if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost))
                        {
                            flags &= ~Flags.HostTypeMask;
                        }
                        else
                        {
                            err = ParsingError.BadPort;
                            return idx;
                        }
                    }

                    if (iriParsing && hasUnicode && justNormalized)
                    {
                        newHost += new string(pString, startPort, idx - startPort);
                    }
                }
                else
                {
                    flags &= ~Flags.HostTypeMask;
                }
            }

            // check on whether nothing has worked out
            if ((flags & Flags.HostTypeMask) == Flags.HostNotParsed)
            {
                //No user info for a Basic hostname
                flags &= ~Flags.HasUserInfo;
                // Some schemes do not allow HostType = Basic (plus V1 almost never understands this issue)
                //
                if (syntax.InFact(UriSyntaxFlags.AllowAnyOtherHost))
                {
                    flags |= Flags.BasicHostType;
                    for (end = idx; end < length; ++end)
                    {
                        if (pString[end] == '/' || (pString[end] == '?' || pString[end] == '#'))
                        {
                            break;
                        }
                    }
                    CheckAuthorityHelperHandleAnyHostIri(pString, startInput, end, iriParsing, hasUnicode, syntax,
                                                            ref flags, ref newHost, ref err);
                }
                else
                {
                    //
                    // ATTN V1 compat: V1 supports hostnames like ".." and ".", and so we do but only for unknown schemes.
                    //
                    if (syntax.InFact(UriSyntaxFlags.V1_UnknownUri))
                    {
                        // Can assert here that the host is not empty so we will set dotFound
                        // at least once or fail before exiting the loop
                        bool dotFound = false;
                        int startOtherHost = idx;
                        for (end = idx; end < length; ++end)
                        {
                            if (dotFound && (pString[end] == '/' || pString[end] == '?' || pString[end] == '#'))
                                break;
                            else if (end < (idx + 2) && pString[end] == '.')
                            {
                                // allow one or two dots
                                dotFound = true;
                            }
                            else
                            {
                                //failure
                                err = ParsingError.BadHostName;
                                flags |= Flags.UnknownHostType;
                                return idx;
                            }
                        }
                        //success
                        flags |= Flags.BasicHostType;

                        if (iriParsing && hasUnicode
                            && StaticNotAny(flags, Flags.HostUnicodeNormalized))
                        {
                            // Normalize any other host
                            string user = new string(pString, startOtherHost, startOtherHost - end);
                            try
                            {
                                newHost += user.Normalize(NormalizationForm.FormC);
                            }
                            catch (ArgumentException)
                            {
                                err = ParsingError.BadFormat;
                                return idx;
                            }

                            flags |= Flags.HostUnicodeNormalized;
                        }
                    }
                    else if (syntax.InFact(UriSyntaxFlags.MustHaveAuthority) ||
                             (syntax.InFact(UriSyntaxFlags.MailToLikeUri)))
                    {
                        err = ParsingError.BadHostName;
                        flags |= Flags.UnknownHostType;
                        return idx;
                    }
                }
            }
            return (ushort)end;
        }
Beispiel #9
0
 //
 // Statically checks if Iri parsing is allowed by the syntax & by config
 //
 internal static bool IriParsingStatic(UriParser syntax)
 {
     return (s_IriParsing && (((syntax != null) && syntax.InFact(UriSyntaxFlags.AllowIriParsing)) ||
            (syntax == null)));
 }