2000-10-13 08:09:31 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 16:18:22 +08:00
| PHP Version 5 |
2000-10-13 08:09:31 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-08-03 22:08:58 +08:00
| Copyright ( c ) 1997 - 2005 The PHP Group |
2000-10-13 08:09:31 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-06-11 04:04:29 +08:00
| This source file is subject to version 3.0 of the PHP license , |
2000-10-13 08:09:31 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_0.txt. |
2000-10-13 08:09:31 +08:00
| 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 . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 16:29:35 +08:00
| Authors : Rasmus Lerdorf < rasmus @ php . net > |
2000-10-13 08:09:31 +08:00
| Jim Winstead < jimw @ php . net > |
| Hartmut Holzgraefe < hholzgra @ php . net > |
2003-05-15 02:02:10 +08:00
| Sara Golemon < pollita @ php . net > |
2000-10-13 08:09:31 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include "php.h"
# include "php_globals.h"
2000-10-13 17:13:01 +08:00
# include "php_network.h"
2000-10-13 08:09:31 +08:00
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# ifdef PHP_WIN32
2003-02-16 11:48:49 +08:00
# include <winsock2.h>
2000-10-13 08:09:31 +08:00
# 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
2003-02-16 11:48:49 +08:00
# include <winsock2.h>
2002-09-05 22:25:07 +08:00
# elif defined(NETWARE) && defined(USE_WINSOCK)
# include <novsock2.h>
2000-10-13 08:09:31 +08:00
# else
# include <netinet/in.h>
# include <netdb.h>
2001-01-22 01:29:15 +08:00
# if HAVE_ARPA_INET_H
2000-10-13 08:09:31 +08:00
# include <arpa/inet.h>
# endif
2001-01-22 01:29:15 +08:00
# endif
2000-10-13 08:09:31 +08:00
2002-09-05 22:25:07 +08:00
# if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
2000-10-13 08:09:31 +08:00
# undef AF_UNIX
# endif
# if defined(AF_UNIX)
# include <sys/un.h>
# endif
# include "php_fopen_wrappers.h"
2002-04-11 06:42:32 +08:00
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 ) ;
2000-10-13 08:09:31 +08:00
}
2002-04-11 06:42:32 +08:00
# define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC)
2000-10-13 08:09:31 +08:00
2002-09-09 00:45:32 +08:00
# define FTPS_ENCRYPT_DATA 1
2002-03-28 08:49:00 +08:00
static 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 ;
}
2002-09-09 03:11:07 +08:00
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 ;
}
2003-04-25 04:32:14 +08:00
/* {{{ php_ftp_fopen_connect
2001-06-06 21:06:12 +08:00
*/
2003-04-25 04:32:14 +08:00
static php_stream * php_ftp_fopen_connect ( php_stream_wrapper * wrapper , char * path , char * mode , int options , char * * opened_path , php_stream_context * context ,
2003-04-26 09:55:31 +08:00
php_stream * * preuseid , php_url * * presource , int * puse_ssl , int * puse_ssl_on_data TSRMLS_DC )
2000-10-13 08:09:31 +08:00
{
2003-04-25 04:32:14 +08:00
php_stream * stream = NULL , * reuseid = NULL ;
php_url * resource = NULL ;
2005-05-08 00:07:59 +08:00
int result , use_ssl , use_ssl_on_data = 0 , tmp_len ;
2000-10-13 08:09:31 +08:00
char * scratch ;
2003-04-25 04:32:14 +08:00
char tmp_line [ 512 ] ;
2005-07-14 07:28:22 +08:00
char * transport ;
int transport_len ;
2002-11-26 06:53:57 +08:00
2004-01-25 08:30:50 +08:00
resource = php_url_parse ( path ) ;
2004-08-16 09:41:14 +08:00
if ( resource = = NULL | | resource - > path = = NULL ) {
if ( resource & & presource ) {
* presource = resource ;
}
2000-10-13 08:09:31 +08:00
return NULL ;
2004-08-16 09:41:14 +08:00
}
2002-03-16 05:03:08 +08:00
2002-09-09 00:45:32 +08:00
use_ssl = resource - > scheme & & ( strlen ( resource - > scheme ) > 3 ) & & resource - > scheme [ 3 ] = = ' s ' ;
2000-10-13 08:09:31 +08:00
/* use port 21 if one wasn't specified */
if ( resource - > port = = 0 )
resource - > port = 21 ;
2005-07-14 07:28:22 +08:00
transport_len = spprintf ( & transport , 0 , " tcp://%s:%d " , resource - > host , resource - > port ) ;
2005-07-15 23:45:43 +08:00
stream = php_stream_xport_create ( transport , transport_len , REPORT_ERRORS , STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT , NULL , NULL , context , NULL , NULL ) ;
2005-07-14 07:28:22 +08:00
efree ( transport ) ;
2002-11-05 19:17:45 +08:00
if ( stream = = NULL ) {
result = 0 ; /* silence */
2003-04-25 04:32:14 +08:00
goto connect_errexit ;
2002-11-05 19:17:45 +08:00
}
2002-03-16 05:03:08 +08:00
2002-04-11 06:42:32 +08:00
php_stream_context_set ( stream , context ) ;
php_stream_notify_info ( context , PHP_STREAM_NOTIFY_CONNECT , NULL , 0 ) ;
2000-10-13 08:09:31 +08:00
/* Start talking to ftp server */
2002-04-11 06:42:32 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result > 299 | | result < 200 ) {
php_stream_notify_error ( context , PHP_STREAM_NOTIFY_FAILURE , tmp_line , result ) ;
2003-04-25 04:32:14 +08:00
goto connect_errexit ;
2002-04-11 06:42:32 +08:00
}
2000-10-13 08:09:31 +08:00
2002-09-09 00:45:32 +08:00
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 ;
2002-09-09 06:26:11 +08:00
} else {
/* we must reuse the old SSL session id */
/* if we talk to an old ftpd-ssl */
reuseid = stream ;
2002-09-09 00:45:32 +08:00
}
} else {
/* encrypt data etc */
}
}
if ( use_ssl ) {
2003-02-28 01:43:38 +08:00
if ( php_stream_xport_crypto_setup ( stream ,
STREAM_CRYPTO_METHOD_SSLv23_CLIENT , NULL TSRMLS_CC ) < 0
| | php_stream_xport_crypto_enable ( stream , 1 TSRMLS_CC ) < 0 ) {
2002-09-09 00:45:32 +08:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Unable to activate SSL mode " ) ;
php_stream_close ( stream ) ;
stream = NULL ;
2003-04-25 04:32:14 +08:00
goto connect_errexit ;
2002-09-09 00:45:32 +08:00
}
/* 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 ) ;
2002-09-09 06:26:11 +08:00
use_ssl_on_data = ( result > = 200 & & result < = 299 ) | | reuseid ;
2002-09-09 00:45:32 +08:00
# else
php_stream_write_string ( stream , " PROT C \r \n " ) ;
/* get the response */
result = GET_FTP_RESULT ( stream ) ;
# endif
}
2005-05-08 00:07:59 +08:00
# 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 connect_errexit ; \
} \
s + + ; \
} \
}
2000-10-13 08:09:31 +08:00
/* send the user name */
if ( resource - > user ! = NULL ) {
2005-05-08 00:07:59 +08:00
tmp_len = php_raw_url_decode ( resource - > user , strlen ( resource - > user ) ) ;
PHP_FTP_CNTRL_CHK ( resource - > user , tmp_len , " Invalid login %s " )
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " USER %s \r \n " , resource - > user ) ;
2000-10-13 08:09:31 +08:00
} else {
2005-10-11 22:33:51 +08:00
php_stream_write_string ( stream , " USER anonymous \r \n " ) ;
2000-10-13 08:09:31 +08:00
}
/* get the response */
2002-04-11 06:42:32 +08:00
result = GET_FTP_RESULT ( stream ) ;
2000-10-13 08:09:31 +08:00
/* if a password is required, send it */
if ( result > = 300 & & result < = 399 ) {
2002-04-11 06:42:32 +08:00
php_stream_notify_info ( context , PHP_STREAM_NOTIFY_AUTH_REQUIRED , tmp_line , 0 ) ;
2000-10-13 08:09:31 +08:00
if ( resource - > pass ! = NULL ) {
2005-05-08 00:07:59 +08:00
tmp_len = php_raw_url_decode ( resource - > pass , strlen ( resource - > pass ) ) ;
PHP_FTP_CNTRL_CHK ( resource - > pass , tmp_len , " Invalid password %s " )
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " PASS %s \r \n " , resource - > pass ) ;
2000-10-13 08:09:31 +08:00
} else {
/* if the user has configured who they are,
send that as the password */
if ( cfg_get_string ( " from " , & scratch ) = = SUCCESS ) {
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " PASS %s \r \n " , scratch ) ;
2000-10-13 08:09:31 +08:00
} else {
2005-10-11 22:33:51 +08:00
php_stream_write_string ( stream , " PASS anonymous \r \n " ) ;
2000-10-13 08:09:31 +08:00
}
}
2005-10-11 22:33:51 +08:00
2000-10-13 08:09:31 +08:00
/* read the response */
2002-04-11 06:42:32 +08:00
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 ) ;
}
2000-10-13 08:09:31 +08:00
}
2003-04-25 04:32:14 +08:00
if ( result > 299 | | result < 200 ) {
goto connect_errexit ;
}
if ( puse_ssl ) {
* puse_ssl = use_ssl ;
}
if ( puse_ssl_on_data ) {
* puse_ssl_on_data = use_ssl_on_data ;
}
if ( preuseid ) {
* preuseid = reuseid ;
}
if ( presource ) {
* presource = resource ;
}
return stream ;
2005-05-08 00:07:59 +08:00
connect_errexit :
if ( resource ) {
php_url_free ( resource ) ;
}
2003-04-25 04:32:14 +08:00
if ( stream ) {
php_stream_close ( stream ) ;
}
return NULL ;
}
/* }}} */
/* {{{ php_fopen_do_pasv
*/
2003-04-26 09:55:31 +08:00
static unsigned short php_fopen_do_pasv ( php_stream * stream , char * ip , int ip_size , char * * phoststart TSRMLS_DC )
2003-04-25 04:32:14 +08:00
{
char tmp_line [ 512 ] ;
int result , i ;
unsigned short portno ;
char * tpath , * ttpath , * hoststart = NULL ;
/* 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 ) {
return 0 ;
}
/* 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 ) {
return 0 ;
}
/* skip over the host ip, to get the port */
hoststart = tpath ;
for ( i = 0 ; i < 4 ; i + + ) {
for ( ; isdigit ( ( int ) * tpath ) ; tpath + + ) ;
if ( * tpath ! = ' , ' ) {
return 0 ;
}
* tpath = ' . ' ;
tpath + + ;
}
tpath [ - 1 ] = ' \0 ' ;
memcpy ( ip , hoststart , ip_size ) ;
ip [ ip_size - 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 */
return 0 ;
}
tpath = ttpath ;
if ( * tpath ! = ' , ' ) {
return 0 ;
}
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 ) {
return 0 ;
}
/* pull out the port */
portno = ( unsigned short ) strtoul ( tpath + 1 , & ttpath , 10 ) ;
}
2000-10-13 08:09:31 +08:00
2003-04-25 04:32:14 +08:00
if ( ttpath = = NULL ) {
/* didn't get correct response from EPSV/PASV */
return 0 ;
}
if ( phoststart ) {
* phoststart = hoststart ;
}
return portno ;
}
/* }}} */
/* {{{ 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 ;
2003-05-17 14:21:34 +08:00
char * hoststart = NULL ;
2003-06-18 11:26:29 +08:00
int result = 0 , use_ssl , use_ssl_on_data = 0 ;
2003-04-25 04:32:14 +08:00
php_stream * reuseid = NULL ;
size_t file_size = 0 ;
zval * * tmpzval ;
int allow_overwrite = 0 ;
2003-04-25 05:21:41 +08:00
int read_write = 0 ;
2005-07-14 07:28:22 +08:00
char * transport ;
int transport_len ;
2003-04-25 04:32:14 +08:00
tmp_line [ 0 ] = ' \0 ' ;
2003-04-25 05:21:41 +08:00
if ( strpbrk ( mode , " r+ " ) ) {
read_write = 1 ; /* Open for reading */
}
if ( strpbrk ( mode , " wa+ " ) ) {
if ( read_write ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " FTP does not support simultaneous read/write connections. " ) ;
return NULL ;
}
if ( strchr ( mode , ' a ' ) ) {
read_write = 3 ; /* Open for Appending */
} else {
read_write = 2 ; /* Open for writting */
}
}
if ( ! read_write ) {
/* No mode specified? */
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Unknown file open mode. " ) ;
2003-04-25 04:32:14 +08:00
return NULL ;
}
2004-07-24 12:14:26 +08:00
if ( context & &
php_stream_context_get_option ( context , " ftp " , " proxy " , & tmpzval ) = = SUCCESS ) {
if ( read_write = = 1 ) {
/* Use http wrapper to proxy ftp request */
return php_stream_url_wrap_http ( wrapper , path , mode , options , opened_path , context STREAMS_CC TSRMLS_CC ) ;
} else {
/* ftp proxy is read-only */
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " FTP proxy may only be used in read mode " ) ;
return NULL ;
}
}
2003-04-26 09:55:31 +08:00
stream = php_ftp_fopen_connect ( wrapper , path , mode , options , opened_path , context , & reuseid , & resource , & use_ssl , & use_ssl_on_data TSRMLS_CC ) ;
2003-04-25 05:21:41 +08:00
if ( ! stream ) {
2003-04-25 06:25:33 +08:00
goto errexit ;
2003-04-25 05:21:41 +08:00
}
2003-04-25 04:32:14 +08:00
2000-10-13 08:09:31 +08:00
/* set the connection to be binary */
2002-03-16 05:03:08 +08:00
php_stream_write_string ( stream , " TYPE I \r \n " ) ;
2002-04-11 06:42:32 +08:00
result = GET_FTP_RESULT ( stream ) ;
2000-10-13 08:09:31 +08:00
if ( result > 299 | | result < 200 )
goto errexit ;
/* find out the size of the file (verifying it exists) */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " SIZE %s \r \n " , resource - > path ) ;
2000-10-13 08:09:31 +08:00
/* read the response */
2002-04-11 06:42:32 +08:00
result = GET_FTP_RESULT ( stream ) ;
2003-04-25 05:21:41 +08:00
if ( read_write = = 1 ) {
/* Read Mode */
2002-04-11 06:42:32 +08:00
char * sizestr ;
2000-10-13 08:09:31 +08:00
/* when reading file, it must exist */
if ( result > 299 | | result < 200 ) {
errno = ENOENT ;
2002-03-16 05:03:08 +08:00
goto errexit ;
2000-10-13 08:09:31 +08:00
}
2002-04-11 06:42:32 +08:00
sizestr = strchr ( tmp_line , ' ' ) ;
if ( sizestr ) {
sizestr + + ;
file_size = atoi ( sizestr ) ;
php_stream_notify_file_size ( context , file_size , tmp_line , result ) ;
}
2003-04-25 05:21:41 +08:00
} else if ( read_write = = 2 ) {
/* when writing file (but not appending), it must NOT exist, unless a context option exists which allows it */
2003-04-22 12:13:09 +08:00
if ( context & & php_stream_context_get_option ( context , " ftp " , " overwrite " , & tmpzval ) = = SUCCESS ) {
allow_overwrite = Z_LVAL_PP ( tmpzval ) ;
}
2000-10-13 08:09:31 +08:00
if ( result < = 299 & & result > = 200 ) {
2003-04-22 12:13:09 +08:00
if ( allow_overwrite ) {
/* Context permits overwritting file,
so we just delete whatever ' s there in preparation */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " DELE %s \r \n " , resource - > path ) ;
2003-04-22 12:13:09 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result > = 300 | | result < = 199 ) {
goto errexit ;
}
} else {
2004-05-18 04:31:59 +08:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Remote file already exists and overwrite context option not specified. " ) ;
2003-04-22 12:13:09 +08:00
errno = EEXIST ;
goto errexit ;
}
2000-10-13 08:09:31 +08:00
}
}
2002-04-11 06:42:32 +08:00
2000-10-13 08:09:31 +08:00
/* set up the passive connection */
2003-04-26 09:55:31 +08:00
portno = php_fopen_do_pasv ( stream , ip , sizeof ( ip ) , & hoststart TSRMLS_CC ) ;
2000-10-13 08:09:31 +08:00
2003-04-25 04:32:14 +08:00
if ( ! portno ) {
2000-10-13 08:09:31 +08:00
goto errexit ;
}
2003-04-25 04:32:14 +08:00
/* Send RETR/STOR command */
2003-04-25 05:21:41 +08:00
if ( read_write = = 1 ) {
2003-08-21 05:59:29 +08:00
/* set resume position if applicable */
if ( context & &
php_stream_context_get_option ( context , " ftp " , " resume_pos " , & tmpzval ) = = SUCCESS & &
Z_TYPE_PP ( tmpzval ) = = IS_LONG & &
Z_LVAL_PP ( tmpzval ) > 0 ) {
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " REST %ld \r \n " , Z_LVAL_PP ( tmpzval ) ) ;
2003-08-21 05:59:29 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 300 | | result > 399 ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Unable to resume from offset %d " , Z_LVAL_PP ( tmpzval ) ) ;
goto errexit ;
}
}
2000-10-13 08:09:31 +08:00
/* retrieve file */
2005-10-11 22:33:51 +08:00
memcpy ( tmp_line , " RETR " , 4 ) ;
2003-04-25 05:21:41 +08:00
} else if ( read_write = = 2 ) {
/* Write new file */
2005-10-11 22:33:51 +08:00
memcpy ( tmp_line , " STOR " , 4 ) ;
2003-04-25 05:21:41 +08:00
} else {
/* Append */
2005-10-11 22:33:51 +08:00
memcpy ( tmp_line , " APPE " , 4 ) ;
2000-10-13 08:09:31 +08:00
}
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " %s %s \r \n " , tmp_line , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ;
2002-11-26 06:00:52 +08:00
/* open the data channel */
if ( hoststart = = NULL ) {
hoststart = resource - > host ;
}
2005-07-14 07:28:22 +08:00
transport_len = spprintf ( & transport , 0 , " tcp://%s:%d " , hoststart , portno ) ;
2005-07-15 23:45:43 +08:00
datastream = php_stream_xport_create ( transport , transport_len , REPORT_ERRORS , STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT , NULL , NULL , context , NULL , NULL ) ;
2005-07-14 07:28:22 +08:00
efree ( transport ) ;
2002-11-26 06:00:52 +08:00
if ( datastream = = NULL ) {
goto errexit ;
}
2002-09-09 00:45:32 +08:00
2002-11-26 06:00:52 +08:00
result = GET_FTP_RESULT ( stream ) ;
2003-02-25 12:20:22 +08:00
if ( result ! = 150 & & result ! = 125 ) {
2002-11-26 06:00:52 +08:00
/* 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 ;
}
2002-09-09 00:45:32 +08:00
php_stream_context_set ( datastream , context ) ;
2002-04-11 06:42:32 +08:00
php_stream_notify_progress_init ( context , 0 , file_size ) ;
2005-07-14 07:28:22 +08:00
if ( use_ssl_on_data & & ( php_stream_xport_crypto_setup ( datastream ,
2003-02-28 01:43:38 +08:00
STREAM_CRYPTO_METHOD_SSLv23_CLIENT , NULL TSRMLS_CC ) < 0 | |
2005-07-14 07:28:22 +08:00
php_stream_xport_crypto_enable ( datastream , 1 TSRMLS_CC ) < 0 ) ) {
2003-02-28 01:43:38 +08:00
2002-09-09 00:45:32 +08:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Unable to activate SSL mode " ) ;
php_stream_close ( datastream ) ;
datastream = NULL ;
goto errexit ;
}
2002-09-09 06:26:11 +08:00
/* remember control stream */
datastream - > wrapperdata = ( zval * ) stream ;
2001-06-11 23:14:04 +08:00
php_url_free ( resource ) ;
2002-09-09 00:45:32 +08:00
return datastream ;
2000-10-13 08:09:31 +08:00
errexit :
2003-05-15 02:02:10 +08:00
if ( resource ) {
php_url_free ( resource ) ;
}
2002-04-11 06:42:32 +08:00
if ( stream ) {
php_stream_notify_error ( context , PHP_STREAM_NOTIFY_FAILURE , tmp_line , result ) ;
2002-03-16 05:03:08 +08:00
php_stream_close ( stream ) ;
2002-04-11 06:42:32 +08:00
}
if ( tmp_line [ 0 ] ! = ' \0 ' )
2002-08-11 22:29:01 +08:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " FTP server reports %s " , tmp_line ) ;
2000-10-13 08:09:31 +08:00
return NULL ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
2001-06-05 21:12:10 +08:00
2003-04-25 04:32:14 +08:00
/* {{{ php_ftp_dirsteam_read
*/
static size_t php_ftp_dirstream_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
{
php_stream_dirent * ent = ( php_stream_dirent * ) buf ;
php_stream * innerstream = ( php_stream * ) stream - > abstract ;
size_t tmp_len ;
char * basename ;
2003-12-10 15:15:28 +08:00
size_t basename_len ;
2003-04-25 04:32:14 +08:00
if ( count ! = sizeof ( php_stream_dirent ) ) {
return 0 ;
}
if ( php_stream_eof ( innerstream ) ) {
return 0 ;
}
if ( ! php_stream_get_line ( innerstream , ent - > d_name , sizeof ( ent - > d_name ) , & tmp_len ) ) {
return 0 ;
}
2003-05-05 21:46:14 +08:00
2003-12-11 05:23:35 +08:00
php_basename ( ent - > d_name , tmp_len , NULL , 0 , & basename , & basename_len TSRMLS_CC ) ;
2003-05-05 21:46:14 +08:00
if ( ! basename ) {
2003-04-25 04:32:14 +08:00
return 0 ;
}
2003-05-05 21:46:14 +08:00
if ( ! basename_len ) {
2003-04-25 04:32:14 +08:00
efree ( basename ) ;
return 0 ;
}
2003-05-05 21:46:14 +08:00
2004-01-29 06:50:12 +08:00
tmp_len = MIN ( sizeof ( ent - > d_name ) , basename_len - 1 ) ;
2003-12-10 15:15:28 +08:00
memcpy ( ent - > d_name , basename , tmp_len ) ;
ent - > d_name [ tmp_len ] = ' \0 ' ;
2003-04-25 04:32:14 +08:00
efree ( basename ) ;
2004-01-29 06:50:12 +08:00
/* Trim off trailing whitespace characters */
tmp_len - - ;
while ( tmp_len > = 0 & &
( ent - > d_name [ tmp_len ] = = ' \n ' | | ent - > d_name [ tmp_len ] = = ' \r ' | |
ent - > d_name [ tmp_len ] = = ' \t ' | | ent - > d_name [ tmp_len ] = = ' ' ) ) {
ent - > d_name [ tmp_len - - ] = ' \0 ' ;
}
2003-04-25 04:32:14 +08:00
return sizeof ( php_stream_dirent ) ;
}
/* }}} */
/* {{{ php_ftp_dirstream_close
*/
static int php_ftp_dirstream_close ( php_stream * stream , int close_handle TSRMLS_DC )
{
php_stream * innerstream = ( php_stream * ) stream - > abstract ;
if ( innerstream - > wrapperdata ) {
php_stream_close ( ( php_stream * ) innerstream - > wrapperdata ) ;
innerstream - > wrapperdata = NULL ;
}
php_stream_close ( ( php_stream * ) stream - > abstract ) ;
stream - > abstract = NULL ;
return 0 ;
}
/* }}} */
/* ftp dirstreams only need to support read and close operations,
They can ' t be rewound because the underlying ftp stream can ' t be rewound . */
static php_stream_ops php_ftp_dirstream_ops = {
NULL , /* write */
php_ftp_dirstream_read , /* read */
php_ftp_dirstream_close , /* close */
NULL , /* flush */
" ftpdir " ,
NULL , /* rewind */
NULL , /* cast */
NULL , /* stat */
NULL /* set option */
} ;
/* {{{ php_stream_ftp_opendir
*/
php_stream * php_stream_ftp_opendir ( php_stream_wrapper * wrapper , char * path , char * mode , int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
{
php_stream * stream , * reuseid , * datastream = NULL ;
2003-05-15 02:02:10 +08:00
php_url * resource = NULL ;
2005-02-28 01:08:18 +08:00
int result = 0 , use_ssl , use_ssl_on_data = 0 ;
2003-04-25 04:32:14 +08:00
char * hoststart = NULL , tmp_line [ 512 ] ;
char ip [ sizeof ( " 123.123.123.123 " ) ] ;
unsigned short portno ;
2003-04-26 09:55:31 +08:00
stream = php_ftp_fopen_connect ( wrapper , path , mode , options , opened_path , context , & reuseid , & resource , & use_ssl , & use_ssl_on_data TSRMLS_CC ) ;
2004-08-16 09:41:14 +08:00
if ( ! stream ) {
goto opendir_errexit ;
}
2003-04-25 04:32:14 +08:00
/* set the connection to be ascii */
php_stream_write_string ( stream , " TYPE A \r \n " ) ;
result = GET_FTP_RESULT ( stream ) ;
if ( result > 299 | | result < 200 )
goto opendir_errexit ;
/* set up the passive connection */
2003-04-26 09:55:31 +08:00
portno = php_fopen_do_pasv ( stream , ip , sizeof ( ip ) , & hoststart TSRMLS_CC ) ;
2003-04-25 04:32:14 +08:00
if ( ! portno ) {
goto opendir_errexit ;
}
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " NLST %s \r \n " , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ;
2003-04-25 04:32:14 +08:00
/* 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 opendir_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 opendir_errexit ;
}
php_stream_context_set ( datastream , context ) ;
if ( use_ssl_on_data & & ( php_stream_xport_crypto_setup ( stream ,
STREAM_CRYPTO_METHOD_SSLv23_CLIENT , NULL TSRMLS_CC ) < 0 | |
php_stream_xport_crypto_enable ( stream , 1 TSRMLS_CC ) < 0 ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " Unable to activate SSL mode " ) ;
php_stream_close ( datastream ) ;
datastream = NULL ;
goto opendir_errexit ;
}
/* remember control stream */
datastream - > wrapperdata = ( zval * ) stream ;
php_url_free ( resource ) ;
return php_stream_alloc ( & php_ftp_dirstream_ops , datastream , 0 , mode ) ;
opendir_errexit :
2003-05-15 02:02:10 +08:00
if ( resource ) {
php_url_free ( resource ) ;
}
2003-04-25 04:32:14 +08:00
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 ;
}
/* }}} */
2003-04-26 09:55:31 +08:00
/* {{{ php_stream_ftp_url_stat
*/
2003-11-29 07:25:28 +08:00
static int php_stream_ftp_url_stat ( php_stream_wrapper * wrapper , char * url , int flags , php_stream_statbuf * ssb , php_stream_context * context TSRMLS_DC )
2003-04-26 09:55:31 +08:00
{
php_stream * stream = NULL ;
2003-05-15 02:02:10 +08:00
php_url * resource = NULL ;
2003-04-26 09:55:31 +08:00
int result ;
char tmp_line [ 512 ] ;
/* If ssb is NULL then someone is misbehaving */
if ( ! ssb ) return - 1 ;
2003-11-30 01:16:58 +08:00
stream = php_ftp_fopen_connect ( wrapper , url , " r " , 0 , NULL , context , NULL , & resource , NULL , NULL TSRMLS_CC ) ;
2003-04-26 09:55:31 +08:00
if ( ! stream ) {
goto stat_errexit ;
}
2003-11-30 01:16:58 +08:00
ssb - > sb . st_mode = 0644 ; /* FTP won't give us a valid mode, so aproximate one based on being readable */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " CWD %s \r \n " , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ; /* If we can CWD to it, it's a directory (maybe a link, but we can't tell) */
2003-11-30 01:16:58 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
ssb - > sb . st_mode | = S_IFREG ;
} else {
ssb - > sb . st_mode | = S_IFDIR ;
}
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " SIZE %s \r \n " , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ;
2003-04-26 09:55:31 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
2003-11-30 01:16:58 +08:00
/* Failure either means it doesn't exist
or it ' s a directory and this server
fails on listing directory sizes */
if ( ssb - > sb . st_mode & S_IFDIR ) {
ssb - > sb . st_size = 0 ;
} else {
goto stat_errexit ;
}
} else {
ssb - > sb . st_size = atoi ( tmp_line + 4 ) ;
}
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " MDTM %s \r \n " , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ;
2004-07-21 12:37:47 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result = = 213 ) {
char * p = tmp_line + 4 ;
int n ;
struct tm tm , tmbuf , * gmt ;
time_t stamp ;
while ( p - tmp_line < sizeof ( tmp_line ) & & ! isdigit ( * p ) ) {
p + + ;
}
if ( p - tmp_line > sizeof ( tmp_line ) ) {
goto mdtm_error ;
}
n = sscanf ( p , " %4u%2u%2u%2u%2u%2u " , & tm . tm_year , & tm . tm_mon , & tm . tm_mday , & tm . tm_hour , & tm . tm_min , & tm . tm_sec ) ;
if ( n ! = 6 ) {
goto mdtm_error ;
}
tm . tm_year - = 1900 ;
tm . tm_mon - - ;
tm . tm_isdst = - 1 ;
/* figure out the GMT offset */
stamp = time ( NULL ) ;
gmt = php_gmtime_r ( & stamp , & tmbuf ) ;
gmt - > tm_isdst = - 1 ;
/* apply the GMT offset */
tm . tm_sec + = stamp - mktime ( gmt ) ;
tm . tm_isdst = gmt - > tm_isdst ;
2004-09-29 18:21:41 +08:00
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = mktime ( & tm ) ;
# else
2004-07-21 12:37:47 +08:00
ssb - > sb . st_mtime = mktime ( & tm ) ;
2004-09-29 18:21:41 +08:00
# endif
2004-07-21 12:37:47 +08:00
} else {
/* error or unsupported command */
mdtm_error :
2004-09-29 18:21:41 +08:00
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = - 1 ;
# else
2004-07-21 12:37:47 +08:00
ssb - > sb . st_mtime = - 1 ;
2004-09-29 18:21:41 +08:00
# endif
2004-07-21 12:37:47 +08:00
}
2003-11-30 01:16:58 +08:00
ssb - > sb . st_ino = 0 ; /* Unknown values */
2003-11-30 04:01:00 +08:00
ssb - > sb . st_dev = 0 ;
2003-11-30 01:16:58 +08:00
ssb - > sb . st_uid = 0 ;
ssb - > sb . st_gid = 0 ;
2004-09-29 18:21:41 +08:00
# ifdef NETWARE
ssb - > sb . st_atime . tv_sec = - 1 ;
ssb - > sb . st_ctime . tv_sec = - 1 ;
# else
2003-11-30 01:16:58 +08:00
ssb - > sb . st_atime = - 1 ;
ssb - > sb . st_ctime = - 1 ;
2004-09-29 18:21:41 +08:00
# endif
2003-11-30 01:16:58 +08:00
ssb - > sb . st_nlink = 1 ;
ssb - > sb . st_rdev = - 1 ;
2003-11-30 04:01:00 +08:00
# ifdef HAVE_ST_BLKSIZE
2003-11-30 01:16:58 +08:00
ssb - > sb . st_blksize = 4096 ; /* Guess since FTP won't expose this information */
2003-11-30 04:01:00 +08:00
# ifdef HAVE_ST_BLOCKS
ssb - > sb . st_blocks = ( int ) ( ( 4095 + ssb - > sb . st_size ) / ssb - > sb . st_blksize ) ; /* emulate ceil */
# endif
# endif
2003-04-26 09:55:31 +08:00
php_stream_close ( stream ) ;
2003-08-08 14:18:25 +08:00
php_url_free ( resource ) ;
2003-04-26 09:55:31 +08:00
return 0 ;
stat_errexit :
2003-05-15 02:02:10 +08:00
if ( resource ) {
php_url_free ( resource ) ;
}
2003-04-26 09:55:31 +08:00
if ( stream ) {
php_stream_close ( stream ) ;
}
return - 1 ;
}
/* }}} */
2003-05-15 02:02:10 +08:00
/* {{{ php_stream_ftp_unlink
*/
static int php_stream_ftp_unlink ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC )
{
php_stream * stream = NULL ;
php_url * resource = NULL ;
int result ;
char tmp_line [ 512 ] ;
stream = php_ftp_fopen_connect ( wrapper , url , " r " , 0 , NULL , NULL , NULL , & resource , NULL , NULL TSRMLS_CC ) ;
if ( ! stream ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to connect to %s " , url ) ;
}
goto unlink_errexit ;
}
if ( resource - > path = = NULL ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid path provided in %s " , url ) ;
}
goto unlink_errexit ;
}
/* Attempt to delete the file */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " DELE %s \r \n " , ( resource - > path ! = NULL ? resource - > path : " / " ) ) ;
2003-05-15 02:02:10 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error Deleting file: %s " , tmp_line ) ;
}
goto unlink_errexit ;
}
php_url_free ( resource ) ;
php_stream_close ( stream ) ;
return 1 ;
unlink_errexit :
if ( resource ) {
php_url_free ( resource ) ;
}
if ( stream ) {
php_stream_close ( stream ) ;
}
return 0 ;
}
/* }}} */
2003-12-13 07:06:42 +08:00
/* {{{ php_stream_ftp_rename
*/
static int php_stream_ftp_rename ( php_stream_wrapper * wrapper , char * url_from , char * url_to , int options , php_stream_context * context TSRMLS_DC )
{
php_stream * stream = NULL ;
php_url * resource_from = NULL , * resource_to = NULL ;
int result ;
char tmp_line [ 512 ] ;
resource_from = php_url_parse ( url_from ) ;
resource_to = php_url_parse ( url_to ) ;
/* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port
( or a 21 / 0 0 / 21 combination which is also " same " )
Also require paths to / from */
if ( ! resource_from | |
! resource_to | |
! resource_from - > scheme | |
! resource_to - > scheme | |
strcmp ( resource_from - > scheme , resource_to - > scheme ) | |
! resource_from - > host | |
! resource_to - > host | |
strcmp ( resource_from - > host , resource_to - > host ) | |
( resource_from - > port ! = resource_to - > port & &
resource_from - > port * resource_to - > port ! = 0 & &
resource_from - > port + resource_to - > port ! = 21 ) | |
! resource_from - > path | |
! resource_to - > path ) {
goto rename_errexit ;
}
stream = php_ftp_fopen_connect ( wrapper , url_from , " r " , 0 , NULL , NULL , NULL , NULL , NULL , NULL TSRMLS_CC ) ;
if ( ! stream ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to connect to %s " , resource_from - > host ) ;
}
goto rename_errexit ;
}
/* Rename FROM */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " RNFR %s \r \n " , ( resource_from - > path ! = NULL ? resource_from - > path : " / " ) ) ;
2003-12-13 07:06:42 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 300 | | result > 399 ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error Renaming file: %s " , tmp_line ) ;
}
goto rename_errexit ;
}
/* Rename TO */
2005-10-11 22:33:51 +08:00
php_stream_printf ( stream TSRMLS_CC , " RNTO %s \r \n " , ( resource_to - > path ! = NULL ? resource_to - > path : " / " ) ) ;
2003-12-13 07:06:42 +08:00
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error Renaming file: %s " , tmp_line ) ;
}
goto rename_errexit ;
}
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_stream_close ( stream ) ;
return 1 ;
rename_errexit :
if ( resource_from ) {
php_url_free ( resource_from ) ;
}
if ( resource_to ) {
php_url_free ( resource_to ) ;
}
if ( stream ) {
php_stream_close ( stream ) ;
}
return 0 ;
}
/* }}} */
2003-12-13 12:07:18 +08:00
/* {{{ php_stream_ftp_mkdir
*/
static int php_stream_ftp_mkdir ( php_stream_wrapper * wrapper , char * url , int mode , int options , php_stream_context * context TSRMLS_DC )
{
php_stream * stream = NULL ;
php_url * resource = NULL ;
int result , recursive = options & PHP_STREAM_MKDIR_RECURSIVE ;
char tmp_line [ 512 ] ;
stream = php_ftp_fopen_connect ( wrapper , url , " r " , 0 , NULL , NULL , NULL , & resource , NULL , NULL TSRMLS_CC ) ;
if ( ! stream ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to connect to %s " , url ) ;
}
goto mkdir_errexit ;
}
if ( resource - > path = = NULL ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid path provided in %s " , url ) ;
}
goto mkdir_errexit ;
}
if ( ! recursive ) {
php_stream_printf ( stream TSRMLS_CC , " MKD %s \r \n " , resource - > path ) ;
result = GET_FTP_RESULT ( stream ) ;
} else {
/* we look for directory separator from the end of string, thus hopefuly reducing our work load */
char * p , * e , * buf ;
buf = estrdup ( resource - > path ) ;
e = buf + strlen ( buf ) ;
/* find a top level directory we need to create */
while ( ( p = strrchr ( buf , ' / ' ) ) ) {
* p = ' \0 ' ;
php_stream_printf ( stream TSRMLS_CC , " CWD %s \r \n " , buf ) ;
result = GET_FTP_RESULT ( stream ) ;
if ( result > = 200 & & result < = 299 ) {
* p = ' / ' ;
break ;
}
}
if ( p = = buf ) {
php_stream_printf ( stream TSRMLS_CC , " MKD %s \r \n " , resource - > path ) ;
result = GET_FTP_RESULT ( stream ) ;
} else {
php_stream_printf ( stream TSRMLS_CC , " MKD %s \r \n " , buf ) ;
result = GET_FTP_RESULT ( stream ) ;
if ( result > = 200 & & result < = 299 ) {
if ( ! p ) {
p = buf ;
}
/* create any needed directories if the creation of the 1st directory worked */
while ( + + p ! = e ) {
if ( * p = = ' \0 ' & & * ( p + 1 ) ! = ' \0 ' ) {
* p = ' / ' ;
php_stream_printf ( stream TSRMLS_CC , " MKD %s \r \n " , buf ) ;
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s " , tmp_line ) ;
}
break ;
}
}
}
}
}
efree ( buf ) ;
}
php_url_free ( resource ) ;
php_stream_close ( stream ) ;
if ( result < 200 | | result > 299 ) {
/* Failure */
return 0 ;
}
return 1 ;
mkdir_errexit :
if ( resource ) {
php_url_free ( resource ) ;
}
if ( stream ) {
php_stream_close ( stream ) ;
}
return 0 ;
}
/* }}} */
/* {{{ php_stream_ftp_rmdir
*/
static int php_stream_ftp_rmdir ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC )
{
php_stream * stream = NULL ;
php_url * resource = NULL ;
int result ;
char tmp_line [ 512 ] ;
stream = php_ftp_fopen_connect ( wrapper , url , " r " , 0 , NULL , NULL , NULL , & resource , NULL , NULL TSRMLS_CC ) ;
if ( ! stream ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to connect to %s " , url ) ;
}
goto rmdir_errexit ;
}
if ( resource - > path = = NULL ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid path provided in %s " , url ) ;
}
goto rmdir_errexit ;
}
php_stream_printf ( stream TSRMLS_CC , " RMD %s \r \n " , resource - > path ) ;
result = GET_FTP_RESULT ( stream ) ;
if ( result < 200 | | result > 299 ) {
if ( options & REPORT_ERRORS ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s " , tmp_line ) ;
}
goto rmdir_errexit ;
}
php_url_free ( resource ) ;
php_stream_close ( stream ) ;
return 1 ;
rmdir_errexit :
if ( resource ) {
php_url_free ( resource ) ;
}
if ( stream ) {
php_stream_close ( stream ) ;
}
return 0 ;
}
/* }}} */
2003-04-25 04:32:14 +08:00
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 ,
2003-04-26 09:55:31 +08:00
php_stream_ftp_url_stat , /* stat_url */
2003-04-25 04:32:14 +08:00
php_stream_ftp_opendir , /* opendir */
2004-07-24 12:01:48 +08:00
" ftp " ,
2003-12-13 07:06:42 +08:00
php_stream_ftp_unlink , /* unlink */
2003-12-13 12:07:18 +08:00
php_stream_ftp_rename , /* rename */
php_stream_ftp_mkdir , /* mkdir */
php_stream_ftp_rmdir /* rmdir */
2003-04-25 04:32:14 +08:00
} ;
PHPAPI php_stream_wrapper php_stream_ftp_wrapper = {
& ftp_stream_wops ,
NULL ,
1 /* is_url */
} ;
2001-06-05 21:12:10 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 21:29:31 +08:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
2001-06-05 21:12:10 +08:00
*/