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

📄 ftp.c

📁 站点映像程序
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* Connect to the given host  * Returns non-zero value if successfull */int ftp_connect_pasv() {    int sock;    sock = socket_connect( ftp_dtp_addr, ftp_dtp_port );    if( sock == -1 ) {	ftp_seterror_err( "Could not connect socket" );	return 0;    } else {	ftp_dtp_socket = sock;	return 1;    }}int ftp_open( ) {    int ret;    if( ftp_connection != false ) return FTP_OK;    fe_connection( fe_connecting );    DEBUG( DEBUG_FTP, "Opening socket to port %d\n", ftp_pi_port );    /* Open the socket. */    ftp_pi_socket = socket_connect( ftp_pi_addr, ftp_pi_port );    if( ftp_pi_socket < 0 ) {	return FTP_CONNECT;    }    /* Read the hello message */    ret = ftp_read();    if( ret != FTP_OK ) {	return FTP_HELLO;    }    ftp_connection = true;    if( ftp_login( ) != FTP_OK ) {/*	ftp_seterror( "Could not log in to server." ); */	ftp_connection = false;	close( ftp_pi_socket );	return FTP_LOGIN;    }    fe_connection( fe_connected );    /* <tr@oxlug.org>: Don't know whether in ASCII or binary mode so try      * to fix it.  I don't like this one bit as ftp_settype can call      * ftp_open.      * joe: Note, ftp_using_ascii is set to -1 to avoid infinite      * recursion. Alter with care.     */    if(ftp_using_ascii != -1) {           bool ascii = ftp_using_ascii;           ftp_using_ascii = -1;           return ftp_settype(ascii);    }    return FTP_OK;}int ftp_login( ) {    char cmd[BUFSIZ];    int ret;    DEBUG( DEBUG_FTP,  "FTP: Logging in as %s...\n", ftp_username );    snprintf( cmd, BUFSIZ, "USER %s", ftp_username );    ret = ftp_exec( cmd );    if( ret == FTP_NEEDPASSWORD ) {	DEBUG( DEBUG_FTP,  "FTP: Supplying password...\n" );	snprintf( cmd, BUFSIZ, "PASS %s", ftp_password );	ret = ftp_exec( cmd );    }    return ret;}/* Returns anything which ftp_read() does */int ftp_exec( const char *command ) {    int tries = 0, ret = FTP_ERROR;    while( ++tries < 3 ) {	if( ftp_open( ) != FTP_OK ) break;	if( strncmp( command, "PASS ", 5 ) == 0 ) {	    DEBUG( DEBUG_SOCKET, "> PASS xxxxxxxx\n" );	} else {	    DEBUG( DEBUG_SOCKET, "> %s\n", command );	}	/* Send the line */	if( send_line( ftp_pi_socket, command ) == 0 ) {	    /* Sent the line... try and read the response */	    ret = ftp_read();	    if( ret != FTP_BROKEN ) {		/* Read the response okay */		break;	    }	}    }    /* Don't let FTP_BROKEN get out */    if( ret == FTP_BROKEN ) 	ret = FTP_ERROR;    return ret;}/* Returns anything ftp_read() does, or FTP_BROKEN when the * socket read fails (indicating a broken socket).   */int ftp_read() {    int multiline, len, reply_code;    char buffer[BUFSIZ];    multiline = 0;        for(;;) {	len = read_line( ftp_pi_socket, buffer, BUFSIZ );	if( len < 0 ) {	    /* It broke. */	    ftp_seterror_err( "Could not read response line" );	    ftp_connection = false;	    break;	}		DEBUG( DEBUG_SOCKET, "< %s", buffer );	if(len<5) /* this is a multi-liner, ignore it and carry on */	    continue; 	/* parse the reply code from the line */	reply_code = get_reply_code(buffer);		/* If we have a VALID reply code and we are currently	 * in a multi line response then this is the end of the	 * multi line response */	if(multiline && reply_code)	    multiline=0;		/* Now, if we aren't in a multi line response... */	if(!multiline) { 	    if(buffer[3]=='-') {		/* A dash in char four denotes beginning of multi		 * line response  'xxx-' */		multiline=1;	    } else {		/* Looks like we've got a real response line */		return ftp_response( buffer, reply_code );	    }	}    }    return FTP_BROKEN;}void ftp_seterror( const char *error ) {    memset( ftp_error, 0, BUFSIZ );    strncpy( ftp_error, error, BUFSIZ );/*    DEBUG( DEBUG_FTP, "FTP Error set: %s\n", ftp_error ); */}/* Sets the error string and appends ": strerror(errno)" */void ftp_seterror_err( const char *error ) {    snprintf( ftp_error, BUFSIZ, "%s: %s", error, strerror(errno) );    DEBUG( DEBUG_FTP, "FTP Error set: %s\n", ftp_error );}int ftp_response( const char *response, const int code ) {    char *newline;    /* Set the error string up. */    ftp_seterror( response );    /* Chop the newline */    newline = strrchr( ftp_error, '\r' );    if( newline ) *newline = '\0';	    switch( code ) {    case 200: /* misc OK codes */    case 220:    case 230:    case 250: /* completed file action */    case 257: /* mkdir success */	return FTP_OK;    case 226: /* received file okay */	return FTP_SENT;    case 150: /* file transfer... ready for data */    case 125:	return FTP_READY;    case 550: /* couldn't complete file action */	return FTP_FILEBAD;    case 331: /* got username, want password */	return FTP_NEEDPASSWORD;    case 350: /* file action pending further info - RNFR */	return FTP_FILEMORE;    case 221:	/* They've closed the connection, the swine. */	ftp_connection = false;	return FTP_CLOSED;    case 421: /* service denied */	return FTP_DENIED;    case 213: /* MDTM response, hopefully */	return ftp_read_mdtm( response );    case 227: /* PASV response, hopefully */	return ftp_read_pasv( response );    case 553: /* couldn't create directory */	return FTP_ERROR;    default:	return FTP_ERROR;    }}/* Parses the 213 response to a MDTM command... on success, * returns FTP_MODTIME and sets ftp_modtime to the time in the response. * On failute, returns FTP_ERROR. */int ftp_read_mdtm( const char *response ) {    struct tm time;    char year[5], month[3], mday[3], hour[3], min[3], sec[3];    char *pnt;    if( (pnt = strrchr( response, '\n' ))!=NULL ) *pnt='\0';    if( (pnt = strrchr( response, '\r' ))!=NULL ) *pnt='\0';    DEBUG( DEBUG_FTP, "Reading modtime: %s\n", response );    if( strlen( response ) != 18 ) {	DEBUG( DEBUG_FTP, "Incorrect length response." );	return FTP_ERROR;    }    if( sscanf( response, "213 %4s%2s%2s" "%2s%2s%2s",		year, month, mday,   hour, min, sec ) < 6 ) {	DEBUG( DEBUG_FTP, "sscanf couldn't parse it.\n" );	return FTP_ERROR;    }    DEBUG( DEBUG_FTP, "Parsed: %d/%d/%d %s:%s:%s\n",	   atoi(year), atoi(month), atoi(mday), hour, min, sec );        memset( &time, 0, sizeof( struct tm ) );        time.tm_year = atoi( year ) - 1900; /* years since 1900 */    time.tm_mon = atoi( month ) - 1; /* months since jan */    time.tm_mday = atoi( mday );        time.tm_hour = atoi( hour );    time.tm_min = atoi( min );    time.tm_sec = atoi( sec );    time.tm_isdst = -1;    ftp_modtime = mktime( &time );    DEBUG( DEBUG_FTP, "Converted to: %s", ctime( &ftp_modtime ) );    return FTP_MODTIME;}/* Parses the response to a PASV command. * Sets ftp_dtp_port to the port and ftp_dtp_addr to the address given * in the response and returns FTP_PASSIVE on success. * On failure, returns FTP_ERROR; */int ftp_read_pasv( const char *response ) {    int h1, h2, h3, h4, p1, p2;    char *start;    start = strchr( response, '(' );    /* get the host + port */    if( sscanf( ++start, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2 ) < 6 )	/* didn't match, give up */	return FTP_ERROR;    /* Record this for future reference */    ftp_dtp_port = (p1<<8) | p2;    ftp_dtp_addr.s_addr = htonl( (h1<<24) | (h2<<16) | (h3<<8) | h4 );    return FTP_PASSIVE;}/* Takes the response line from an FTP command and returns the value * of the response code, or 0 if none is found. */int get_reply_code( const char *buffer) {    if(strlen(buffer) > 3)	if( isdigit((unsigned)buffer[0]) &&	    isdigit((unsigned)buffer[1]) && 	    isdigit((unsigned)buffer[2]) )	    /* looks good */	    return atoi(buffer);    return 0;}/* This one does the ls -laR, and tries it's best to parse the resulting * list. Currently implemented only for Unix-style servers, which go: * dirlist * new/directory/name: * dirlist * another/directory/name: * dirlist * etc. where dirlist is a straight ls -al listing */int ftp_fetch_gettree( const char *startdir, struct proto_file_t **files ) {    struct proto_file_t *this_file, *last_file;    char command[BUFSIZ], buffer[BUFSIZ], *pnt;    char *curdir;   /* Holds the path of the current directory */    char perms[BUFSIZ], filename[BUFSIZ], tmp[BUFSIZ];    int ret, filesize, buflen;    bool afterblank;    snprintf( command, BUFSIZ, "LIST -laR %s", startdir );    if( (ret = ftp_data_open( command )) != FTP_READY ) {	return PROTO_ERROR;    }    /* The current directory is a 0-length string. */    curdir = malloc( 1 );    *curdir = '\0';    last_file = NULL;    afterblank = false;    while( read_line( ftp_dtp_socket, buffer, BUFSIZ ) >= 0 ) {	/* Get rid of the EOL */	if( (pnt = strrchr( buffer, '\n' ))!=NULL ) *pnt='\0';	if( (pnt = strrchr( buffer, '\r' ))!=NULL ) *pnt='\0';	DEBUG( DEBUG_FTP, "[ls] < %s\n", buffer );	buflen = strlen( buffer );	if( buflen > 0 ) {	    if( strncmp( buffer, "total ", 6 ) == 0 ) {		/* ignore the line */		DEBUG( DEBUG_FTP, "Line ignored.\n" );	    } else if( *(buffer+buflen-1) == ':' && afterblank ) {		/* A new directory name indicator, which goes:		 *    `directory/name/here:'		 * We want directory names as:		 *    `/directory/name/here' 		 * Hence a bit of messing about. */		free( curdir );		buflen = buflen - strlen(startdir );		curdir = malloc( buflen + 1 );		strncpy( curdir, buffer+strlen(startdir), buflen );		*(curdir+buflen-1) = '/';		*(curdir+buflen) = '\0';		DEBUG( DEBUG_FTP, "Now in directory: %s\n", curdir );	    } else {		/* Weird bit at the end should pick up everything		 * to the EOL... filenames could have whitespace in.		 */		sscanf( buffer, "%s %s %s %s %d %s %s %s %[^*]",  			perms, tmp, tmp, tmp, &filesize,			tmp, tmp, tmp, filename);		if( perms!=NULL && filename!=NULL ) {		    if( *perms == '-' ) {			/* Normal file. */			DEBUG( DEBUG_FTP, "File: %s, size %d\n",			       filename, filesize );			this_file = malloc( sizeof(struct proto_file_t) );			memset( this_file, 0, sizeof(struct proto_file_t) );			this_file->next = *files;			*files = this_file;			if( last_file==NULL ) last_file = this_file;			this_file->filename = strdup( filename );			this_file->directory = strdup( curdir );			this_file->isdir = false;			this_file->size = filesize;		    } else if( *perms == 'd' ) {			/* Subdirectory */			if( strcmp( filename, "." ) == 0 ||			    strcmp( filename, ".." ) == 0 ) {			    DEBUG( DEBUG_FTP, "Ignoring: %s\n", filename );			} else {			    DEBUG( DEBUG_FTP, "Subdir: %s\n", filename );			    this_file = malloc( sizeof(struct proto_file_t) );			    memset( this_file, 0, sizeof(struct proto_file_t) );			    if( last_file==NULL ) {				*files = this_file;			    } else {				last_file->next = this_file;			    }			    last_file = this_file;			    this_file->filename = strdup( filename );			    this_file->directory = strdup( curdir );			    this_file->isdir = true;			}		    } else { 			/* Summant else... ignore */			DEBUG( DEBUG_FTP, "Ignoring: %s\n", filename );		    }		} else {		    DEBUG( DEBUG_FTP, "Could not parse line.\n" );		}	    }	} else {	    DEBUG( DEBUG_FTP, "Blank line.\n" );	    afterblank = true;	}    }    DEBUG( DEBUG_FTP, "Fetch finished successfully.\n" );    if( ftp_data_close( ) == FTP_SENT ) {	return FTP_OK;    } else {	return FTP_ERROR;    }}/* Sorts out the modtimes for all the files in the list. * Returns FTP_OK on success, else FTP_ERROR. */int ftp_fetch_walktree( const char *rootdir, struct proto_file_t *files ) {    struct proto_file_t *this_file;    char command[BUFSIZ];     /* Walk the files list. Okay, it's not really a tree */    for( this_file=files; this_file!=NULL; this_file=this_file->next ) {	if( this_file->isdir ) {	    continue;	}	DEBUG( DEBUG_FTP, "File: %s%s%s\n", rootdir,	       this_file->directory, this_file->filename );	snprintf( command, BUFSIZ, "MDTM %s%s%s", 		  rootdir, this_file->directory, this_file->filename );	if( ftp_exec( command ) == FTP_MODTIME ) {	    DEBUG( DEBUG_FTP, "Got modtime.\n" );	    this_file->modtime = ftp_modtime;	} else {	    DEBUG( DEBUG_FTP, "Didn't get modtime.\n" );	    return FTP_ERROR;	}    }    DEBUG( DEBUG_FTP, "Walk finished ok.\n" );    return FTP_OK;}/* Retrieves remote file listings. * This is a multi-stage operation. * First off, we do a LIST -R, which returns a recursive file listing. * Next, we go through the entire list of files returned and do a * MDTM on them to retrieve their accurate modtime. * If we can successfully retrieve every modtime, then we pass the * files one by one back up to the sites code. About as inefficient * as it gets. */int ftp_fetch( const char *startdir, struct proto_file_t **files ) {    int ret;    ret = ftp_fetch_gettree( startdir, files );    if( ret == FTP_OK ) {	ret = ftp_fetch_walktree( startdir, *files );    }        if( ret == FTP_OK ) {	return PROTO_OK;    } else {	return PROTO_ERROR;    }   }   

⌨️ 快捷键说明

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