Пример #1
0
        public override bool TryFormat(Span <char> span)
        {
            var isCommentNull = string.IsNullOrWhiteSpace(Comment);
            var len           = NameSize +
                                RawValue.AsSpan().StringSizeWithQuoteReplacement(0) + 2;

            if (span.Length < EntrySizeInBytes)
            {
                return(false);
            }

            span.Slice(0, EntrySizeInBytes).Fill(' ');
            Name.AsSpan().CopyTo(span);
            //span[EqualsPos] = '=';

            if (!RawValue.AsSpan().TryGetCompatibleString(span.Slice(ValueStart), 0))
            {
                span.Slice(0, EntrySizeInBytes).Fill(' ');
                return(false);
            }


            if (isCommentNull)
            {
                return(true);
            }

            Comment.AsSpan().CopyTo(span.Slice(len + 2));
            span[len + 1] = '/';

            return(true);
        }
Пример #2
0
        public override bool TryFormat(Span <char> span)
        {
            if (span.Length < EntrySizeInBytes)
            {
                return(false);
            }

            var isCommentNull = string.IsNullOrWhiteSpace(Comment);

            span.Slice(0, EntrySizeInBytes).Fill(' ');
            Name.AsSpan().CopyTo(span);

            if (isCommentNull)
            {
                return(true);
            }

            //Comment.AsSpan().CopyTo(span.Slice(ValueStart));
            // This accounts for the absence of `= ` in special keys
            Comment.AsSpan().CopyTo(span.Slice(ValueStart - 1));

            return(true);
        }
Пример #3
0
        // According to spec we must assume default values for attributes but still
        // keep in mind that we must not include them into the requests.
        // We also check the validity of all attributes based on the version and variant (read RFC)
        //
        // To work properly this function must be called after cookie construction with
        // default (response) URI AND setDefault == true
        //
        // Afterwards, the function can be called many times with other URIs and
        // setDefault == false to check whether this cookie matches given uri
        internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDomain, string localDomain, bool setDefault, bool shouldThrow)
        {
            string host  = uri.Host;
            int    port  = uri.Port;
            string path  = uri.AbsolutePath;
            bool   valid = true;

            if (setDefault)
            {
                // Set Variant. If version is zero => reset cookie to Version0 style
                if (Version == 0)
                {
                    variant = CookieVariant.Plain;
                }
                else if (Version == 1 && variant == CookieVariant.Unknown)
                {
                    // Since we don't expose Variant to an app, set it to Default
                    variant = CookieVariant.Default;
                }
                m_cookieVariant = variant;
            }

            // Check the name
            if (string.IsNullOrEmpty(m_name) ||
                m_name.StartsWith('$') ||
                m_name.StartsWith(' ') ||
                m_name.EndsWith(' ') ||
                m_name.AsSpan().IndexOfAny(ReservedToName) >= 0)
            {
                if (shouldThrow)
                {
                    throw new CookieException(SR.Format(SR.net_cookie_attribute, "Name", m_name ?? "<null>"));
                }
                return(false);
            }

            // Check the value
            if (m_value == null ||
                (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.AsSpan().IndexOfAny(';', ',') >= 0))
            {
                if (shouldThrow)
                {
                    throw new CookieException(SR.Format(SR.net_cookie_attribute, "Value", m_value ?? "<null>"));
                }
                return(false);
            }

            // Check Comment syntax
            if (Comment != null && !(Comment.Length > 2 && Comment.StartsWith('\"') && Comment.EndsWith('\"')) &&
                (Comment.AsSpan().IndexOfAny(';', ',') >= 0))
            {
                if (shouldThrow)
                {
                    throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.CommentAttributeName, Comment));
                }
                return(false);
            }

            // Check Path syntax
            if (Path != null && !(Path.Length > 2 && Path.StartsWith('\"') && Path.EndsWith('\"')) &&
                (Path.AsSpan().IndexOfAny(';', ',') != -1))
            {
                if (shouldThrow)
                {
                    throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PathAttributeName, Path));
                }
                return(false);
            }

            // Check/set domain
            //
            // If domain is implicit => assume a) uri is valid, b) just set domain to uri hostname.
            if (setDefault && m_domain_implicit)
            {
                m_domain = host;
            }
            else
            {
                if (!m_domain_implicit)
                {
                    // Forwarding note: If Uri.Host is of IP address form then the only supported case
                    // is for IMPLICIT domain property of a cookie.
                    // The code below (explicit cookie.Domain value) will try to parse Uri.Host IP string
                    // as a fqdn and reject the cookie.

                    // Aliasing since we might need the KeyValue (but not the original one).
                    string domain = m_domain;

                    // Syntax check for Domain charset plus empty string.
                    if (!DomainCharsTest(domain))
                    {
                        if (shouldThrow)
                        {
                            throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.DomainAttributeName, domain ?? "<null>"));
                        }
                        return(false);
                    }

                    // Domain must start with '.' if set explicitly.
                    if (domain[0] != '.')
                    {
                        domain = '.' + domain;
                    }

                    int host_dot = host.IndexOf('.');

                    // First quick check is for pushing a cookie into the local domain.
                    if (isLocalDomain && string.Equals(localDomain, domain, StringComparison.OrdinalIgnoreCase))
                    {
                        valid = true;
                    }
                    else if (domain.IndexOf('.', 1, domain.Length - 2) == -1)
                    {
                        // A single label domain is valid only if the domain is exactly the same as the host specified in the URI.
                        if (!IsDomainEqualToHost(domain, host))
                        {
                            valid = false;
                        }
                    }
                    else if (variant == CookieVariant.Plain)
                    {
                        // We distinguish between Version0 cookie and other versions on domain issue.
                        // According to Version0 spec a domain must be just a substring of the hostname.

                        if (!IsDomainEqualToHost(domain, host))
                        {
                            if (host.Length <= domain.Length ||
                                (string.Compare(host, host.Length - domain.Length, domain, 0, domain.Length, StringComparison.OrdinalIgnoreCase) != 0))
                            {
                                valid = false;
                            }
                        }
                    }
                    else if (host_dot == -1 ||
                             domain.Length != host.Length - host_dot ||
                             (string.Compare(host, host_dot, domain, 0, domain.Length, StringComparison.OrdinalIgnoreCase) != 0))
                    {
                        // Starting from the first dot, the host must match the domain.
                        //
                        // For null hosts, the host must match the domain exactly.
                        if (!IsDomainEqualToHost(domain, host))
                        {
                            valid = false;
                        }
                    }

                    if (valid)
                    {
                        m_domainKey = domain.ToLowerInvariant();
                    }
                }
                else
                {
                    // For implicitly set domain AND at the set_default == false time
                    // we simply need to match uri.Host against m_domain.
                    if (!string.Equals(host, m_domain, StringComparison.OrdinalIgnoreCase))
                    {
                        valid = false;
                    }
                }
                if (!valid)
                {
                    if (shouldThrow)
                    {
                        throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.DomainAttributeName, m_domain));
                    }
                    return(false);
                }
            }

            // Check/Set Path
            if (setDefault && m_path_implicit)
            {
                // This code assumes that the URI path is always valid and contains at least one '/'.
                switch (m_cookieVariant)
                {
                case CookieVariant.Plain:
                    // As per RFC6265 5.1.4. (https://tools.ietf.org/html/rfc6265#section-5.1.4):
                    // | 2. If the uri-path is empty or if the first character of the uri-
                    // |    path is not a %x2F ("/") character, output %x2F ("/") and skip
                    // |    the remaining steps.
                    // | 3. If the uri-path contains no more than one %x2F ("/") character,
                    // |    output %x2F ("/") and skip the remaining step.
                    // Note: Normally Uri.AbsolutePath contains at least one "/" after parsing,
                    //       but it's possible construct Uri with an empty path using a custom UriParser
                    int lastSlash;
                    if (!path.StartsWith('/') || (lastSlash = path.LastIndexOf('/')) == 0)
                    {
                        m_path = "/";
                        break;
                    }

                    // | 4. Output the characters of the uri-path from the first character up
                    // |    to, but not including, the right-most %x2F ("/").
                    m_path = path.Substring(0, lastSlash);
                    break;

                case CookieVariant.Rfc2109:
                    m_path = path.Substring(0, path.LastIndexOf('/'));     // May be empty
                    break;

                case CookieVariant.Rfc2965:
                default:
                    // NOTE: this code is not resilient against future versions with different 'Path' semantics.
                    m_path = path.Substring(0, path.LastIndexOf('/') + 1);
                    break;
                }
            }

            // Set the default port if Port attribute was present but had no value.
            if (setDefault && (m_port_implicit == false && m_port.Length == 0))
            {
                m_port_list = new int[1] {
                    port
                };
            }

            if (m_port_implicit == false)
            {
                // Port must match against the one from the uri.
                valid = false;
                foreach (int p in m_port_list !)
                {
                    if (p == port)
                    {
                        valid = true;
                        break;
                    }
                }
                if (!valid)
                {
                    if (shouldThrow)
                    {
                        throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, m_port));
                    }
                    return(false);
                }
            }
            return(true);
        }