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

📄 http.c

📁 wget讓你可以在console介面下
💻 C
📖 第 1 页 / 共 5 页
字号:
				       u->host, u->port, u->path,#ifdef HAVE_SSL				       u->scheme == SCHEME_HTTPS#else				       0#endif				       ),			rel_value);  if (opt.post_data || opt.post_file_name)    {      request_set_header (req, "Content-Type",			  "application/x-www-form-urlencoded", rel_none);      if (opt.post_data)	post_data_size = strlen (opt.post_data);      else	{	  post_data_size = file_size (opt.post_file_name);	  if (post_data_size == -1)	    {	      logprintf (LOG_NOTQUIET, _("POST data file `%s' missing: %s\n"),			 opt.post_file_name, strerror (errno));	      post_data_size = 0;	    }	}      request_set_header (req, "Content-Length",			  xstrdup (number_to_static_string (post_data_size)),			  rel_value);    }  /* Add the user headers. */  if (opt.user_headers)    {      int i;      for (i = 0; opt.user_headers[i]; i++)	request_set_user_header (req, opt.user_headers[i]);    } retry_with_auth:  /* We need to come back here when the initial attempt to retrieve     without authorization header fails.  (Expected to happen at least     for the Digest authorization scheme.)  */  keep_alive = 0;  /* Establish the connection.  */  if (!inhibit_keep_alive)    {      /* Look for a persistent connection to target host, unless a	 proxy is used.  The exception is when SSL is in use, in which	 case the proxy is nothing but a passthrough to the target	 host, registered as a connection to the latter.  */      struct url *relevant = conn;#ifdef HAVE_SSL      if (u->scheme == SCHEME_HTTPS)	relevant = u;#endif      if (persistent_available_p (relevant->host, relevant->port,#ifdef HAVE_SSL				  relevant->scheme == SCHEME_HTTPS,#else				  0,#endif				  &host_lookup_failed))	{	  sock = pconn.socket;	  using_ssl = pconn.ssl;	  logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"),		     escnonprint (pconn.host), pconn.port);	  DEBUGP (("Reusing fd %d.\n", sock));	  if (pconn.authorized)	    /* If the connection is already authorized, the "Basic"	       authorization added by code above is unnecessary and	       only hurts us.  */	    request_remove_header (req, "Authorization");	}    }  if (sock < 0)    {      /* In its current implementation, persistent_available_p will	 look up conn->host in some cases.  If that lookup failed, we	 don't need to bother with connect_to_host.  */      if (host_lookup_failed)	{	  request_free (req);	  return HOSTERR;	}      sock = connect_to_host (conn->host, conn->port);      if (sock == E_HOST)	{	  request_free (req);	  return HOSTERR;	}      else if (sock < 0)	{	  request_free (req);	  return (retryable_socket_connect_error (errno)		  ? CONERROR : CONIMPOSSIBLE);	}#ifdef HAVE_SSL      if (proxy && u->scheme == SCHEME_HTTPS)	{	  /* When requesting SSL URLs through proxies, use the	     CONNECT method to request passthrough.  */	  struct request *connreq = request_new ();	  request_set_method (connreq, "CONNECT",			      aprintf ("%s:%d", u->host, u->port));	  SET_USER_AGENT (connreq);	  if (proxyauth)	    {	      request_set_header (connreq, "Proxy-Authorization",				  proxyauth, rel_value);	      /* Now that PROXYAUTH is part of the CONNECT request,		 zero it out so we don't send proxy authorization with		 the regular request below.  */	      proxyauth = NULL;	    }	  /* Examples in rfc2817 use the Host header in CONNECT	     requests.  I don't see how that gains anything, given	     that the contents of Host would be exactly the same as	     the contents of CONNECT.  */	  write_error = request_send (connreq, sock);	  request_free (connreq);	  if (write_error < 0)	    {	      CLOSE_INVALIDATE (sock);	      return WRITEFAILED;	    }	  head = read_http_response_head (sock);	  if (!head)	    {	      logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"),			 strerror (errno));	      CLOSE_INVALIDATE (sock);	      return HERR;	    }	  message = NULL;	  if (!*head)	    {	      xfree (head);	      goto failed_tunnel;	    }	  DEBUGP (("proxy responded with: [%s]\n", head));	  resp = resp_new (head);	  statcode = resp_status (resp, &message);	  resp_free (resp);	  xfree (head);	  if (statcode != 200)	    {	    failed_tunnel:	      logprintf (LOG_NOTQUIET, _("Proxy tunneling failed: %s"),			 message ? escnonprint (message) : "?");	      xfree_null (message);	      return CONSSLERR;	    }	  xfree_null (message);	  /* SOCK is now *really* connected to u->host, so update CONN	     to reflect this.  That way register_persistent will	     register SOCK as being connected to u->host:u->port.  */	  conn = u;	}      if (conn->scheme == SCHEME_HTTPS)	{	  if (!ssl_connect (sock) || !ssl_check_certificate (sock, u->host))	    {	      fd_close (sock);	      return CONSSLERR;	    }	  using_ssl = 1;	}#endif /* HAVE_SSL */    }  /* Send the request to server.  */  write_error = request_send (req, sock);  if (write_error >= 0)    {      if (opt.post_data)	{	  DEBUGP (("[POST data: %s]\n", opt.post_data));	  write_error = fd_write (sock, opt.post_data, post_data_size, -1.0);	}      else if (opt.post_file_name && post_data_size != 0)	write_error = post_file (sock, opt.post_file_name, post_data_size);    }  if (write_error < 0)    {      CLOSE_INVALIDATE (sock);      request_free (req);      return WRITEFAILED;    }  logprintf (LOG_VERBOSE, _("%s request sent, awaiting response... "),	     proxy ? "Proxy" : "HTTP");  contlen = -1;  contrange = 0;  *dt &= ~RETROKF;  head = read_http_response_head (sock);  if (!head)    {      if (errno == 0)	{	  logputs (LOG_NOTQUIET, _("No data received.\n"));	  CLOSE_INVALIDATE (sock);	  request_free (req);	  return HEOF;	}      else	{	  logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),		     strerror (errno));	  CLOSE_INVALIDATE (sock);	  request_free (req);	  return HERR;	}    }  DEBUGP (("\n---response begin---\n%s---response end---\n", head));  resp = resp_new (head);  /* Check for status line.  */  message = NULL;  statcode = resp_status (resp, &message);  if (!opt.server_response)    logprintf (LOG_VERBOSE, "%2d %s\n", statcode,	       message ? escnonprint (message) : "");  else    {      logprintf (LOG_VERBOSE, "\n");      print_server_response (resp, "  ");    }  if (!opt.ignore_length      && resp_header_copy (resp, "Content-Length", hdrval, sizeof (hdrval)))    {      wgint parsed;      errno = 0;      parsed = str_to_wgint (hdrval, NULL, 10);      if (parsed == WGINT_MAX && errno == ERANGE)	/* Out of range.	   #### If Content-Length is out of range, it most likely	   means that the file is larger than 2G and that we're	   compiled without LFS.  In that case we should probably	   refuse to even attempt to download the file.  */	contlen = -1;      else	contlen = parsed;    }  /* Check for keep-alive related responses. */  if (!inhibit_keep_alive && contlen != -1)    {      if (resp_header_copy (resp, "Keep-Alive", NULL, 0))	keep_alive = 1;      else if (resp_header_copy (resp, "Connection", hdrval, sizeof (hdrval)))	{	  if (0 == strcasecmp (hdrval, "Keep-Alive"))	    keep_alive = 1;	}    }  if (keep_alive)    /* The server has promised that it will not close the connection       when we're done.  This means that we can register it.  */    register_persistent (conn->host, conn->port, sock, using_ssl);  if (statcode == HTTP_STATUS_UNAUTHORIZED)    {      /* Authorization is required.  */      if (keep_alive && !head_only && skip_short_body (sock, contlen))	CLOSE_FINISH (sock);      else	CLOSE_INVALIDATE (sock);      pconn.authorized = 0;      if (!auth_finished && (user && passwd))	{	  /* IIS sends multiple copies of WWW-Authenticate, one with	     the value "negotiate", and other(s) with data.  Loop over	     all the occurrences and pick the one we recognize.  */	  int wapos;	  const char *wabeg, *waend;	  char *www_authenticate = NULL;	  for (wapos = 0;	       (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos,					    &wabeg, &waend)) != -1;	       ++wapos)	    if (known_authentication_scheme_p (wabeg, waend))	      {		BOUNDED_TO_ALLOCA (wabeg, waend, www_authenticate);		break;	      }	  if (!www_authenticate)	    /* If the authentication header is missing or	       unrecognized, there's no sense in retrying.  */	    logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));	  else if (BEGINS_WITH (www_authenticate, "Basic"))	    /* If the authentication scheme is "Basic", which we send	       by default, there's no sense in retrying either.  (This	       should be changed when we stop sending "Basic" data by	       default.)  */	    ;	  else	    {	      char *pth;	      pth = url_full_path (u);	      request_set_header (req, "Authorization",				  create_authorization_line (www_authenticate,							     user, passwd,							     request_method (req),							     pth,							     &auth_finished),				  rel_value);	      if (BEGINS_WITH (www_authenticate, "NTLM"))		ntlm_seen = 1;	      xfree (pth);	      goto retry_with_auth;	    }	}      logputs (LOG_NOTQUIET, _("Authorization failed.\n"));      request_free (req);      return AUTHFAILED;    }  else /* statcode != HTTP_STATUS_UNAUTHORIZED */    {      /* Kludge: if NTLM is used, mark the TCP connection as authorized. */      if (ntlm_seen)	pconn.authorized = 1;    }  request_free (req);  hs->statcode = statcode;  if (statcode == -1)    hs->error = xstrdup (_("Malformed status line"));  else if (!*message)    hs->error = xstrdup (_("(no description)"));  else    hs->error = xstrdup (message);  xfree_null (message);  type = resp_header_strdup (resp, "Content-Type");  if (type)    {      char *tmp = strchr (type, ';');      if (tmp)	{	  while (tmp > type && ISSPACE (tmp[-1]))	    --tmp;	  *tmp = '\0';	}    }  hs->newloc = resp_header_strdup (resp, "Location");  hs->remote_time = resp_header_strdup (resp, "Last-Modified");  /* Handle (possibly multiple instances of) the Set-Cookie header. */  if (opt.cookies)    {      int scpos;      const char *scbeg, *scend;      /* The jar should have been created by now. */      assert (wget_cookie_jar != NULL);      for (scpos = 0;	   (scpos = resp_header_locate (resp, "Set-Cookie", scpos,					&scbeg, &scend)) != -1;	   ++scpos)	{	  char *set_cookie; BOUNDED_TO_ALLOCA (scbeg, scend, set_cookie);	  cookie_handle_set_cookie (wget_cookie_jar, u->host, u->port,				    u->path, set_cookie);	}    }  if (resp_header_copy (resp, "Content-Range", hdrval, sizeof (hdrval)))    {      wgint first_byte_pos, last_byte_pos, entity_length;      if (parse_content_range (hdrval, &first_byte_pos, &last_byte_pos,			       &entity_length))	contrange = first_byte_pos;    }  resp_free (resp);  /* 20x responses are counted among successful by default.  */  if (H_20X (statcode))    *dt |= RETROKF;  /* Return if redirected.  */  if (H_REDIRECTED (statcode) || statcode == HTTP_STATUS_MULTIPLE_CHOICES)    {      /* RFC2068 says that in case of the 300 (multiple choices)	 response, the server can output a preferred URL through	 `Location' header; otherwise, the request should be treated	 like GET.  So, if the location is set, it will be a	 redirection; otherwise, just proceed normally.  */      if (statcode == HTTP_STATUS_MULTIPLE_CHOICES && !hs->newloc)	*dt |= RETROKF;      else	{	  logprintf (LOG_VERBOSE,		     _("Location: %s%s\n"),		     hs->newloc ? escnonprint_uri (hs->newloc) : _("unspecified"),		     hs->newloc ? _(" [following]") : "");	  if (keep_alive && !head_only && skip_short_body (sock, contlen))	    CLOSE_FINISH (sock);	  else	    CLOSE_INVALIDATE (sock);	  xfree_null (type);	  return NEWLOCATION;	}    }  /* If content-type is not given, assume text/html.  This is because     of the multitude of broken CGI's that "forget" to generate the     content-type.  */  if (!type ||        0 == strncasecmp (type, TEXTHTML_S, strlen (TEXTHTML_S)) ||        0 == strncasecmp (type, TEXTXHTML_S, strlen (TEXTXHTML_S)))    *dt |= TEXTHTML;  else    *dt &= ~TEXTHTML;  if (opt.html_extension && (*dt & TEXTHTML))    /* -E / --html-extension / html_extension = on was specified, and this is a       text/html file.  If some case-insensitive variation on ".htm[l]" isn't       already the file's suffix, tack on ".html". */    {      char *last_period_in_local_filename = strrchr (*hs->local_file, '.');      if (last_period_in_local_filename == NULL	  || !(0 == strcasecmp (last_period_in_local_filename, ".htm")	       || 0 == strcasecmp (last_period_in_local_filename, ".html")))	{	  int local_filename_len = strlen (*hs->local_file);	  /* Resize the local file, allowing for ".html" preceded by	     optional ".NUMBER".  */	  *hs->local_file = xrealloc (*hs->local_file,				      local_filename_len + 24 + sizeof (".html"));	  strcpy(*hs->local_file + local_filename_len, ".html");	  /* If clobbering is not allowed and the file, as named,	     exists, tack on ".NUMBER.html" instead. */	  if (!ALLOW_CLOBBER)

⌨️ 快捷键说明

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