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

📄 htftp.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*			File Transfer Protocol (FTP) Client**			for a WorldWideWeb browser**			===================================****	A cache of control connections is kept.**** Note: Port allocation****	It is essential that the port is allocated by the system, rather**	than chosen in rotation by us (POLL_PORTS), or the following**	problem occurs.****	It seems that an attempt by the server to connect to a port which has**	been used recently by a listen on the same socket, or by another**	socket this or another process causes a hangup of (almost exactly)**	one minute.  Therefore, we have to use a rotating port number.**	The problem remains that if the application is run twice in quick**	succession, it will hang for what remains of a minute.**** Authors**	TBL	Tim Berners-lee <timbl@info.cern.ch>**	DD	Denis DeLaRoca 310 825-4580 <CSP1DWD@mvs.oac.ucla.edu>**	LM	Lou Montulli <montulli@ukanaix.cc.ukans.edu>**	FM	Foteos Macrides <macrides@sci.wfeb.edu>** History:**	 2 May 91	Written TBL, as a part of the WorldWideWeb project.**	15 Jan 92	Bug fix: close() was used for NETCLOSE for control soc**	10 Feb 92	Retry if cached connection times out or breaks**	 8 Dec 92	Bug fix 921208 TBL after DD**	17 Dec 92	Anon FTP password now just WWWuser@ suggested by DD**			fails on princeton.edu!**	27 Dec 93 (FM)	Fixed up so FTP now works with VMS hosts.  Path**			must be Unix-style and cannot include the device**			or top directory.**	?? ??? ?? (LM)	Added code to prompt and send passwords for non**			anonymous FTP**	25 Mar 94 (LM)	Added code to recognize different ftp server types**			and code to parse dates and sizes on most hosts.**	27 Mar 93 (FM)	Added code for getting dates and sizes on VMS hosts.**** Notes:**			Portions Copyright 1994 Trustees of Dartmouth College**			Code for recognizing different FTP servers and**			parsing "ls -l" output taken from Macintosh Fetch**			program with permission from Jim Matthews,**			Dartmouth Software Development Team.*//*BUGS:	@@@	Limit connection cache size!		Error reporting to user.		400 & 500 errors are ack'ed by user with windows.		Use configuration file for user names**		Note for portability this version does not use select() and**		so does not watch the control and data channels at the**		same time.*/#include <HTUtils.h>#include <HTAlert.h>#include <HTFTP.h>	/* Implemented here */#include <HTTCP.h>#include <HTTP.h>#include <HTFont.h>#define REPEAT_PORT	/* Give the port number for each file */#define REPEAT_LISTEN	/* Close each listen socket and open a new one *//* define POLL_PORTS		 If allocation does not work, poll ourselves.*/#define LISTEN_BACKLOG 2	/* Number of pending connect requests (TCP)*/#define FIRST_TCP_PORT	1024	/* Region to try for a listening port */#define LAST_TCP_PORT	5999#define LINE_LENGTH 256#include <HTParse.h>#include <HTAnchor.h>#include <HTFile.h>	/* For HTFileFormat() */#include <HTBTree.h>#include <HTChunk.h>#ifndef IPPORT_FTP#define IPPORT_FTP	21#endif /* !IPORT_FTP */#include <LYUtils.h>#include <LYGlobalDefs.h>#include <LYStrings.h>#include <LYLeaks.h>typedef struct _connection {    struct _connection *	next;	/* Link on list		*/    unsigned long		addr;	/* IP address		*/    int				socket; /* Socket number for communication */    BOOL			binary; /* Binary mode? */} connection;/*		Hypertext object building machinery*/#include <HTML.h>#define PUTC(c)      (*targetClass.put_character) (target, c)#define PUTS(s)      (*targetClass.put_string)    (target, s)#define START(e)     (*targetClass.start_element) (target, e, 0, 0, -1, 0)#define END(e)       (*targetClass.end_element)   (target, e, 0)#define FREE_TARGET  (*targetClass._free)         (target)#define ABORT_TARGET (*targetClass._free)         (target)struct _HTStructured {	CONST HTStructuredClass *	isa;	/* ... */};/*	Global Variables**	---------------------*/PUBLIC int HTfileSortMethod = FILE_BY_NAME;#ifndef DISABLE_FTP /*This disables everything to end-of-file */PRIVATE char ThisYear[8];PRIVATE char LastYear[8];PRIVATE int TheDate;PRIVATE BOOLEAN HaveYears = FALSE;/*	Module-Wide Variables**	---------------------*/PRIVATE connection * connections = NULL;/* Linked list of connections */PRIVATE char response_text[LINE_LENGTH+1];/* Last response from ftp host */PRIVATE connection * control = NULL;	/* Current connection */PRIVATE int data_soc = -1;		/* Socket for data transfer =invalid */PRIVATE char *user_entered_password = NULL;PRIVATE char *last_username_and_host = NULL;/* * ProFTPD 1.2.5rc1 is known to have a broken implementation of RETR.  If asked * to retrieve a directory, it gets confused and fails subsequent commands such * as CWD and LIST.  Since this is an unusual bug, we should remove this ifdef * at some point - TD 2004/1/1. */#define BROKEN_PROFTPD 1PRIVATE int ProFTPD_bugs = FALSE;typedef enum {	GENERIC_SERVER	, MACHTEN_SERVER	, UNIX_SERVER	, VMS_SERVER	, CMS_SERVER	, DCTS_SERVER	, TCPC_SERVER	, PETER_LEWIS_SERVER	, NCSA_SERVER	, WINDOWS_NT_SERVER	, WINDOWS_2K_SERVER	, MS_WINDOWS_SERVER	, MSDOS_SERVER	, APPLESHARE_SERVER	, NETPRESENZ_SERVER	, DLS_SERVER} eServerType;PRIVATE eServerType server_type = GENERIC_SERVER; /* the type of ftp host */PRIVATE int	unsure_type = FALSE;		/* sure about the type? */PRIVATE BOOLEAN use_list = FALSE;		/* use the LIST command? */PRIVATE int	interrupted_in_next_data_char = FALSE;#ifdef POLL_PORTSPRIVATE PortNumber	port_number = FIRST_TCP_PORT;#endif /* POLL_PORTS */PRIVATE int	master_socket = -1;	/* Listening socket = invalid	*/PRIVATE char	port_command[255];	/* Command for setting the port */PRIVATE fd_set	open_sockets;		/* Mask of active channels */PRIVATE int	num_sockets;		/* Number of sockets to scan */PRIVATE PortNumber	passive_port;	/* Port server specified for data */#define NEXT_CHAR HTGetCharacter()	/* Use function in HTFormat.c */#define DATA_BUFFER_SIZE 2048PRIVATE char data_buffer[DATA_BUFFER_SIZE];		/* Input data buffer */PRIVATE char * data_read_pointer;PRIVATE char * data_write_pointer;#define NEXT_DATA_CHAR next_data_char()PRIVATE int close_connection PARAMS((	connection *	con));#ifdef LY_FIND_LEAKS/***  This function frees module globals. - FM*/PRIVATE void free_FTPGlobals NOARGS{    FREE(user_entered_password);    FREE(last_username_and_host);    if (control) {	if (control->socket != -1)	    close_connection(control);	FREE(control);    }}#endif /* LY_FIND_LEAKS *//* PUBLIC						HTVMS_name()**		CONVERTS WWW name into a VMS name** ON ENTRY:**	nn		Node Name (optional)**	fn		WWW file name**** ON EXIT:**	returns		vms file specification**** Bug: Returns pointer to static -- non-reentrant*/PUBLIC char * HTVMS_name ARGS2(	CONST char *,	nn,	CONST char *,	fn){/*	We try converting the filename into Files-11 syntax.  That is, we assume**	first that the file is, like us, on a VMS node.  We try remote**	(or local) DECnet access.  Files-11, VMS, VAX and DECnet**	are trademarks of Digital Equipment Corporation.**	The node is assumed to be local if the hostname WITHOUT DOMAIN**	matches the local one. @@@*/    static char *vmsname;    char * filename = (char*)malloc(strlen(fn)+1);    char * nodename = (char*)malloc(strlen(nn)+2+1);	/* Copies to hack */    char *second;		/* 2nd slash */    char *last;			/* last slash */    CONST char * hostname = HTHostName();    if (!filename || !nodename)	outofmem(__FILE__, "HTVMSname");    strcpy(filename, fn);    strcpy(nodename, "");	/* On same node?  Yes if node names match */    if (strncmp(nn, "localhost", 9)) {	CONST char *p;	CONST char *q;	for (p = hostname, q = nn;	     *p && *p != '.' && *q && *q != '.'; p++, q++){	    if (TOUPPER(*p) != TOUPPER(*q)) {		char *r;		strcpy(nodename, nn);		r = strchr(nodename, '.');	/* Mismatch */		if (r)		    *r = '\0';			/* Chop domain */		strcat(nodename, "::");		/* Try decnet anyway */		break;	    }	}    }    second = strchr(filename+1, '/');		/* 2nd slash */    last = strrchr(filename, '/');	/* last slash */    if (!second) {				/* Only one slash */	HTSprintf0(&vmsname, "%s%s", nodename, filename + 1);    } else if (second == last) {		/* Exactly two slashes */	*second = '\0';		/* Split filename from disk */	HTSprintf0(&vmsname, "%s%s:%s", nodename, filename+1, second+1);	*second = '/';	/* restore */    } else {				/* More than two slashes */	char * p;	*second = '\0';		/* Split disk from directories */	*last = '\0';		/* Split dir from filename */	HTSprintf0(&vmsname, "%s%s:[%s]%s",		nodename, filename+1, second+1, last+1);	*second = *last = '/';	/* restore filename */	for (p = strchr(vmsname, '['); *p!=']'; p++)	    if (*p == '/')		*p = '.';		/* Convert dir sep.  to dots */    }    FREE(nodename);    FREE(filename);    return vmsname;}/*	Procedure: Read a character from the data connection**	----------------------------------------------------*/PRIVATE int next_data_char NOARGS{    int status;    if (data_read_pointer >= data_write_pointer) {	status = NETREAD(data_soc, data_buffer, DATA_BUFFER_SIZE);      if (status == HT_INTERRUPTED)	interrupted_in_next_data_char = 1;      if (status <= 0)	return -1;      data_write_pointer = data_buffer + status;      data_read_pointer = data_buffer;    }#ifdef NOT_ASCII    {	char c = *data_read_pointer++;	return FROMASCII(c);    }#else    return UCH(*data_read_pointer++);#endif /* NOT_ASCII */}/*	Close an individual connection***/PRIVATE int close_connection ARGS1(	connection *,	con){    connection * scan;    int status;    CTRACE((tfp, "HTFTP: Closing control socket %d\n", con->socket));    status = NETCLOSE(con->socket);    if (TRACE && status != 0) {#ifdef UNIX	CTRACE((tfp, "HTFTP:close_connection: %s", LYStrerror(errno)));#else	if (con->socket != INVSOC)	    HTInetStatus("HTFTP:close_connection");#endif    }    con->socket = -1;    if (connections == con) {	connections = con->next;	return status;    }    for (scan = connections; scan; scan = scan->next) {	if (scan->next == con) {	    scan->next = con->next;	/* Unlink */	    if (control == con)		control = (connection*)0;	    return status;	} /*if */    } /* for */    return -1;		/* very strange -- was not on list. */}PRIVATE char *help_message_buffer = NULL;  /* global :( */PRIVATE void init_help_message_cache NOARGS{    FREE(help_message_buffer);}PRIVATE void help_message_cache_add ARGS1(	char *,		string){    if (help_message_buffer)	StrAllocCat(help_message_buffer, string);    else	StrAllocCopy(help_message_buffer, string);    CTRACE((tfp,"Adding message to help cache: %s\n",string));}PRIVATE char *help_message_cache_non_empty NOARGS{  return(help_message_buffer);}PRIVATE char *help_message_cache_contents NOARGS{   return(help_message_buffer);}/*	Send One Command**	----------------****	This function checks whether we have a control connection, and sends**	one command if given.**** On entry,**	control	points to the connection which is established.**	cmd	points to a command, or is zero to just get the response.****	The command should already be terminated with the CRLF pair.**** On exit,**	returns:  1 for success,**		  or negative for communication failure (in which case**		  the control connection will be closed).*/PRIVATE int write_cmd ARGS1(	char *,		cmd){    int status;    if (!control) {	CTRACE((tfp, "HTFTP: No control connection set up!!\n"));	return -99;    }    if (cmd) {	CTRACE((tfp, "  Tx: %s", cmd));#ifdef NOT_ASCII	{	    char * p;	    for (p = cmd; *p; p++) {		*p = TOASCII(*p);	    }	}#endif /* NOT_ASCII */	status = NETWRITE(control->socket, cmd, (int)strlen(cmd));	if (status < 0) {	    CTRACE((tfp, "HTFTP: Error %d sending command: closing socket %d\n",			status, control->socket));	    close_connection(control);	    return status;	}    }    return 1;}/*	Execute Command and get Response**	--------------------------------****	See the state machine illustrated in RFC959, p57. This implements**	one command/reply sequence.  It also interprets lines which are to**	be continued, which are marked with a "-" immediately after the**	status code.****	Continuation then goes on until a line with a matching reply code**	an a space after it.**** On entry,**	control	points to the connection which is established.**	cmd	points to a command, or is zero to just get the response.****	The command must already be terminated with the CRLF pair.**** On exit,**	returns:  The first digit of the reply type,**		  or negative for communication failure.*/PRIVATE int response ARGS1(	char *,		cmd){    int result;				/* Three-digit decimal code */    int continuation_response = -1;    int status;    if ((status = write_cmd(cmd)) < 0)	return status;    do {	char *p = response_text;	for (;;) {	    int ich = NEXT_CHAR;	    if (((*p++ = (char) ich) == LF)			|| (p == &response_text[LINE_LENGTH])) {		char continuation;		if (interrupted_in_htgetcharacter) {		    CTRACE((tfp, "HTFTP: Interrupted in HTGetCharacter, apparently.\n"));		    NETCLOSE (control->socket);		    control->socket = -1;		    return HT_INTERRUPTED;		}		*p = '\0';			/* Terminate the string */		CTRACE((tfp, "    Rx: %s", response_text));		/* Check for login or help messages */		if (!strncmp(response_text,"230-",4) ||		    !strncmp(response_text,"250-",4) ||		    !strncmp(response_text,"220-",4))		    help_message_cache_add(response_text+4);		sscanf(response_text, "%d%c", &result, &continuation);		if  (continuation_response == -1) {			if (continuation == '-')  /* start continuation */			    continuation_response = result;		} else {	/* continuing */			if (continuation_response == result &&			    continuation == ' ')			    continuation_response = -1; /* ended */		}#ifdef BROKEN_PROFTPD		if (result == 220 && LYstrstr(response_text, "ProFTPD 1.2.5")) {		    ProFTPD_bugs = TRUE;		    CTRACE((tfp, "This server is broken (RETR)\n"));		}#endif		break;	    } /* if end of line */	    if (interrupted_in_htgetcharacter) {		CTRACE((tfp, "HTFTP: Interrupted in HTGetCharacter, apparently.\n"));		NETCLOSE (control->socket);

⌨️ 快捷键说明

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