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

📄 http.c

📁 wget讓你可以在console介面下
💻 C
📖 第 1 页 / 共 5 页
字号:
    start = hunk + oldlen - 4;  end = hunk + oldlen + peeklen;  for (; start < end - 1; start++)    if (*start == '\n')      {	if (start < end - 2	    && start[1] == '\r'	    && start[2] == '\n')	  return start + 3;	if (start[1] == '\n')	  return start + 2;      }  return NULL;}/* The maximum size of a single HTTP response we care to read.  This   is not meant to impose an arbitrary limit, but to protect the user   from Wget slurping up available memory upon encountering malicious   or buggy server output.  Define it to 0 to remove the limit.  */#define HTTP_RESPONSE_MAX_SIZE 65536/* Read the HTTP request head from FD and return it.  The error   conditions are the same as with fd_read_hunk.   To support HTTP/0.9 responses, this function tries to make sure   that the data begins with "HTTP".  If this is not the case, no data   is read and an empty request is returned, so that the remaining   data can be treated as body.  */static char *read_http_response_head (int fd){  return fd_read_hunk (fd, response_head_terminator, 512,		       HTTP_RESPONSE_MAX_SIZE);}struct response {  /* The response data. */  const char *data;  /* The array of pointers that indicate where each header starts.     For example, given this HTTP response:       HTTP/1.0 200 Ok       Description: some        text       Etag: x     The headers are located like this:     "HTTP/1.0 200 Ok\r\nDescription: some\r\n text\r\nEtag: x\r\n\r\n"     ^                   ^                             ^          ^     headers[0]          headers[1]                    headers[2] headers[3]     I.e. headers[0] points to the beginning of the request,     headers[1] points to the end of the first header and the     beginning of the second one, etc.  */  const char **headers;};/* Create a new response object from the text of the HTTP response,   available in HEAD.  That text is automatically split into   constituent header lines for fast retrieval using   resp_header_*.  */static struct response *resp_new (const char *head){  const char *hdr;  int count, size;  struct response *resp = xnew0 (struct response);  resp->data = head;  if (*head == '\0')    {      /* Empty head means that we're dealing with a headerless	 (HTTP/0.9) response.  In that case, don't set HEADERS at	 all.  */      return resp;    }  /* Split HEAD into header lines, so that resp_header_* functions     don't need to do this over and over again.  */  size = count = 0;  hdr = head;  while (1)    {      DO_REALLOC (resp->headers, size, count + 1, const char *);      resp->headers[count++] = hdr;      /* Break upon encountering an empty line. */      if (!hdr[0] || (hdr[0] == '\r' && hdr[1] == '\n') || hdr[0] == '\n')	break;      /* Find the end of HDR, including continuations. */      do	{	  const char *end = strchr (hdr, '\n');	  if (end)	    hdr = end + 1;	  else	    hdr += strlen (hdr);	}      while (*hdr == ' ' || *hdr == '\t');    }  DO_REALLOC (resp->headers, size, count + 1, const char *);  resp->headers[count] = NULL;  return resp;}/* Locate the header named NAME in the request data, starting with   position START.  This allows the code to loop through the request   data, filtering for all requests of a given name.  Returns the   found position, or -1 for failure.  The code that uses this   function typically looks like this:     for (pos = 0; (pos = resp_header_locate (...)) != -1; pos++)       ... do something with header ...   If you only care about one header, use resp_header_get instead of   this function.  */static intresp_header_locate (const struct response *resp, const char *name, int start,		    const char **begptr, const char **endptr){  int i;  const char **headers = resp->headers;  int name_len;  if (!headers || !headers[1])    return -1;  name_len = strlen (name);  if (start > 0)    i = start;  else    i = 1;  for (; headers[i + 1]; i++)    {      const char *b = headers[i];      const char *e = headers[i + 1];      if (e - b > name_len	  && b[name_len] == ':'	  && 0 == strncasecmp (b, name, name_len))	{	  b += name_len + 1;	  while (b < e && ISSPACE (*b))	    ++b;	  while (b < e && ISSPACE (e[-1]))	    --e;	  *begptr = b;	  *endptr = e;	  return i;	}    }  return -1;}/* Find and retrieve the header named NAME in the request data.  If   found, set *BEGPTR to its starting, and *ENDPTR to its ending   position, and return 1.  Otherwise return 0.   This function is used as a building block for resp_header_copy   and resp_header_strdup.  */static intresp_header_get (const struct response *resp, const char *name,		 const char **begptr, const char **endptr){  int pos = resp_header_locate (resp, name, 0, begptr, endptr);  return pos != -1;}/* Copy the response header named NAME to buffer BUF, no longer than   BUFSIZE (BUFSIZE includes the terminating 0).  If the header   exists, 1 is returned, otherwise 0.  If there should be no limit on   the size of the header, use resp_header_strdup instead.   If BUFSIZE is 0, no data is copied, but the boolean indication of   whether the header is present is still returned.  */static intresp_header_copy (const struct response *resp, const char *name,		  char *buf, int bufsize){  const char *b, *e;  if (!resp_header_get (resp, name, &b, &e))    return 0;  if (bufsize)    {      int len = MIN (e - b, bufsize - 1);      memcpy (buf, b, len);      buf[len] = '\0';    }  return 1;}/* Return the value of header named NAME in RESP, allocated with   malloc.  If such a header does not exist in RESP, return NULL.  */static char *resp_header_strdup (const struct response *resp, const char *name){  const char *b, *e;  if (!resp_header_get (resp, name, &b, &e))    return NULL;  return strdupdelim (b, e);}/* Parse the HTTP status line, which is of format:   HTTP-Version SP Status-Code SP Reason-Phrase   The function returns the status-code, or -1 if the status line   appears malformed.  The pointer to "reason-phrase" message is   returned in *MESSAGE.  */static intresp_status (const struct response *resp, char **message){  int status;  const char *p, *end;  if (!resp->headers)    {      /* For a HTTP/0.9 response, assume status 200. */      if (message)	*message = xstrdup (_("No headers, assuming HTTP/0.9"));      return 200;    }  p = resp->headers[0];  end = resp->headers[1];  if (!end)    return -1;  /* "HTTP" */  if (end - p < 4 || 0 != strncmp (p, "HTTP", 4))    return -1;  p += 4;  /* Match the HTTP version.  This is optional because Gnutella     servers have been reported to not specify HTTP version.  */  if (p < end && *p == '/')    {      ++p;      while (p < end && ISDIGIT (*p))	++p;      if (p < end && *p == '.')	++p;       while (p < end && ISDIGIT (*p))	++p;    }  while (p < end && ISSPACE (*p))    ++p;  if (end - p < 3 || !ISDIGIT (p[0]) || !ISDIGIT (p[1]) || !ISDIGIT (p[2]))    return -1;  status = 100 * (p[0] - '0') + 10 * (p[1] - '0') + (p[2] - '0');  p += 3;  if (message)    {      while (p < end && ISSPACE (*p))	++p;      while (p < end && ISSPACE (end[-1]))	--end;      *message = strdupdelim (p, end);    }  return status;}/* Release the resources used by RESP.  */static voidresp_free (struct response *resp){  xfree_null (resp->headers);  xfree (resp);}/* Print the server response, line by line, omitting the trailing CRLF   from individual header lines, and prefixed with PREFIX.  */static voidprint_server_response (const struct response *resp, const char *prefix){  int i;  if (!resp->headers)    return;  for (i = 0; resp->headers[i + 1]; i++)    {      const char *b = resp->headers[i];      const char *e = resp->headers[i + 1];      /* Skip CRLF */      if (b < e && e[-1] == '\n')	--e;      if (b < e && e[-1] == '\r')	--e;      /* This is safe even on printfs with broken handling of "%.<n>s"	 because resp->headers ends with \0.  */      logprintf (LOG_VERBOSE, "%s%.*s\n", prefix, e - b, b);    }}/* Parse the `Content-Range' header and extract the information it   contains.  Returns 1 if successful, -1 otherwise.  */static intparse_content_range (const char *hdr, wgint *first_byte_ptr,		     wgint *last_byte_ptr, wgint *entity_length_ptr){  wgint num;  /* Ancient versions of Netscape proxy server, presumably predating     rfc2068, sent out `Content-Range' without the "bytes"     specifier.  */  if (!strncasecmp (hdr, "bytes", 5))    {      hdr += 5;      /* "JavaWebServer/1.1.1" sends "bytes: x-y/z", contrary to the	 HTTP spec. */      if (*hdr == ':')	++hdr;      while (ISSPACE (*hdr))	++hdr;      if (!*hdr)	return 0;    }  if (!ISDIGIT (*hdr))    return 0;  for (num = 0; ISDIGIT (*hdr); hdr++)    num = 10 * num + (*hdr - '0');  if (*hdr != '-' || !ISDIGIT (*(hdr + 1)))    return 0;  *first_byte_ptr = num;  ++hdr;  for (num = 0; ISDIGIT (*hdr); hdr++)    num = 10 * num + (*hdr - '0');  if (*hdr != '/' || !ISDIGIT (*(hdr + 1)))    return 0;  *last_byte_ptr = num;  ++hdr;  for (num = 0; ISDIGIT (*hdr); hdr++)    num = 10 * num + (*hdr - '0');  *entity_length_ptr = num;  return 1;}/* Read the body of the request, but don't store it anywhere and don't   display a progress gauge.  This is useful for reading the bodies of   administrative responses to which we will soon issue another   request.  The response is not useful to the user, but reading it   allows us to continue using the same connection to the server.   If reading fails, 0 is returned, non-zero otherwise.  In debug   mode, the body is displayed for debugging purposes.  */static intskip_short_body (int fd, wgint contlen){  enum {    SKIP_SIZE = 512,		/* size of the download buffer */    SKIP_THRESHOLD = 4096	/* the largest size we read */  };  char dlbuf[SKIP_SIZE + 1];  dlbuf[SKIP_SIZE] = '\0';	/* so DEBUGP can safely print it */  /* We shouldn't get here with unknown contlen.  (This will change     with HTTP/1.1, which supports "chunked" transfer.)  */  assert (contlen != -1);  /* If the body is too large, it makes more sense to simply close the     connection than to try to read the body.  */  if (contlen > SKIP_THRESHOLD)    return 0;  DEBUGP (("Skipping %s bytes of body: [", number_to_static_string (contlen)));  while (contlen > 0)    {      int ret = fd_read (fd, dlbuf, MIN (contlen, SKIP_SIZE), -1.0);      if (ret <= 0)	{	  /* Don't normally report the error since this is an	     optimization that should be invisible to the user.  */	  DEBUGP (("] aborting (%s).\n",		   ret < 0 ? strerror (errno) : "EOF received"));	  return 0;	}      contlen -= ret;      /* Safe even if %.*s bogusly expects terminating \0 because	 we've zero-terminated dlbuf above.  */      DEBUGP (("%.*s", ret, dlbuf));    }  DEBUGP (("] done.\n"));  return 1;}/* Persistent connections.  Currently, we cache the most recently used   connection as persistent, provided that the HTTP server agrees to   make it such.  The persistence data is stored in the variables   below.  Ideally, it should be possible to cache an arbitrary fixed   number of these connections.  *//* Whether a persistent connection is active. */static int pconn_active;static struct {  /* The socket of the connection.  */  int socket;  /* Host and port of the currently active persistent connection. */  char *host;  int port;  /* Whether a ssl handshake has occoured on this connection.  */  int ssl;  /* Whether the connection was authorized.  This is only done by     NTLM, which authorizes *connections* rather than individual     requests.  (That practice is peculiar for HTTP, but it is a     useful optimization.)  */  int authorized;#ifdef ENABLE_NTLM  /* NTLM data of the current connection.  */  struct ntlmdata ntlm;#endif} pconn;/* Mark the persistent connection as invalid and free the resources it   uses.  This is used by the CLOSE_* macros after they forcefully   close a registered persistent connection.  */static voidinvalidate_persistent (void){  DEBUGP (("Disabling further reuse of socket %d.\n", pconn.socket));  pconn_active = 0;

⌨️ 快捷键说明

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