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

📄 http.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	BStrCat0(command, crlf);	/* Blank line means "end" of headers */	BStrCat(command, anAnchor->post_data);    }    else	BStrCat0(command, crlf);	/* Blank line means "end" of headers */    if (TRACE) {	CTRACE((tfp, "Writing:\n"));	trace_bstring(command);#ifdef USE_SSL	CTRACE((tfp, "%s",	       (anAnchor->post_data && !do_connect ? crlf : "")));#else	CTRACE((tfp, "%s",	       (anAnchor->post_data ? crlf : "")));#endif /* USE_SSL */	CTRACE((tfp, "----------------------------------\n"));    }  _HTProgress (gettext("Sending HTTP request."));#ifdef    NOT_ASCII  /* S/390 -- gil -- 0548 */  {   char *p;      for ( p = BStrData(command); p < BStrData(command) + BStrLen(command); p++ )	  *p = TOASCII(*p);  }#endif /* NOT_ASCII */  status = HTTP_NETWRITE(s, BStrData(command), BStrLen(command), handle);  BStrFree(command);  FREE(linebuf);  if (status <= 0) {      if (status == 0) {	  CTRACE((tfp, "HTTP: Got status 0 in initial write\n"));	  /* Do nothing. */      } else if ((SOCKET_ERRNO == ENOTCONN ||		  SOCKET_ERRNO == ECONNRESET ||		  SOCKET_ERRNO == EPIPE) &&		 !already_retrying &&		 /* Don't retry if we're posting. */ !do_post) {	    /*	    **	Arrrrgh, HTTP 0/1 compatibility problem, maybe.	    */	    CTRACE((tfp, "HTTP: BONZO ON WRITE Trying again with HTTP0 request.\n"));	    _HTProgress (RETRYING_AS_HTTP0);	    HTTP_NETCLOSE(s, handle);	    extensions = NO;	    already_retrying = TRUE;	    goto try_again;      } else {	  CTRACE((tfp, "HTTP: Hit unexpected network WRITE error; aborting connection.\n"));	  HTTP_NETCLOSE(s, handle);	  status = -1;	  HTAlert(gettext("Unexpected network write error; connection aborted."));	  goto done;      }  }  CTRACE((tfp, "HTTP: WRITE delivered OK\n"));  _HTProgress (gettext("HTTP request sent; waiting for response."));  /*	Read the first line of the response  **	-----------------------------------  */  {    /* Get numeric status etc */    BOOL end_of_file = NO;    int buffer_length = INIT_LINE_SIZE;    line_buffer = typecallocn(char, buffer_length);    if (line_buffer == NULL)	outofmem(__FILE__, "HTLoadHTTP");    HTReadProgress (bytes_already_read = 0, 0);    do {/* Loop to read in the first line */	/*	**  Extend line buffer if necessary for those crazy WAIS URLs ;-)	*/	if (buffer_length - length < LINE_EXTEND_THRESH) {	    buffer_length = buffer_length + buffer_length;	    line_buffer =	      (char *)realloc(line_buffer, (buffer_length * sizeof(char)));	    if (line_buffer == NULL)		outofmem(__FILE__, "HTLoadHTTP");	}	CTRACE((tfp, "HTTP: Trying to read %d\n", buffer_length - length - 1));	status = HTTP_NETREAD(s, line_buffer + length,			      buffer_length - length - 1, handle);	CTRACE((tfp, "HTTP: Read %d\n", status));	if (status <= 0) {	    /*	     *	Retry if we get nothing back too.	     *	Bomb out if we get nothing twice.	     */	    if (status == HT_INTERRUPTED) {		CTRACE((tfp, "HTTP: Interrupted initial read.\n"));		_HTProgress (CONNECTION_INTERRUPTED);		HTTP_NETCLOSE(s, handle);		status = HT_NO_DATA;		goto clean_up;	    } else if  (status < 0 &&			(SOCKET_ERRNO == ENOTCONN ||#ifdef _WINDOWS	/* 1997/11/09 (Sun) 16:59:58 */			 SOCKET_ERRNO == ETIMEDOUT ||#endif			 SOCKET_ERRNO == ECONNRESET ||			 SOCKET_ERRNO == EPIPE) &&			!already_retrying && !do_post) {		/*		**  Arrrrgh, HTTP 0/1 compability problem, maybe.		*/		CTRACE((tfp, "HTTP: BONZO Trying again with HTTP0 request.\n"));		HTTP_NETCLOSE(s, handle);		FREE(line_buffer);		FREE(line_kept_clean);		extensions = NO;		already_retrying = TRUE;		_HTProgress (RETRYING_AS_HTTP0);		goto try_again;	    } else {		CTRACE((tfp, "HTTP: Hit unexpected network read error; aborting connection; status %d.\n",			   status));		HTAlert(gettext("Unexpected network read error; connection aborted."));		HTTP_NETCLOSE(s, handle);		status = -1;		goto clean_up;	    }	}#ifdef    NOT_ASCII  /* S/390 -- gil -- 0564 */	{   char *p;	    for ( p = line_buffer + length; p < line_buffer + length + status; p++ )		*p = FROMASCII(*p);	}#endif /* NOT_ASCII */	bytes_already_read += status;	HTReadProgress (bytes_already_read, 0);#ifdef UCX  /* UCX returns -1 on EOF */	if (status == 0 || status == -1)#else	if (status == 0)#endif	{	    end_of_file = YES;	    break;	}	line_buffer[length+status] = 0;	if (line_buffer) {	    FREE(line_kept_clean);	    line_kept_clean = (char *)malloc(buffer_length * sizeof(char));	    if (line_kept_clean == NULL)		outofmem(__FILE__, "HTLoadHTTP");	    memcpy(line_kept_clean, line_buffer, buffer_length);	    real_length_of_line = length + status;	}	eol = strchr(line_buffer + length, LF);	/* Do we *really* want to do this? */	if (eol && eol != line_buffer && *(eol-1) == CR)	    *(eol-1) = ' ';	length = length + status;	/* Do we really want to do *this*? */	if (eol)	    *eol = 0;		/* Terminate the line */    }    /*	All we need is the first line of the response.	If it's a HTTP/1.0    **	response, then the first line will be absurdly short and therefore    **	we can safely gate the number of bytes read through this code    **	(as opposed to below) to ~1000.    **    **	Well, let's try 100.    */    while (!eol && !end_of_file && bytes_already_read < 100);  } /* Scope of loop variables */  /* save total length, in case we decide later to show it all - kw */  rawlength = length;  /*	We now have a terminated unfolded line.  Parse it.  **	--------------------------------------------------  */  CTRACE((tfp, "HTTP: Rx: %s\n", line_buffer));  /*  **  Kludge to work with old buggy servers and the VMS Help gateway.  **  They can't handle the third word, so we try again without it.  */  if (extensions &&	  /* Old buggy server or Help gateway? */      (0==strncmp(line_buffer,"<TITLE>Bad File Request</TITLE>",31) ||       0==strncmp(line_buffer,"Address should begin with",25) ||       0==strncmp(line_buffer,"<TITLE>Help ",12) ||       0==strcmp(line_buffer,		 "Document address invalid or access not authorised"))) {      FREE(line_buffer);      FREE(line_kept_clean);      extensions = NO;      already_retrying = TRUE;      CTRACE((tfp, "HTTP: close socket %d to retry with HTTP0\n", s));      HTTP_NETCLOSE(s, handle);      /* print a progress message */      _HTProgress (RETRYING_AS_HTTP0);      goto try_again;  }  {    int fields;    char server_version[VERSION_LENGTH+1];    server_version[0] = 0;    fields = sscanf(line_buffer, "%20s %d",		    server_version,		    &server_status);    CTRACE((tfp, "HTTP: Scanned %d fields from line_buffer\n", fields));    if (http_error_file) {     /* Make the status code externally available */	FILE *error_file;#ifdef SERVER_STATUS_ONLY	error_file = fopen(http_error_file, TXT_W);	if (error_file) {		/* Managed to open the file */	    fprintf(error_file, "error=%d\n", server_status);	    fclose(error_file);	}#else	error_file = fopen(http_error_file, TXT_A);	if (error_file) {		/* Managed to open the file */	    fprintf(error_file, "   URL=%s (%s)\n", url, METHOD);	    fprintf(error_file, "STATUS=%s\n", line_buffer);	    fclose(error_file);	}#endif /* SERVER_STATUS_ONLY */    }    /*    **	Rule out a non-HTTP/1.n reply as best we can.    */    if (fields < 2 || !server_version[0] || server_version[0] != 'H' ||	server_version[1] != 'T' || server_version[2] != 'T' ||	server_version[3] != 'P' || server_version[4] != '/' ||	server_version[6] != '.') {	/*	 *  Ugh!  An HTTP0 reply,	 */	HTAtom * encoding;	CTRACE((tfp, "--- Talking HTTP0.\n"));	format_in = HTFileFormat(url, &encoding, NULL);	/*	**  Treat all plain text as HTML.	**  This sucks but its the only solution without	**  without looking at content.	*/	if (!strncmp(HTAtom_name(format_in), "text/plain",10)) {	    CTRACE((tfp, "HTTP: format_in being changed to text/HTML\n"));	    format_in = WWW_HTML;	}	if (!IsUnityEnc(encoding)) {	    /*	    **	Change the format to that for "www/compressed".	    */	    CTRACE((tfp, "HTTP: format_in is '%s',\n", HTAtom_name(format_in)));	    StrAllocCopy(anAnchor->content_type, HTAtom_name(format_in));	    StrAllocCopy(anAnchor->content_encoding, HTAtom_name(encoding));	    format_in = HTAtom_for("www/compressed");	    CTRACE((tfp, "        Treating as '%s' with encoding '%s'\n",			"www/compressed", HTAtom_name(encoding)));	}	start_of_data = line_kept_clean;    } else {	/*	**  Set up to decode full HTTP/1.n response. - FM	*/	format_in = HTAtom_for("www/mime");	CTRACE((tfp, "--- Talking HTTP1.\n"));	/*	**  We set start_of_data to "" when !eol here because there	**  will be a put_block done below; we do *not* use the value	**  of start_of_data (as a pointer) in the computation of	**  length (or anything else) when !eol.  Otherwise, set the	**  value of length to what we have beyond eol (i.e., beyond	**  the status line). - FM	*/	start_of_data = eol ? eol + 1 : "";	length = eol ? length - (start_of_data - line_buffer) : 0;	/*	**  Trim trailing spaces in line_buffer so that we can use	**  it in messages which include the status line. - FM	*/	while (line_buffer[strlen(line_buffer)-1] == ' ')	       line_buffer[strlen(line_buffer)-1] = '\0';	/*	**  Take appropriate actions based on the status. - FM	*/	switch (server_status/100) {	  case 1:	    /*	    **	HTTP/1.1 Informational statuses.	    **	100 Continue.	    **	101 Switching Protocols.	    **	> 101 is unknown.	    **	We should never get these, and they have only	    **	the status line and possibly other headers,	    **	so we'll deal with them by showing the full	    **	header to the user as text/plain. - FM	    */	    HTAlert(gettext("Got unexpected Informational Status."));	    do_head = TRUE;	    break;	  case 2:	    /*	    **	Good: Got MIME object! (Successful) - FM	    */	    if (do_head) {		/*		 *  If HEAD was requested, show headers (and possibly		 *  bogus body) for all 2xx status codes as text/plain - KW		 */		HTProgress(line_buffer);		break;	    }	    switch (server_status) {	      case 204:		/*		 *  No Content.		 */		HTAlert(line_buffer);		HTTP_NETCLOSE(s, handle);		HTNoDataOK = 1;		status = HT_NO_DATA;		goto clean_up;	      case 205:		/*		 *  Reset Content.  The server has fulfilled the		 *  request but nothing is returned and we should		 *  reset any form content.  We'll instruct the		 *  user to do that, and restore the current		 *  document. - FM		 */		HTAlert(gettext("Request fulfilled.  Reset Content."));		HTTP_NETCLOSE(s, handle);		status = HT_NO_DATA;		goto clean_up;	      case 206:		/*		 *  Partial Content.  We didn't send a Range		 *  so something went wrong somewhere.	Show		 *  the status message and restore the current		 *  document. - FM		 */		HTAlert(line_buffer);		HTTP_NETCLOSE(s, handle);		status = HT_NO_DATA;		goto clean_up;	      default:		/*		 *  200 OK.		 *  201 Created.		 *  202 Accepted.		 *  203 Non-Authoritative Information.		 *  > 206 is unknown.		 *  All should return something to display.		 */#if defined(USE_SSL) && !defined(DISABLE_NEWS)		if (do_connect) {		    CTRACE((tfp, "HTTP: Proxy tunnel to '%s' established.\n",				connect_host));		    do_connect = FALSE;		    url = connect_url;		    FREE(line_buffer);		    FREE(line_kept_clean);		    if (!strncmp(connect_url, "snews", 5)) {			CTRACE((tfp,			"      Will attempt handshake and snews connection.\n"));			status = HTNewsProxyConnect(s, url, anAnchor,						    format_out, sink);			goto done;		    }		    did_connect = TRUE;		    already_retrying = TRUE;		    eol = 0;		    bytes_already_read = 0;		    had_header = NO;		    length = 0;		    doing_redirect = FALSE;		    permanent_redirection = FALSE;		    target = NULL;		    CTRACE((tfp,			"      Will attempt handshake and resubmit headers.\n"));		    goto use_tunnel;		}#endif /* USE_SSL */		HTProgress(line_buffer);	    } /* case 2 switch */	    break;	  case 3:	    /*	    **	Various forms of Redirection. - FM	    **	300 Multiple Choices.	    **	301 Moved Permanently.	    **	302 Found (temporary; we can, and do, use GET).	    **	303 See Other (temporary; always use GET).	    **	304 Not Modified.	    **	305 Use Proxy.	    **	306 Set Proxy.	    **	307 Temporary Redirect with method retained.	    **	> 308 is unknown.	    */	    if (no_url_redirection || do_head || keep_mime_headers) {		/*		 *  If any of these flags are set, we do not redirect,		 *  but instead show what was returned to the user as		 *  text/plain. - FM		 */		HTProgress(line_buffer);		break;	    }	    if (server_status == 300) { /* Multiple Choices */		/*		 *  For client driven content negotiation.  The server		 *  should be sending some way for the user-agent to		 *  make a selection, so we'll show the user whatever		 *  the server returns.  There might be a Location:		 *  header with the server's preference present, but		 *  the choice should be up to the user, someday based		 *  on an Alternates: header, and a body always should		 *  be present with descriptions and links for the		 *  choices (i.e., we use the latter, for now). - FM		 */		HTAlert(line_buffer);		if (traversal) {		    HTTP_NETCLOSE(s, handle);		    status = -1;		    goto clean_up;		}		if (!dump_output_immediately &&		    format_out == HTAtom_for("www/download")) {		    /*		     *	Convert a download request to		     *	a presentation request for		     *	interactive users. - FM		     */		    format_out = WWW_PRESENT;		}		break;	    }	    if (server_status == 304) { /* Not Modified */		/*		 *  We didn't send an "If-Modified-Since" header,		 *  so this status is inappropriate.  We'll deal		 *  with it by showing the full header to the user		 *  as text/plain. - FM		 */		HTAlert(gettext("Got unexpected 304 Not Modified status."));		do_head = TRUE;		break;	    }	    if (server_status == 305 ||		server_status == 306 ||		server_status > 307) {		/*		 *  Show user the content, if any, for 305, 306,		 *  or unknown status. - FM		 */		HTAlert(line_buffer);		if (traversal) {		    HTTP_NETCLOSE(s, handle);		    status = -1;		    goto clean_up;		}		if (!dump_output_immediately &&		    format_out == HTAtom_for("www/download")) {		    /*		     *	Convert a download request to		     *	a presentation request for		     *	interactive users. - FM		     */		    format_out = WWW_PRESENT;		}		break;	    }	    /*	     *	We do not load the file, but read the headers for	     *	the "Location:", check out that redirecting_url	     *	and if it's acceptible (e.g., not a telnet URL	     *	when we have that disabled), initiate a new fetch.	     *	If that's another redirecting_url, we'll repeat the	     *	checks, and fetch initiations if acceptible, until	     *	we reach the actual URL, or the redirection limit	     *	set in HTAccess.c is exceeded.	If the status was 301	     *	indicating that the relocation is permanent, we set	     *	the permanent_redirection flag to make it permanent	     *	for the current anchor tree (i.e., will persist until	     *	the tree is freed or the client exits).  If the	     *	redirection would include POST content, we seek	     *	confirmation from an interactive user, with option to	     *	use 303 for 301 (but not for 307), and otherwise refuse	     *	the redirection.  We also don't allow permanent	     *	redirection if we keep POST content.  If we don't find	     *	the Location header or it's value is zero-length, we	     *	display whatever the server returned, and the user	     *	should RELOAD that to try again, or make a selection	     *	from it if it contains links, or Left-Arrow to the	     *	previous document. - FM	     */	    {	      if ((dump_output_immediately || traversal) &&		  do_post &&		  server_status != 303 &&		  server_status != 302 &&		  server_status != 301) {		  /*

⌨️ 快捷键说明

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