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

📄 http.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*	HyperText Tranfer Protocol	- Client implementation		HTTP.c**	==========================** Modified:** 27 Jan 1994	PDM  Added Ari Luotonen's Fix for Reload when using proxy**		     servers.** 28 Apr 1997	AJL,FM Do Proxy Authorisation.*/#include <HTUtils.h>#include <HTTP.h>#include <LYUtils.h>#ifdef USE_SSL#include <HTNews.h>#endif#define HTTP_VERSION	"HTTP/1.0"#define HTTP_PORT   80#define HTTPS_PORT  443#define SNEWS_PORT  563#define INIT_LINE_SIZE		1536	/* Start with line buffer this big */#define LINE_EXTEND_THRESH	256	/* Minimum read size */#define VERSION_LENGTH		20	/* for returned protocol version */#include <HTParse.h>#include <HTTCP.h>#include <HTFormat.h>#include <HTFile.h>#include <HTAlert.h>#include <HTMIME.h>#include <HTML.h>#include <HTInit.h>#include <HTAABrow.h>#include <HTAccess.h>		/* Are we using an HTTP gateway? */#include <LYCookie.h>#include <LYGlobalDefs.h>#include <GridText.h>#include <LYStrings.h>#include <LYLeaks.h>struct _HTStream{  HTStreamClass * isa;};extern char * HTAppName;	/* Application name: please supply */extern char * HTAppVersion;	/* Application version: please supply */PUBLIC BOOL reloading = FALSE;	/* Reloading => send no-cache pragma to proxy */PUBLIC char * redirecting_url = NULL;	    /* Location: value. */PUBLIC BOOL permanent_redirection = FALSE;  /* Got 301 status? */PUBLIC BOOL redirect_post_content = FALSE;  /* Don't convert to GET? */#ifdef USE_SSLPUBLIC SSL_CTX * ssl_ctx = NULL;	/* SSL ctx */PUBLIC SSL * SSL_handle = NULL;PUBLIC int ssl_okay;PRIVATE void free_ssl_ctx NOARGS{    if (ssl_ctx != NULL)	SSL_CTX_free(ssl_ctx);}PRIVATE int HTSSLCallback(int preverify_ok, X509_STORE_CTX *x509_ctx){    char *msg = NULL;    int result = 1;    if (!(preverify_ok || ssl_okay || ssl_noprompt)) {#ifdef USE_X509_SUPPORT	HTSprintf0(&msg, "SSL error:%s-Continue?",		   X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)));	if (HTForcedPrompt(ssl_noprompt, msg, YES))	    ssl_okay = 1;	else	    result = 0;#endif	FREE(msg);    }    return result;}PUBLIC SSL * HTGetSSLHandle NOARGS{    if (ssl_ctx == NULL) {	/*	 *  First time only.	 */#if SSLEAY_VERSION_NUMBER < 0x0800	ssl_ctx = SSL_CTX_new();	X509_set_default_verify_paths(ssl_ctx->cert);#else	SSLeay_add_ssl_algorithms();	ssl_ctx = SSL_CTX_new(SSLv23_client_method());	SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);	SSL_CTX_set_default_verify_paths(ssl_ctx);	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, HTSSLCallback);#endif /* SSLEAY_VERSION_NUMBER < 0x0800 */	atexit(free_ssl_ctx);    }    ssl_okay = 0;    return(SSL_new(ssl_ctx));}PUBLIC void HTSSLInitPRNG NOARGS{#if SSLEAY_VERSION_NUMBER >= 0x00905100    if (RAND_status() == 0) {	char rand_file[256];	time_t t;	int pid;	long l,seed;	t = time(NULL);	pid = getpid();	RAND_file_name(rand_file, 256);	CTRACE((tfp,"HTTP: Seeding PRNG\n"));	if(rand_file != NULL) {	    /* Seed as much as 1024 bytes from RAND_file_name */	    RAND_load_file(rand_file, 1024);	}	/* Seed in time (mod_ssl does this) */	RAND_seed((unsigned char *)&t, sizeof(time_t));	/* Seed in pid (mod_ssl does this) */	RAND_seed((unsigned char *)&pid, sizeof(pid));	/* Initialize system's random number generator */	RAND_bytes((unsigned char *)&seed, sizeof(long));	lynx_srand(seed);	while (RAND_status() == 0) {	    /* Repeatedly seed the PRNG using the system's random number generator until it has been seeded with enough data */	    l = lynx_rand();	    RAND_seed((unsigned char *)&l, sizeof(long));	}	if (rand_file != NULL) {	    /* Write a rand_file */	    RAND_write_file(rand_file);	}    }#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */    return;}#define HTTP_NETREAD(sock, buff, size, handle) \	(handle ? SSL_read(handle, buff, size) : NETREAD(sock, buff, size))#define HTTP_NETWRITE(sock, buff, size, handle) \	(handle ? SSL_write(handle, buff, size) : NETWRITE(sock, buff, size))#define HTTP_NETCLOSE(sock, handle)  \	{ (void)NETCLOSE(sock); if (handle) SSL_free(handle); SSL_handle = handle = NULL; }#else#define HTTP_NETREAD(a, b, c, d)   NETREAD(a, b, c)#define HTTP_NETWRITE(a, b, c, d)  NETWRITE(a, b, c)#define HTTP_NETCLOSE(a, b)  (void)NETCLOSE(a)#endif /* USE_SSL */#ifdef _WINDOWS		/* 1997/11/06 (Thu) 13:00:08 */#define	BOX_TITLE	"Lynx " __FILE__#define	BOX_FLAG	(MB_ICONINFORMATION | MB_SETFOREGROUND)typedef struct {	int fd;	char *buf;	int len;} recv_data_t;PUBLIC int ws_read_per_sec = 0;PRIVATE int ws_errno = 0;PRIVATE DWORD g_total_times = 0;PRIVATE DWORD g_total_bytes = 0;PUBLIC char * str_speed(void){    static char buff[32];    if (ws_read_per_sec > 1000)	sprintf(buff, "%d.%03dkB", ws_read_per_sec / 1000,			(ws_read_per_sec % 1000) );    else	sprintf(buff, "%3d", ws_read_per_sec);    return buff;}/* The same like read, but takes care of EINTR and uses select to   timeout the stale connections.  */PRIVATE int ws_read(int fd, char *buf, int len){     int res;     int retry = 3;     do {	res = recv(fd, buf, len, 0);	if (WSAEWOULDBLOCK == WSAGetLastError()) {	  Sleep(100);	  if (retry-- > 0)	    continue;	}     } while (res == SOCKET_ERROR && SOCKET_ERRNO == EINTR);     return res;}PRIVATE void _thread_func (void *p){    int i, val, ret;    recv_data_t *q = (recv_data_t *)p;    i = 0;    i++;    val = ws_read(q->fd, q->buf, q->len);    if (val == SOCKET_ERROR) {	ws_errno = WSAGetLastError();#if 0	char buff[256];	sprintf(buff, "Thread read: %d, error (%ld), fd = %d, len = %d",		i, ws_errno, q->fd, q->len);	MessageBox(NULL, buff, BOX_TITLE, BOX_FLAG);#endif	ret = -1;    } else {	ret = val;    }    ExitThread((DWORD)ret);}/* The same like read, but takes care of EINTR and uses select to   timeout the stale connections.  */PUBLIC int ws_netread(int fd, char *buf, int len){    int i;    char buff[256];     /* 1998/03/30 (Mon) 09:01:21 */    HANDLE hThread;    DWORD dwThreadID;    DWORD exitcode = 0;    DWORD ret_val = -1, val, process_time, now_TickCount, save_TickCount;    static recv_data_t para;    extern int win32_check_interrupt(void);	/* LYUtil.c */    extern int lynx_timeout;			/* LYMain.c */    extern CRITICAL_SECTION critSec_READ;	/* LYMain.c */#define TICK	5#define STACK_SIZE	0x2000uL    InitializeCriticalSection(&critSec_READ);    para.fd = fd;    para.buf = buf;    para.len = len;    ws_read_per_sec = 0;    save_TickCount = GetTickCount();    hThread = CreateThread((void *)NULL, STACK_SIZE,		 (LPTHREAD_START_ROUTINE)_thread_func,		 (void *)&para, 0UL, &dwThreadID);    if (hThread == 0) {	HTInfoMsg("CreateThread Failed (read)");	goto read_exit;    }    i = 0;    while (1) {	val = WaitForSingleObject(hThread, 1000/TICK);	i++;	if (val == WAIT_FAILED) {	    HTInfoMsg("Wait Failed");	    ret_val = -1;	    break;	} else if (val == WAIT_TIMEOUT) {	    i++;	    if (i/TICK > (AlertSecs + 2)) {		sprintf(buff, "Read Waiting (%2d.%01d) for %d Bytes",			i/TICK, (i%TICK) * 10 / TICK, len);		SetConsoleTitle(buff);	    }	    if (win32_check_interrupt() || ((i/TICK) > lynx_timeout)) {		if (CloseHandle(hThread) == FALSE) {		    HTInfoMsg("Thread terminate Failed");		}		WSASetLastError(ETIMEDOUT);		ret_val = HT_INTERRUPTED;		break;	    }	} else if (val == WAIT_OBJECT_0) {	    if (GetExitCodeThread(hThread, &exitcode) == FALSE) {		exitcode = -1;	    }	    if (CloseHandle(hThread) == FALSE) {		HTInfoMsg("Thread terminate Failed");	    }	    now_TickCount = GetTickCount();	    if (now_TickCount > save_TickCount)		process_time = now_TickCount - save_TickCount;	    else		process_time = now_TickCount + (0xffffffff - save_TickCount);	    g_total_times += process_time;	    g_total_bytes += exitcode;	    if (g_total_bytes > 2000000) {		ws_read_per_sec = g_total_bytes / (g_total_times/1000);	    } else {		ws_read_per_sec = g_total_bytes * 1000 / g_total_times;	    }	    ret_val = exitcode;	    break;	}    }	/* end while(1) */    read_exit:    LeaveCriticalSection(&critSec_READ);    return ret_val;}#endif/* * Strip any username from the given string so we retain only the host. * If the */PRIVATE void strip_userid ARGS1(	char *,		host){    char *p1 = host;    char *p2 = strchr(host, '@');    char *fake;    if (p2 != 0) {	*p2++ = '\0';	if ((fake = HTParse(host, "", PARSE_HOST)) != NULL) {	    char *msg = NULL;	    CTRACE((tfp, "FIXME:%s\n", fake));	    HTSprintf0(&msg, gettext("Address contains a username: %s"), host);	    HTAlert(msg);	    FREE(msg);	}	while ((*p1++ = *p2++) != '\0') {	    ;	}    }}/*		Load Document from HTTP Server			HTLoadHTTP()**		==============================****	Given a hypertext address, this routine loads a document.******  On entry,**	arg	is the hypertext reference of the article to be loaded.****  On exit,**	returns >=0	If no error, a good socket number**		<0	Error.****	The socket must be closed by the caller after the document has been**	read.***/PRIVATE int HTLoadHTTP ARGS4 (	CONST char *,		arg,	HTParentAnchor *,	anAnchor,	HTFormat,		format_out,	HTStream*,		sink){  int s;			/* Socket number for returned data */  CONST char *url = arg;	/* The URL which get_physical() returned */  bstring *command = NULL;	/* The whole command */  char *eol;			/* End of line if found */  char *start_of_data;		/* Start of body of reply */  int status;			/* tcp return */  int bytes_already_read;  char crlf[3];			/* A CR LF equivalent string */  HTStream *target;		/* Unconverted data */  HTFormat format_in;		/* Format arriving in the message */  BOOL do_head = FALSE;		/* Whether or not we should do a head */  BOOL do_post = FALSE;		/* ARE WE posting ? */  char *METHOD;  BOOL had_header;		/* Have we had at least one header? */  char *line_buffer;  char *line_kept_clean;  int real_length_of_line;  BOOL extensions;		/* Assume good HTTP server */  char *linebuf = NULL;  char temp[80];  BOOL first_Accept = TRUE;  BOOL show_401 = FALSE;  BOOL show_407 = FALSE;  BOOL auth_proxy = NO;		/* Generate a proxy authorization. - AJL */  int length, rawlength, rv;  int server_status;  BOOL doing_redirect, already_retrying = FALSE;  int len = 0;#ifdef USE_SSL  BOOL do_connect = FALSE;	/* ARE WE going to use a proxy tunnel ? */  BOOL did_connect = FALSE;	/* ARE WE actually using a proxy tunnel ? */  CONST char *connect_url = NULL; /* The URL being proxied */  char *connect_host = NULL;	/* The host being proxied */  SSL * handle = NULL;		/* The SSL handle */  char ssl_dn[256];  char *cert_host;  char *ssl_host;  char *p;  char *msg = NULL;#if SSLEAY_VERSION_NUMBER >= 0x0900  BOOL try_tls = TRUE;#endif /* SSLEAY_VERSION_NUMBER >= 0x0900 */  SSL_handle = NULL;#else  void * handle = NULL;#endif /* USE_SSL */  if (anAnchor->isHEAD)      do_head = TRUE;  else if (anAnchor->post_data)      do_post = TRUE;  if (!url) {      status = -3;      _HTProgress (BAD_REQUEST);      goto done;  }  if (!*url) {      status = -2;      _HTProgress (BAD_REQUEST);      goto done;  }#ifdef USE_SSL  if (using_proxy && !strncmp(url, "http://", 7)) {      if ((connect_url = strstr((url+7), "https://"))) {	  do_connect = TRUE;	  connect_host = HTParse(connect_url, "https", PARSE_HOST);	  if (!strchr(connect_host, ':')) {	      sprintf(temp, ":%d", HTTPS_PORT);	      StrAllocCat(connect_host, temp);	  }	  CTRACE((tfp, "HTTP: connect_url = '%s'\n", connect_url));	  CTRACE((tfp, "HTTP: connect_host = '%s'\n", connect_host));      } else if ((connect_url = strstr((url+7), "snews://"))) {	  do_connect = TRUE;	  connect_host = HTParse(connect_url, "snews", PARSE_HOST);	  if (!strchr(connect_host, ':')) {	      sprintf(temp, ":%d", SNEWS_PORT);	      StrAllocCat(connect_host, temp);	  }	  CTRACE((tfp, "HTTP: connect_url = '%s'\n", connect_url));	  CTRACE((tfp, "HTTP: connect_host = '%s'\n", connect_host));      }  }#endif /* USE_SSL */  sprintf(crlf, "%c%c", CR, LF);  /*  **  At this point, we're talking HTTP/1.0.  */  extensions = YES;try_again:  /*  **  All initializations are moved down here from up above,  **  so we can start over here...  */  eol = 0;  had_header = NO;  length = 0;  doing_redirect = FALSE;  permanent_redirection = FALSE;  redirect_post_content = FALSE;  target = NULL;  line_buffer = NULL;  line_kept_clean = NULL;#ifdef USE_SSL  if (!strncmp(url, "https", 5))    status = HTDoConnect (url, "HTTPS", HTTPS_PORT, &s);  else    status = HTDoConnect (url, "HTTP", HTTP_PORT, &s);#else  if (!strncmp(url, "https", 5))    {      HTAlert(gettext("This client does not contain support for HTTPS URLs."));      status = HT_NOT_LOADED;      goto done;    }  status = HTDoConnect (arg, "HTTP", HTTP_PORT, &s);#endif /* USE_SSL */  if (status == HT_INTERRUPTED) {      /*      **  Interrupt cleanly.      */       CTRACE((tfp, "HTTP: Interrupted on connect; recovering cleanly.\n"));       _HTProgress (CONNECTION_INTERRUPTED);       status = HT_NOT_LOADED;       goto done;   }   if (status < 0) {#ifdef _WINDOWS      CTRACE((tfp, "HTTP: Unable to connect to remote host for `%s'\n"			  " (status = %d, sock_errno = %d).\n",			  url, status, SOCKET_ERRNO));#else      CTRACE((tfp,	    "HTTP: Unable to connect to remote host for `%s' (errno = %d).\n",	    url, SOCKET_ERRNO));#endif      HTAlert(gettext("Unable to connect to remote host."));      status = HT_NOT_LOADED;      goto done;  }/* *sob*  All this needs to be converted to handle binary strings * if we're going to be able to handle binary form uploads... * This is a nice long function as well.  *sigh*  -RJP

⌨️ 快捷键说明

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