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;
}
_cookieVariant = variant;
}
// Check the name
if (_name == null || _name.Length == 0 || _name[0] == '$' || _name.IndexOfAny(ReservedToName) != -1)
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, "Name", _name == null ? "<null>" : _name));
}
return false;
}
// Check the value
if (_value == null ||
(!(_value.Length > 2 && _value[0] == '\"' && _value[_value.Length - 1] == '\"') && _value.IndexOfAny(ReservedToValue) != -1))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, "Value", _value == null ? "<null>" : _value));
}
return false;
}
// Check Comment syntax
if (Comment != null && !(Comment.Length > 2 && Comment[0] == '\"' && Comment[Comment.Length - 1] == '\"')
&& (Comment.IndexOfAny(ReservedToValue) != -1))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, CommentAttributeName, Comment));
}
return false;
}
// Check Path syntax
if (Path != null && !(Path.Length > 2 && Path[0] == '\"' && Path[Path.Length - 1] == '\"')
&& (Path.IndexOfAny(ReservedToValue) != -1))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, 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 && _domainImplicit == true)
{
_domain = host;
}
else
{
if (!_domainImplicit)
{
// 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 = _domain;
// Syntax check for Domain charset plus empty string.
if (!DomainCharsTest(domain))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, DomainAttributeName, domain == null ? "<null>" : domain));
}
return false;
}
// Domain must start with '.' if set explicitly.
if (domain[0] != '.')
{
if (!(variant == CookieVariant.Rfc2965 || variant == CookieVariant.Plain))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, DomainAttributeName, _domain));
}
return false;
}
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)
{
_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, _domain, StringComparison.OrdinalIgnoreCase))
{
valid = false;
}
}
if (!valid)
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, DomainAttributeName, _domain));
}
return false;
}
}
// Check/Set Path
if (setDefault && _pathImplicit == true)
{
// This code assumes that the URI path is always valid and contains at least one '/'.
switch (_cookieVariant)
{
case CookieVariant.Plain:
_path = path;
break;
case CookieVariant.Rfc2109:
_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.
_path = path.Substring(0, path.LastIndexOf('/') + 1);
break;
}
}
else
{
// Check current path (implicit/explicit) against given URI.
if (!path.StartsWith(CookieParser.CheckQuoted(_path)))
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, PathAttributeName, _path));
}
return false;
}
}
// Set the default port if Port attribute was present but had no value.
if (setDefault && (_portImplicit == false && _port.Length == 0))
{
_portList = new int[1] { port };
}
if (_portImplicit == false)
{
// Port must match against the one from the uri.
valid = false;
foreach (int p in _portList)
{
if (p == port)
{
valid = true;
break;
}
}
if (!valid)
{
if (shouldThrow)
{
throw new CookieException(SR.Format(SR.net_cookie_attribute, PortAttributeName, _port));
}
return false;
}
}
return true;
}