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

📄 ftp_fopen_wrapper.c

📁 php-4.4.7学习linux时下载的源代码
💻 C
字号:
/*   +----------------------------------------------------------------------+   | PHP Version 4                                                        |   +----------------------------------------------------------------------+   | Copyright (c) 1997-2007 The PHP Group                                |   +----------------------------------------------------------------------+   | This source file is subject to version 3.01 of the PHP license,      |   | that is bundled with this package in the file LICENSE, and is        |   | available through the world-wide-web at the following url:           |   | http://www.php.net/license/3_01.txt                                  |   | If you did not receive a copy of the PHP license and are unable to   |   | obtain it through the world-wide-web, please send a note to          |   | license@php.net so we can mail you a copy immediately.               |   +----------------------------------------------------------------------+   | Authors: Rasmus Lerdorf <rasmus@php.net>                             |   |          Jim Winstead <jimw@php.net>                                 |   |          Hartmut Holzgraefe <hholzgra@php.net>                       |   +----------------------------------------------------------------------+ *//* $Id: ftp_fopen_wrapper.c,v 1.38.2.8.2.6 2007/01/01 09:46:48 sebastian Exp $ */#include "php.h"#include "php_globals.h"#include "php_network.h"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifdef PHP_WIN32#include <windows.h>#include <winsock.h>#define O_RDONLY _O_RDONLY#include "win32/param.h"#else#include <sys/param.h>#endif#include "php_standard.h"#include <sys/types.h>#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef PHP_WIN32#include <winsock.h>#elif defined(NETWARE) && defined(USE_WINSOCK)#include <novsock2.h>#else#include <netinet/in.h>#include <netdb.h>#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#endif#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)#undef AF_UNIX#endif#if defined(AF_UNIX)#include <sys/un.h>#endif#include "php_fopen_wrappers.h"static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC){	while (php_stream_gets(stream, buffer, buffer_size-1) &&		   !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) &&			 isdigit((int) buffer[2]) && buffer[3] == ' '));	return strtol(buffer, NULL, 10);}#define GET_FTP_RESULT(stream)	get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC)#define FTPS_ENCRYPT_DATA 1static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper,		php_stream *stream,		php_stream_statbuf *ssb		TSRMLS_DC){	/* For now, we return with a failure code to prevent the underlying	 * file's details from being used instead. */	return -1;}static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper,		php_stream *stream		TSRMLS_DC){	php_stream *controlstream = (php_stream *)stream->wrapperdata;		if (controlstream) {		php_stream_write_string(controlstream, "QUIT\r\n");		php_stream_close(controlstream);		stream->wrapperdata = NULL;	}	return 0;}static php_stream_wrapper_ops ftp_stream_wops = {	php_stream_url_wrap_ftp,	php_stream_ftp_stream_close, /* stream_close */	php_stream_ftp_stream_stat,	NULL, /* stat_url */	NULL, /* opendir */	"FTP"};php_stream_wrapper php_stream_ftp_wrapper =	{	&ftp_stream_wops,	NULL,	1 /* is_url */};/* {{{ php_fopen_url_wrap_ftp */php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC){	php_stream *stream=NULL, *datastream=NULL;	php_url *resource=NULL;	char tmp_line[512];	char ip[sizeof("123.123.123.123")];	unsigned short portno;	char *scratch;	int result;	int i, use_ssl, tmp_len;#ifdef HAVE_OPENSSL_EXT		int use_ssl_on_data=0;	php_stream *reuseid=NULL;#endif		char *tpath, *ttpath, *hoststart=NULL;	size_t file_size = 0;	tmp_line[0] = '\0';	if (strchr(mode, 'a') || strchr(mode, '+')) {		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP does not support simultaneous read/write connections.");		return NULL;	}		resource = php_url_parse((char *) path);	if (resource == NULL || resource->path == NULL)		return NULL;	use_ssl = resource->scheme && (strlen(resource->scheme) > 3) && resource->scheme[3] == 's';	/* use port 21 if one wasn't specified */	if (resource->port == 0)		resource->port = 21;		stream = php_stream_sock_open_host(resource->host, resource->port, SOCK_STREAM, NULL, 0);	if (stream == NULL) {		result = 0; /* silence */		goto errexit;	}	php_stream_context_set(stream, context);	php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);	/* Start talking to ftp server */	result = GET_FTP_RESULT(stream);	if (result > 299 || result < 200) {		php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);		goto errexit;	}#ifdef HAVE_OPENSSL_EXT	if (use_ssl)	{			/* send the AUTH TLS request name */		php_stream_write_string(stream, "AUTH TLS\r\n");		/* get the response */		result = GET_FTP_RESULT(stream);		if (result != 234) {			/* AUTH TLS not supported try AUTH SSL */			php_stream_write_string(stream, "AUTH SSL\r\n");						/* get the response */			result = GET_FTP_RESULT(stream);			if (result != 334) {				use_ssl = 0;			} else {				/* we must reuse the old SSL session id */				/* if we talk to an old ftpd-ssl */				reuseid = stream;			}		} else {			/* encrypt data etc */		}	}		if (use_ssl) {		if (use_ssl && php_stream_sock_ssl_activate(stream, 1) == FAILURE)	{			php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");			php_stream_close(stream);			stream = NULL;			goto errexit;		}			/* set PBSZ to 0 */		php_stream_write_string(stream, "PBSZ 0\r\n");		/* ignore the response */		result = GET_FTP_RESULT(stream);				/* set data connection protection level */#if FTPS_ENCRYPT_DATA		php_stream_write_string(stream, "PROT P\r\n");		/* get the response */		result = GET_FTP_RESULT(stream);		use_ssl_on_data = (result >= 200 && result<=299) || reuseid;#else		php_stream_write_string(stream, "PROT C\r\n");		/* get the response */		result = GET_FTP_RESULT(stream);#endif	}#endif#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) {	\	unsigned char *s = val, *e = s + val_len;	\	while (s < e) {	\		if (iscntrl(*s)) {	\			php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val);	\			goto errexit;	\		}	\		s++;	\	}	\}	/* send the user name */	if (resource->user != NULL) {		tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));				PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")				php_stream_printf(stream TSRMLS_CC, "USER %s\r\n", resource->user);	} else {		php_stream_write_string(stream, "USER anonymous\r\n");	}		/* get the response */	result = GET_FTP_RESULT(stream);		/* if a password is required, send it */	if (result >= 300 && result <= 399) {		php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0);		if (resource->pass != NULL) {			tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));						PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")						php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", resource->pass);		} else {			/* if the user has configured who they are,			   send that as the password */			if (cfg_get_string("from", &scratch) == SUCCESS) {				php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", scratch);			} else {				php_stream_write_string(stream, "PASS anonymous\r\n");			}		}				/* read the response */		result = GET_FTP_RESULT(stream);		if (result > 299 || result < 200) {			php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result);		} else {			php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result);		}	}	if (result > 299 || result < 200)		goto errexit;		/* set the connection to be binary */	php_stream_write_string(stream, "TYPE I\r\n");	result = GET_FTP_RESULT(stream);	if (result > 299 || result < 200)		goto errexit;		/* find out the size of the file (verifying it exists) */	php_stream_printf(stream TSRMLS_CC, "SIZE %s\r\n", resource->path);		/* read the response */	result = GET_FTP_RESULT(stream);	if (mode[0] == 'r') {		char *sizestr;				/* when reading file, it must exist */		if (result > 299 || result < 200) {			errno = ENOENT;			goto errexit;		}				sizestr = strchr(tmp_line, ' ');		if (sizestr) {			sizestr++;			file_size = atoi(sizestr);			php_stream_notify_file_size(context, file_size, tmp_line, result);		}		} else {		/* when writing file, it must NOT exist */		if (result <= 299 && result >= 200) {			errno = EEXIST;			goto errexit;		}	}	/* set up the passive connection */	/* We try EPSV first, needed for IPv6 and works on some IPv4 servers */	php_stream_write_string(stream, "EPSV\r\n");	result = GET_FTP_RESULT(stream);	/* check if we got a 229 response */	if (result != 229) {		/* EPSV failed, let's try PASV */		php_stream_write_string(stream, "PASV\r\n");		result = GET_FTP_RESULT(stream);				/* make sure we got a 227 response */		if (result != 227)			goto errexit;		/* parse pasv command (129, 80, 95, 25, 13, 221) */		tpath = tmp_line;		/* skip over the "227 Some message " part */		for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++);		if (!*tpath)			goto errexit;		/* skip over the host ip, to get the port */		hoststart = tpath;		for (i = 0; i < 4; i++) {			for (; isdigit((int) *tpath); tpath++);			if (*tpath != ',')				goto errexit;			*tpath='.';				tpath++;		}		tpath[-1] = '\0';		memcpy(ip, hoststart, sizeof(ip));		ip[sizeof(ip)-1] = '\0';		hoststart = ip;				/* pull out the MSB of the port */		portno = (unsigned short) strtoul(tpath, &ttpath, 10) * 256;		if (ttpath == NULL) {			/* didn't get correct response from PASV */			goto errexit;		}		tpath = ttpath;		if (*tpath != ',')			goto errexit;		tpath++;		/* pull out the LSB of the port */		portno += (unsigned short) strtoul(tpath, &ttpath, 10);	} else {		/* parse epsv command (|||6446|) */		for (i = 0, tpath = tmp_line + 4; *tpath; tpath++) {			if (*tpath == '|') {				i++;				if (i == 3)					break;			}		}		if (i < 3)			goto errexit;		/* pull out the port */		portno = (unsigned short) strtoul(tpath + 1, &ttpath, 10);	}		if (ttpath == NULL) {		/* didn't get correct response from EPSV/PASV */		goto errexit;	}		php_stream_printf(stream TSRMLS_CC, "%s %s\r\n", (mode[0] == 'r' ? "RETR" : "STOR"), (resource->path != NULL ? resource->path : "/"));		/* open the data channel */	if (hoststart == NULL) {		hoststart = resource->host;	}	datastream = php_stream_sock_open_host(hoststart, portno, SOCK_STREAM, 0, 0);	if (datastream == NULL) {		goto errexit;	}	result = GET_FTP_RESULT(stream);	if (result != 150 && result != 125) {		/* Could not retrieve or send the file 		 * this data will only be sent to us after connection on the data port was initiated.		 */		php_stream_close(datastream);		datastream = NULL;		goto errexit;		}			php_stream_context_set(datastream, context);	php_stream_notify_progress_init(context, 0, file_size);#ifdef HAVE_OPENSSL_EXT	if (use_ssl_on_data && php_stream_sock_ssl_activate_with_method(datastream, 1, SSLv23_method(), reuseid TSRMLS_CC) == FAILURE)	{		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");		php_stream_close(datastream);		datastream = NULL;		goto errexit;	}#endif	/* remember control stream */		datastream->wrapperdata = (zval *)stream;	php_url_free(resource);	return datastream; errexit:	php_url_free(resource);	if (stream) {		php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);		php_stream_close(stream);	}	if (tmp_line[0] != '\0')		php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP server reports %s", tmp_line);	return NULL;}/* }}} *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */

⌨️ 快捷键说明

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