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

📄 ftp-retr.c

📁 linux下的网络下载工具prozilla的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Functions to help with  retreiving FTP files   Copyright (C) 2000 Kalum Somaratna       This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef HAVE_CONFIG_H#  include <config.h>#endif				/*				 * HAVE_CONFIG_H 				 */#include <stdio.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <errno.h>#include <ctype.h>#include <netdb.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <signal.h>#include <setjmp.h>#include <assert.h>#include <pthread.h>#ifdef HAVE_NCURSES_H#include <ncurses.h>#else#include <curses.h>#endif				/*				 * HAVE_CURSES 				 */#include "connect.h"#include "resume.h"#include "ftp.h"#include "ftp-retr.h"#include "main.h"#include "mainconf.h"#include "netrc.h"#include "runtime.h"#include "misc.h"#include "debug.h"#include <fcntl.h>void clean_ftpsocks(void *cdata){    int flags;    connection_data *connection = (connection_data *) cdata;    debug_prz("in clean ftp sock\n");    if (connection->data_sock > 0)    {	flags = fcntl(connection->data_sock, F_GETFD, 0);	if (flags == -1)	{	    debug_prz("data sock invalid\n");	} else	    close(connection->data_sock);    }    if (connection->control_sock > 0)    {	flags = fcntl(connection->control_sock, F_GETFD, 0);	if (flags == -1)	{	    debug_prz("control sock invalid\n");	} else	    close(connection->control_sock);    }}/* * function to get a file chunk through ftp */uerr_t ftp_get_file_chunk(connection_data * connection){    char *user, *passwd;    unsigned char pasv_addr[6];	/*				 * for PASV 				 */    int passive_mode = FALSE;    uerr_t err;    netrc_entry *netrc_ent;    int tos = IPTOS_THROUGHPUT;    extern pthread_mutex_t status_change_mutex;    extern pthread_cond_t connecting_cond;    /*     * set the thread attributes      */    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);    /*     * did we get a filename?      */    assert(connection->localfile != NULL);    assert(connection->file_mode != NULL);    /*clear the socks */    connection->control_sock = 0;    connection->data_sock = 0;    /*     * if there is nothing to download then return      */    if (connection->status == COMPLETED)    {	gettimeofday(&connection->time_begin, NULL);	return FTPOK;    }    /* Broadcast the condition here */    pthread_mutex_lock(&status_change_mutex);    /* Change the connection status */    connection->status = CONNECTING;    pthread_cond_broadcast(&connecting_cond);    pthread_mutex_unlock(&status_change_mutex);    err = ftp_connect_to_server(&(connection->control_sock),				connection->u.host, connection->u.port);    if (err != FTPOK)    {	if (err == FTPCONREFUSED)	{	    close(connection->control_sock);	    connection->status = CONREJECT;	    /*	     * message("Login was not allowed by the server!"); 	     */	    return err;	} else	{	    message("Error connecting to %s", connection->u.host);	    connection->status = REMOTEFATAL;	    return err;	}    }    message("connect ok");    user = connection->u.user;    passwd = connection->u.passwd;    /*     * Use .netrc if asked to do so.      */    if (rt.use_netrc == TRUE)    {	netrc_ent = search_netrc(rt.netrc_list, connection->u.host);	if (netrc_ent != NULL)	{	    user = netrc_ent->account;	    passwd = netrc_ent->password;	}    }    user = user ? user : DEFAULT_FTP_USER;    passwd = passwd ? passwd : DEFAULT_FTP_PASSWD;    message("Logging in as user %s password %s", user, passwd);    connection->status = LOGGININ;    /*     * if the login was refused the send  FTPLOGREFUSED      */    err = ftp_login(connection->control_sock, user, passwd);    if (err != FTPOK)    {	if (err == FTPLOGREFUSED)	{	    close(connection->control_sock);	    connection->status = LOGINFAIL;	    /*	     * message("Login was not allowed by the server!"); 	     */	    return err;	} else	{	    message("login failed");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    } else	message("login ok");    err = ftp_binary(connection->control_sock);    if (err != FTPOK)    {	message("binary failed");	close(connection->control_sock);	connection->status = REMOTEFATAL;	return err;    } else	message("binary ok");    /*     * De we need to CWD      */    if (*connection->u.dir)    {	err = ftp_cwd(connection->control_sock, connection->u.dir);	if (err != FTPOK)	{	    message("CWD failed to change to directory %s",		    connection->u.dir);	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	} else	    message("CWD OK");    } else    {	message("CWD is not needed");    }    /*     * If enabled lets try PASV      */    if (rt.use_pasv == TRUE)    {	err = ftp_pasv(connection->control_sock, pasv_addr);	/*	 * If the error is due to the server not supporting PASV then	 * * set the flag and lets try PORT	 */	if (err == FTPNOPASV || err == FTPINVPASV)	{	    message("Server doesn't seem to support PASV");	    passive_mode = FALSE;	}	if (err == FTPOK)	/*				 * server supports PASV 				 */	{	    char dhost[256];	    unsigned short dport;	    snprintf(dhost, sizeof(dhost), "%d.%d.%d.%d",		     pasv_addr[0], pasv_addr[1], pasv_addr[2],		     pasv_addr[3]);	    dport = (pasv_addr[4] << 8) + pasv_addr[5];	    /*	     * message("Connecting to %s %d",dhost,dport);          	     * *delay_ms(500);	     */	    debug_prz("FTP PASV server =%s port=%d\n", dhost, dport);	    err =		connect_to_server(&(connection->data_sock), dhost, dport,				  rt.timeout);	    if (err != NOCONERROR)	    {		message		    ("Error while connecting, according to servers PASV info");		close(connection->control_sock);		connection->status = REMOTEFATAL;		return err;	    }	    /*	     * Everything seems to be ok 	     */	    passive_mode = TRUE;	} else	{	    message("Error while connecting to FTP server for PASV");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    } else    {	/*	 * Ok..since PASV is not to be used... 	 */	passive_mode = FALSE;    }    if (passive_mode == FALSE)	/*				 * try to use PORT instead 				 */    {	err = ftp_get_listen_socket(connection->control_sock,				    &(connection->listen_sock));	if (err != FTPOK)	{	    message("listen failed");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    }    err = ftp_rest(connection->control_sock, connection->remote_startpos);    if (err != FTPOK)    {	message("REST failed");	close(connection->control_sock);	connection->status = REMOTEFATAL;	return err;    }    message("REST ok");    err = ftp_retr(connection->control_sock, connection->u.file);    if (err != FTPOK)    {	message("RETR failed");	close(connection->control_sock);	connection->status = REMOTEFATAL;	return err;    }    message("RETR ok");    if (passive_mode == FALSE)	/*				 * Then we have to accept the connection 				 */    {	err = accept_connection(connection->listen_sock,				&(connection->data_sock));	if (err != ACCEPTOK)	{	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    }    /*     * Lets get the file and store it       * open the file with current mode      */    if (!	(connection->fp =	 fopen(connection->localfile, connection->file_mode)))    {	close(connection->control_sock);	close(connection->data_sock);	connection->status = LOCALFATAL;	return FOPENERR;    }    /*     * prioritize packets      */    setsockopt(connection->data_sock, IPPROTO_IP, IP_TOS,	       (char *) &tos, sizeof(tos));    /*     * Make sure all writes go directly to the file      */    setvbuf(connection->fp, NULL, _IONBF, 0);    connection->status = DOWNLOADING;    /*     * lets store the start time in the connections structure     * if this is the first time we have started      */    if ((connection->time_begin.tv_sec == 0)	&& (connection->time_begin.tv_usec == 0))	gettimeofday(&connection->time_begin, NULL);    err = ftp_retr_fsize_known(connection, connection->fp);    close(connection->control_sock);    close(connection->data_sock);    /*     * no need to close the listen_sock since it is already       * closed by accept connection      */    return err;}/* a function that handles the FTP downloading of a complete file *//* such as when the server doesn't support the REST call */uerr_t ftp_get_file_to_end(connection_data * connection){    uerr_t err;    char *user, *passwd;    unsigned char pasv_addr[6];	/*				 * for PASV 				 */    int passive_mode = FALSE;    int tos = IPTOS_THROUGHPUT;    netrc_entry *netrc_ent;    extern pthread_mutex_t status_change_mutex;    extern pthread_cond_t connecting_cond;    /*     * set the thread attributes      */    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);    /*     * did we get a filename?      */    assert(connection->localfile != NULL);    assert(connection->file_mode != NULL);    /*clear the socks */    connection->control_sock = 0;    connection->data_sock = 0;    /*     * if there is nothing to download then return      */    if (connection->status == COMPLETED)    {	gettimeofday(&connection->time_begin, NULL);	return FTPOK;    }    /* Broadcast the condition here */    pthread_mutex_lock(&status_change_mutex);    /* Change the connection status */    connection->status = CONNECTING;    pthread_cond_broadcast(&connecting_cond);    pthread_mutex_unlock(&status_change_mutex);    err = ftp_connect_to_server(&(connection->control_sock),				connection->u.host, connection->u.port);    if (err != FTPOK)    {	if (err == FTPCONREFUSED)	{	    close(connection->control_sock);	    connection->status = CONREJECT;	    /*	     * message("Login was not allowed by the server!"); 	     */	    return err;	} else	{	    message("Error connecting to %s", connection->u.host);	    connection->status = REMOTEFATAL;	    return err;	}    }    message("connect ok");    user = connection->u.user;    passwd = connection->u.passwd;    /*     * Use .netrc if asked to do so.      */    if (rt.use_netrc == TRUE)    {	netrc_ent = search_netrc(rt.netrc_list, connection->u.host);	if (netrc_ent != NULL)	{	    user = netrc_ent->account;	    passwd = netrc_ent->password;	}    }    user = user ? user : DEFAULT_FTP_USER;    passwd = passwd ? passwd : DEFAULT_FTP_PASSWD;    message("Logging in as user %s password %s", user, passwd);    connection->status = LOGGININ;    err = ftp_login(connection->control_sock, user, passwd);    if (err != FTPOK)    {	if (err == FTPLOGREFUSED)	{	    close(connection->control_sock);	    connection->status = LOGINFAIL;	    /*	     * message("Login was not allowed by the server!"); 	     */	    return err;	} else	{	    message("login failed");	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	}    } else	message("login ok");    err = ftp_binary(connection->control_sock);    if (err != FTPOK)    {	message("binary failed");	close(connection->control_sock);	connection->status = REMOTEFATAL;	return err;    } else	message("binary ok");    /* De we need to CWD */    if (*connection->u.dir)    {	err = ftp_cwd(connection->control_sock, connection->u.dir);	if (err != FTPOK)	{	    message("CWD '%s' failed", connection->u.dir);	    close(connection->control_sock);	    connection->status = REMOTEFATAL;	    return err;	} else	    message("CWD OK");    } else    {	message("CWD not needed");    }    /*     * If enabled lets try PASV      */    if (rt.use_pasv == TRUE)    {	err = ftp_pasv(connection->control_sock, pasv_addr);	/*	 * If the error is due to the server not supporting PASV then	 * set the flag and lets try PORT	 */	if (err == FTPNOPASV || err == FTPINVPASV)	{	    message("Server doesn't seem to support PASV");	    passive_mode = FALSE;	}	if (err == FTPOK)	/*				 * server supports PASV 				 */	{	    char dhost[256];	    unsigned short dport;	    snprintf(dhost, sizeof(dhost), "%d.%d.%d.%d",		     pasv_addr[0], pasv_addr[1], pasv_addr[2],		     pasv_addr[3]);	    dport = (pasv_addr[4] << 8) + pasv_addr[5];	    err =		connect_to_server(&(connection->data_sock), dhost, dport,				  rt.timeout);	    if (err != NOCONERROR)	    {		message("Error while connecting according to PASV");		connection->status = REMOTEFATAL;		close(connection->control_sock);		return err;	    }	    /*	     * Everything seems to be ok 	     */	    passive_mode = TRUE;	} else	{	    message("Error while connecting to FTP server for PASV");	    close(connection->control_sock);

⌨️ 快捷键说明

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