ftp.c
来自「网络爬虫程序」· C语言 代码 · 共 2,200 行 · 第 1/4 页
C
2,200 行
/***************************************************************************//* This code is part of WWW grabber called pavuk *//* Copyright (c) 1997 - 2001 Stefan Ondrejicka *//* Distributed under GPL 2 or later *//***************************************************************************/#include "config.h"#include <ctype.h>#include <errno.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/types.h>#include <time.h>#include <unistd.h>#include <unistd.h>#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#include "absio.h"#include "abstract.h"#include "dns.h"#include "doc.h"#include "errcode.h"#include "ftp.h"#include "http.h"#include "mode.h"#include "myssl.h"#include "net.h"#include "times.h"#include "tools.h"#include "uexit.h"#include "url.h"static ftp_handshake_info *ftp_handshake_info_data_find(char *, int);static int ftp_do_login_handshake_cust(ftp_handshake_info *, doc *, char *, char *);static int ftp_control_write(doc * docp, char *buf, size_t bufsize){ return bufio_write(docp->ftp_control, buf, bufsize);}static int ftp_control_readln(doc * docp, char *buf, int bufsize){ return bufio_readln(docp->ftp_control, buf, bufsize);}/********************************************************//* zistenie navratoveho kodu z FTP servera *//* FIXME: Translate me! *//********************************************************/int ftp_get_response(doc * docp, char **mbuf, int setrc){ char buf[1024]; bool_t end = FALSE; int alen, tlen = 0; char *sresp = NULL; while(!end) { if((alen = ftp_control_readln(docp, buf, sizeof(buf))) > 0) { DEBUG_PROTOS("%s", buf); if(mbuf) { tlen += alen; sresp = _realloc(sresp, tlen + 1); memcpy(sresp + tlen - alen, buf, alen + 1); } if(strlen(buf) > 3) { if(tl_ascii_isdigit(*(buf)) && tl_ascii_isdigit(*(buf + 1)) && tl_ascii_isdigit(*(buf + 2)) && tl_ascii_isspace(*(buf + 3))) end = TRUE; } } else { if(alen) xperror("ftp_get_response"); else xprintf(1, gettext ("ftp_get_response: ftp control connection closed before any response\n")); if(setrc) docp->ftp_respc = 600; return 600; } } if(mbuf) *mbuf = sresp; if(setrc) docp->ftp_respc = _atoi(buf); return _atoi(buf);}static bufio *ftp_open_data_finish(doc * docp){ if(docp->ftp_data_con_finished) return docp->datasock; if(!cfg.ftp_activec || (priv_cfg.ftp_proxy && cfg.ftp_dirtyp)) { if(priv_cfg.ftp_proxy && cfg.ftp_dirtyp) { if(!(docp->datasock = bufio_sock_fdopen(net_connect(priv_cfg.ftp_proxy, cfg.ftp_proxy_port, docp)))) { if(_h_errno_ != 0) xherror(priv_cfg.ftp_proxy); else xperror("net_connect"); docp->errcode = ERR_PROXY_CONNECT; return NULL; } if(http_dumy_proxy_connect(docp, docp->ftp_pasv_host, docp->ftp_pasv_port, priv_cfg.ftp_proxy, cfg.ftp_proxy_port)) { docp->errcode = ERR_PROXY_CONNECT; bufio_close(docp->datasock); docp->datasock = NULL; return NULL; } } else { if(!(docp->datasock = bufio_sock_fdopen(net_connect(docp->ftp_pasv_host, docp->ftp_pasv_port, docp)))) { if(_h_errno_ != 0) xherror(priv_cfg.ftp_proxy); else xperror("net_connect"); docp->errcode = ERR_FTP_DATACON; return NULL; } } } else { bufio *dsock = bufio_sock_fdopen(net_accept(bufio_getfd(docp->datasock))); bufio_close(docp->datasock); docp->datasock = dsock; }#ifdef IP_TOS#ifdef IPTOS_THROUGHPUT if(docp->datasock) { int v = IPTOS_THROUGHPUT; if(setsockopt(bufio_getfd(docp->datasock), IPPROTO_IP, IP_TOS, (char *) &v, sizeof(v))) { xperror(gettext("ftp: setsockopt TOS - THROUGHPUT failed")); } }#endif#endif#ifdef USE_SSL if(docp->doc_url->type == URLT_FTPS) { bufio *ssl_sock; ssl_sock = my_ssl_do_connect(docp, docp->datasock, bufio_get_ssl_hook_data(docp->ftp_control)); if(!ssl_sock) { if(!docp->errcode) docp->errcode = ERR_FTPS_DATASSLCONNECT; bufio_close(docp->datasock); docp->datasock = NULL; } else docp->datasock = ssl_sock; }#endif if(docp->datasock) docp->ftp_data_con_finished = TRUE; return docp->datasock;}static int ftp_open_data_init(doc * docp){ char buf[256]; char *mbuf; struct sockaddr_storage scaddr; struct sockaddr *caddr; int reply; socklen_t n; caddr = (struct sockaddr *) &scaddr; n = sizeof(scaddr); if(getsockname(bufio_getfd(docp->ftp_control), caddr, &n)) { xperror("FTP control getsockname"); docp->datasock = NULL; return -1; } if(!cfg.ftp_activec || (priv_cfg.ftp_proxy && cfg.ftp_dirtyp)) {#ifdef HAVE_INET6 if(caddr->sa_family == AF_INET6) { sprintf(buf, "EPSV\r\n"); DEBUG_PROTOC("%s", buf); ftp_control_write(docp, buf, strlen(buf)); mbuf = NULL; if((reply = ftp_get_response(docp, &mbuf, TRUE)) >= 400) { int h[16], p[2], hal, af, pal; abs_addr haddr; _free(mbuf) if(reply == 600) { docp->ftp_fatal_err = TRUE; return -1; } sprintf(buf, "LPSV\r\n"); DEBUG_PROTOC("%s", buf); ftp_control_write(docp, buf, strlen(buf)); mbuf = NULL; if((reply = ftp_get_response(docp, &mbuf, TRUE)) >= 400) { docp->ftp_fatal_err = (reply == 600); _free(mbuf); return -1; } n = sscanf(mbuf, "%d %*[^0-9]%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &reply, &af, &hal, &h[0], &h[1], &h[2], &h[3], &h[4], &h[5], &h[6], &h[7], &h[8], &h[9], &h[10], &h[11], &h[12], &h[13], &h[14], &h[15], &pal, &p[0], &p[1]); if(n != 22 || reply != 228 || af != 6 || hal != 16 || pal != 2) { xprintf(1, gettext("Error parsing FTP response to %s command - %s\n"), "LPSV", mbuf); _free(mbuf); return -1; } _free(mbuf); docp->ftp_pasv_port = (p[0] << 8) + p[1]; haddr.family = AF_INET6; for(n = 0; n < 16; n++) haddr.addr[n] = (unsigned char) h[n]; docp->ftp_pasv_host = dns_get_abs_addr_ip(&haddr); } else { int port; char d[4]; n = sscanf(mbuf, "%d %*[^0-9(]\(%c%c%c%d%c", &reply, &d[0], &d[1], &d[2], &port, &d[3]); if(n != 6 || reply != 229 || d[0] != d[1] || d[0] != d[2] || d[0] != d[3]) { xprintf(1, gettext("Error parsing FTP response to %s command - %s\n"), "EPSV", mbuf); _free(mbuf); return -1; } _free(mbuf); docp->ftp_pasv_port = port; docp->ftp_pasv_host = dns_get_sockaddr_ip(caddr); } } else#endif { int h0, h1, h2, h3, p0, p1; sprintf(buf, "PASV\r\n"); DEBUG_PROTOC("%s", buf); ftp_control_write(docp, buf, strlen(buf)); mbuf = NULL; if((reply = ftp_get_response(docp, &mbuf, TRUE)) >= 400) { docp->ftp_fatal_err = (reply == 600); _free(mbuf); return -1; } if(!mbuf) { return -1; } n = sscanf(mbuf, "%d %*[^0-9]%d,%d,%d,%d,%d,%d", &reply, &h0, &h1, &h2, &h3, &p0, &p1); if(n != 7 || reply != 227) { xprintf(1, gettext("Error parsing FTP response to %s command - %s\n"), "PASV", mbuf); _free(mbuf); return -1; } _free(mbuf); docp->ftp_pasv_port = (p0 << 8) + p1; sprintf(buf, "%d.%d.%d.%d", h0, h1, h2, h3); docp->ftp_pasv_host = tl_strdup(buf); } } else { struct sockaddr_storage saddr; struct sockaddr *addr; char *p; int port; addr = (struct sockaddr *) &saddr; if(!docp->datasock) { int bfd; abs_addr laddr; memset(laddr.addr, '\0', sizeof(laddr.addr)); laddr.family = caddr->sa_family; if(priv_cfg.local_ip) { memcpy(laddr.addr, cfg.local_ip_addr.addr, sizeof(laddr.addr)); laddr.family = cfg.local_ip_addr.family; } bfd = net_bindport(&laddr, cfg.active_ftp_min_port, cfg.active_ftp_max_port); if(!(docp->datasock = bufio_sock_fdopen(bfd))) { xperror("bind"); return -1; } } n = sizeof(saddr); if(getsockname(bufio_getfd(docp->datasock), addr, &n)) { xperror("FTP data getsockname"); bufio_close(docp->datasock); docp->datasock = NULL; return -1; } port = dns_get_sockaddr_port(addr); mbuf = dns_get_sockaddr_ip(caddr);#ifdef HAVE_INET6 if(caddr->sa_family == AF_INET6) { snprintf(buf, sizeof(buf), "EPRT |2|%s|%d|\r\n", mbuf, port); _free(mbuf); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if((reply = ftp_get_response(docp, NULL, TRUE)) >= 400) { unsigned char *h; if(reply == 600) { bufio_close(docp->datasock); docp->datasock = NULL; docp->ftp_fatal_err = TRUE; return -1; } h = ((struct sockaddr_in6 *) caddr)->sin6_addr.s6_addr; sprintf(buf, "LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d\r\n", h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15], port / 256, port % 256); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if((reply = ftp_get_response(docp, NULL, TRUE)) >= 400) { bufio_close(docp->datasock); docp->datasock = NULL; docp->ftp_fatal_err = (reply == 600); return -1; } } } else#endif { for(p = mbuf; (p = strchr(p, '.')); *p = ','); snprintf(buf, sizeof(buf), "PORT %s,%d,%d\r\n", mbuf, port / 256, port % 256); _free(mbuf); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if((reply = ftp_get_response(docp, NULL, TRUE)) >= 400) { bufio_close(docp->datasock); docp->datasock = NULL; docp->ftp_fatal_err = (reply == 600); return -1; } } } return 0;}static int ftp_do_login_handshake(doc * docp, char *ruser, char *user, char *password){ ftp_handshake_info *fhi; fhi = ftp_handshake_info_data_find(docp->doc_url->p.ftp.host, docp->doc_url->p.ftp.port); if(!fhi) fhi = ftp_handshake_info_data_find("", DEFAULT_FTP_PORT); if(fhi) { if(ftp_do_login_handshake_cust(fhi, docp, ruser, password)) { docp->ftp_fatal_err = TRUE; docp->errcode = ERR_FTP_LOGIN_HANDSHAKE; return -1; } } else { char buf[2048]; int reply; if(priv_cfg.ftp_proxy_user && priv_cfg.ftp_proxy && !cfg.ftp_via_http && !cfg.ftp_dirtyp) { snprintf(buf, sizeof(buf), "USER %s\r\n", priv_cfg.ftp_proxy_user); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if((reply = ftp_get_response(docp, NULL, TRUE)) >= 400) { docp->ftp_fatal_err = TRUE; docp->errcode = ERR_FTP_BPROXYUSER; return -1; } } else reply = 0; if(priv_cfg.ftp_proxy_pass && priv_cfg.ftp_proxy && !cfg.ftp_via_http && !cfg.ftp_dirtyp) { if(reply == 331) /*** we need password ***/ { snprintf(buf, sizeof(buf), "PASS %s\r\n", priv_cfg.ftp_proxy_pass); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if(ftp_get_response(docp, NULL, TRUE) >= 400) { docp->ftp_fatal_err = TRUE; docp->errcode = ERR_FTP_BPROXYPASS; return -1; } } } snprintf(buf, sizeof(buf), "USER %s\r\n", user); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if((reply = ftp_get_response(docp, NULL, TRUE)) >= 400) { docp->ftp_fatal_err = TRUE; docp->errcode = ERR_FTP_BUSER; return -1; } if(reply == 331) /*** we need password ***/ { snprintf(buf, sizeof(buf), "PASS %s\r\n", password); ftp_control_write(docp, buf, strlen(buf)); DEBUG_PROTOC("%s", buf); if(ftp_get_response(docp, NULL, TRUE) >= 400) { docp->ftp_fatal_err = TRUE; docp->errcode = ERR_FTP_BPASS; return -1; } } } return 0;}#define CLOSE_CONTROL \ bufio_close(docp->ftp_control);\ docp->ftp_control = NULL;static bufio *ftp_open_control_connection(doc * docp, char *host, int port, char *ruser, char *user, char *password){ docp->errcode = ERR_NOERROR; docp->ftp_fatal_err = FALSE; docp->ftp_respc = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?