⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cookies.c

📁 wget讓你可以在console介面下
💻 C
📖 第 1 页 / 共 4 页
字号:
      /* According to netscape's specification, expiry time in the	 past means that discarding of a matching cookie is	 requested.  */      if (cookie->expiry_time < cookies_now)	cookie->discard_requested = 1;      return 1;    }  else if (NAME_IS ("max-age"))    {      double maxage = -1;      char *value_copy;      if (!VALUE_NON_EMPTY)	return 0;      BOUNDED_TO_ALLOCA (value_b, value_e, value_copy);      sscanf (value_copy, "%lf", &maxage);      if (maxage == -1)	/* something went wrong. */	return 0;      cookie->permanent = 1;      cookie->expiry_time = cookies_now + maxage;      /* According to rfc2109, a cookie with max-age of 0 means that	 discarding of a matching cookie is requested.  */      if (maxage == 0)	cookie->discard_requested = 1;      return 1;    }  else if (NAME_IS ("secure"))    {      /* ignore value completely */      cookie->secure = 1;      return 1;    }  else    /* Unrecognized attribute; ignore it. */    return 1;}#undef NAME_IS/* Returns non-zero for characters that are legal in the name of an   attribute.  This used to allow only alphanumerics, '-', and '_',   but we need to be more lenient because a number of sites wants to   use weirder attribute names.  rfc2965 "informally specifies"   attribute name (token) as "a sequence of non-special, non-white   space characters".  So we allow everything except the stuff we know   could harm us.  */#define ATTR_NAME_CHAR(c) ((c) > 32 && (c) < 127	\			   && (c) != '"' && (c) != '='	\			   && (c) != ';' && (c) != ',')/* Parse the contents of the `Set-Cookie' header.  The header looks   like this:   name1=value1; name2=value2; ...   Trailing semicolon is optional; spaces are allowed between all   tokens.  Additionally, values may be quoted.   A new cookie is returned upon success, NULL otherwise.  The   specified CALLBACK function (normally `update_cookie_field' is used   to update the fields of the newly created cookie structure.  */static struct cookie *parse_set_cookies (const char *sc,		   int (*callback) (struct cookie *,				    const char *, const char *,				    const char *, const char *),		   int silent){  struct cookie *cookie = cookie_new ();  /* #### Hand-written DFAs are no fun to debug.  We'de be better off     to rewrite this as an inline parser.  */  enum { S_START, S_NAME, S_NAME_POST,	 S_VALUE_PRE, S_VALUE, S_QUOTED_VALUE, S_VALUE_TRAILSPACE,	 S_ATTR_ACTION, S_DONE, S_ERROR  } state = S_START;  const char *p = sc;  char c;  const char *name_b  = NULL, *name_e  = NULL;  const char *value_b = NULL, *value_e = NULL;  c = *p;  while (state != S_DONE && state != S_ERROR)    {      switch (state)	{	case S_START:	  if (!c)	    state = S_DONE;	  else if (ISSPACE (c))	    /* Strip all whitespace preceding the name. */	    c = *++p;	  else if (ATTR_NAME_CHAR (c))	    {	      name_b = p;	      state = S_NAME;	    }	  else	    /* empty attr name not allowed */	    state = S_ERROR;	  break;	case S_NAME:	  if (!c || c == ';' || c == '=' || ISSPACE (c))	    {	      name_e = p;	      state = S_NAME_POST;	    }	  else if (ATTR_NAME_CHAR (c))	    c = *++p;	  else	    state = S_ERROR;	  break;	case S_NAME_POST:	  if (!c || c == ';')	    {	      value_b = value_e = NULL;	      if (c == ';')		c = *++p;	      state = S_ATTR_ACTION;	    }	  else if (c == '=')	    {	      c = *++p;	      state = S_VALUE_PRE;	    }	  else if (ISSPACE (c))	    /* Ignore space and keep the state. */	    c = *++p;	  else	    state = S_ERROR;	  break;	case S_VALUE_PRE:	  if (!c || c == ';')	    {	      value_b = value_e = p;	      if (c == ';')		c = *++p;	      state = S_ATTR_ACTION;	    }	  else if (c == '"')	    {	      c = *++p;	      value_b = p;	      state = S_QUOTED_VALUE;	    }	  else if (ISSPACE (c))	    c = *++p;	  else	    {	      value_b = p;	      value_e = NULL;	      state = S_VALUE;	    }	  break;	case S_VALUE:	  if (!c || c == ';' || ISSPACE (c))	    {	      value_e = p;	      state = S_VALUE_TRAILSPACE;	    }	  else	    {	      value_e = NULL;	/* no trailing space */	      c = *++p;	    }	  break;	case S_QUOTED_VALUE:	  if (c == '"')	    {	      value_e = p;	      c = *++p;	      state = S_VALUE_TRAILSPACE;	    }	  else if (!c)	    state = S_ERROR;	  else	    c = *++p;	  break;	case S_VALUE_TRAILSPACE:	  if (c == ';')	    {	      c = *++p;	      state = S_ATTR_ACTION;	    }	  else if (!c)	    state = S_ATTR_ACTION;	  else if (ISSPACE (c))	    c = *++p;	  else	    state = S_VALUE;	  break;	case S_ATTR_ACTION:	  {	    int legal = callback (cookie, name_b, name_e, value_b, value_e);	    if (!legal)	      {		if (!silent)		  {		    char *name;		    BOUNDED_TO_ALLOCA (name_b, name_e, name);		    logprintf (LOG_NOTQUIET,			       _("Error in Set-Cookie, field `%s'"),			       escnonprint (name));		  }		state = S_ERROR;		break;	      }	    state = S_START;	  }	  break;	case S_DONE:	case S_ERROR:	  /* handled by loop condition */	  break;	}    }  if (state == S_DONE)    return cookie;  delete_cookie (cookie);  if (state != S_ERROR)    abort ();  if (!silent)    logprintf (LOG_NOTQUIET,	       _("Syntax error in Set-Cookie: %s at position %d.\n"),	       escnonprint (sc), (int) (p - sc));  return NULL;}/* Sanity checks.  These are important, otherwise it is possible for   mailcious attackers to destroy important cookie information and/or   violate your privacy.  */#define REQUIRE_DIGITS(p) do {			\  if (!ISDIGIT (*p))				\    return 0;					\  for (++p; ISDIGIT (*p); p++)			\    ;						\} while (0)#define REQUIRE_DOT(p) do {			\  if (*p++ != '.')				\    return 0;					\} while (0)/* Check whether ADDR matches <digits>.<digits>.<digits>.<digits>.   We don't want to call network functions like inet_addr() because   all we need is a check, preferrably one that is small, fast, and   well-defined.  */static intnumeric_address_p (const char *addr){  const char *p = addr;  REQUIRE_DIGITS (p);		/* A */  REQUIRE_DOT (p);		/* . */  REQUIRE_DIGITS (p);		/* B */  REQUIRE_DOT (p);		/* . */  REQUIRE_DIGITS (p);		/* C */  REQUIRE_DOT (p);		/* . */  REQUIRE_DIGITS (p);		/* D */  if (*p != '\0')    return 0;  return 1;}/* Check whether COOKIE_DOMAIN is an appropriate domain for HOST.   Originally I tried to make the check compliant with rfc2109, but   the sites deviated too often, so I had to fall back to "tail   matching", as defined by the original Netscape's cookie spec.  */static intcheck_domain_match (const char *cookie_domain, const char *host){  DEBUGP (("cdm: 1"));  /* Numeric address requires exact match.  It also requires HOST to     be an IP address.  */  if (numeric_address_p (cookie_domain))    return 0 == strcmp (cookie_domain, host);  DEBUGP ((" 2"));  /* For the sake of efficiency, check for exact match first. */  if (0 == strcasecmp (cookie_domain, host))    return 1;  DEBUGP ((" 3"));  /* HOST must match the tail of cookie_domain. */  if (!match_tail (host, cookie_domain, 1))    return 0;  /* We know that COOKIE_DOMAIN is a subset of HOST; however, we must     make sure that somebody is not trying to set the cookie for a     subdomain shared by many entities.  For example, "company.co.uk"     must not be allowed to set a cookie for ".co.uk".  On the other     hand, "sso.redhat.de" should be able to set a cookie for     ".redhat.de".     The only marginally sane way to handle this I can think of is to     reject on the basis of the length of the second-level domain name     (but when the top-level domain is unknown), with the assumption     that those of three or less characters could be reserved.  For     example:          .co.org -> works because the TLD is known           .co.uk -> doesn't work because "co" is only two chars long          .com.au -> doesn't work because "com" is only 3 chars long          .cnn.uk -> doesn't work because "cnn" is also only 3 chars long (ugh)          .cnn.de -> doesn't work for the same reason (ugh!!)         .abcd.de -> works because "abcd" is 4 chars long      .img.cnn.de -> works because it's not trying to set the 2nd level domain       .cnn.co.uk -> works for the same reason    That should prevent misuse, while allowing reasonable usage.  If    someone knows of a better way to handle this, please let me    know.  */  {    const char *p = cookie_domain;    int dccount = 1;		/* number of domain components */    int ldcl  = 0;		/* last domain component length */    int nldcl = 0;		/* next to last domain component length */    int out;    if (*p == '.')      /* Ignore leading period in this calculation. */      ++p;    DEBUGP ((" 4"));    for (out = 0; !out; p++)      switch (*p)	{	case '\0':	  out = 1;	  break;	case '.':	  if (ldcl == 0)	    /* Empty domain component found -- the domain is invalid. */	    return 0;	  if (*(p + 1) == '\0')	    {	      /* Tolerate trailing '.' by not treating the domain as		 one ending with an empty domain component.  */	      out = 1;	      break;	    }	  nldcl = ldcl;	  ldcl  = 0;	  ++dccount;	  break;	default:	  ++ldcl;	}    DEBUGP ((" 5"));    if (dccount < 2)      return 0;    DEBUGP ((" 6"));    if (dccount == 2)      {	int i;	int known_toplevel = 0;	static const char *known_toplevel_domains[] = {	  ".com", ".edu", ".net", ".org", ".gov", ".mil", ".int"	};	for (i = 0; i < countof (known_toplevel_domains); i++)	  if (match_tail (cookie_domain, known_toplevel_domains[i], 1))	    {	      known_toplevel = 1;	      break;	    }	if (!known_toplevel && nldcl <= 3)	  return 0;      }  }  DEBUGP ((" 7"));  /* Don't allow the host "foobar.com" to set a cookie for domain     "bar.com".  */  if (*cookie_domain != '.')    {      int dlen = strlen (cookie_domain);      int hlen = strlen (host);      /* cookie host:    hostname.foobar.com */      /* desired domain:             bar.com */      /* '.' must be here in host-> ^        */      if (hlen > dlen && host[hlen - dlen - 1] != '.')

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -