PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - ftp_fopen_wrapper.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 0 548 0.0 %
Date: 2014-07-27 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2013 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16             :    |          Jim Winstead <jimw@php.net>                                 |
      17             :    |          Hartmut Holzgraefe <hholzgra@php.net>                       |
      18             :    |          Sara Golemon <pollita@php.net>                              |
      19             :    +----------------------------------------------------------------------+
      20             :  */
      21             : /* $Id$ */
      22             : 
      23             : #include "php.h"
      24             : #include "php_globals.h"
      25             : #include "php_network.h"
      26             : #include "php_ini.h"
      27             : 
      28             : #include <stdio.h>
      29             : #include <stdlib.h>
      30             : #include <errno.h>
      31             : #include <sys/types.h>
      32             : #include <sys/stat.h>
      33             : #include <fcntl.h>
      34             : 
      35             : #ifdef PHP_WIN32
      36             : #include <winsock2.h>
      37             : #define O_RDONLY _O_RDONLY
      38             : #include "win32/param.h"
      39             : #else
      40             : #include <sys/param.h>
      41             : #endif
      42             : 
      43             : #include "php_standard.h"
      44             : 
      45             : #include <sys/types.h>
      46             : #if HAVE_SYS_SOCKET_H
      47             : #include <sys/socket.h>
      48             : #endif
      49             : 
      50             : #ifdef PHP_WIN32
      51             : #include <winsock2.h>
      52             : #elif defined(NETWARE) && defined(USE_WINSOCK)
      53             : #include <novsock2.h>
      54             : #else
      55             : #include <netinet/in.h>
      56             : #include <netdb.h>
      57             : #if HAVE_ARPA_INET_H
      58             : #include <arpa/inet.h>
      59             : #endif
      60             : #endif
      61             : 
      62             : #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
      63             : #undef AF_UNIX
      64             : #endif
      65             : 
      66             : #if defined(AF_UNIX)
      67             : #include <sys/un.h>
      68             : #endif
      69             : 
      70             : #include "php_fopen_wrappers.h"
      71             : 
      72             : #define FTPS_ENCRYPT_DATA 1
      73             : #define GET_FTP_RESULT(stream)  get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC)
      74             : 
      75             : typedef struct _php_ftp_dirstream_data {
      76             :         php_stream *datastream;
      77             :         php_stream *controlstream;
      78             :         php_stream *dirstream;
      79             : } php_ftp_dirstream_data;
      80             : 
      81             : /* {{{ get_ftp_result
      82             :  */
      83           0 : static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC)
      84             : {
      85           0 :         while (php_stream_gets(stream, buffer, buffer_size-1) &&
      86           0 :                    !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) &&
      87           0 :                          isdigit((int) buffer[2]) && buffer[3] == ' '));
      88           0 :         return strtol(buffer, NULL, 10);
      89             : }
      90             : /* }}} */
      91             : 
      92             : /* {{{ php_stream_ftp_stream_stat
      93             :  */
      94           0 : static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
      95             : {
      96             :         /* For now, we return with a failure code to prevent the underlying
      97             :          * file's details from being used instead. */
      98           0 :         return -1;
      99             : }
     100             : /* }}} */
     101             : 
     102             : /* {{{ php_stream_ftp_stream_close
     103             :  */
     104           0 : static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC)
     105             : {
     106           0 :         php_stream *controlstream = stream->wrapperthis;
     107           0 :         int ret = 0;
     108             :         
     109           0 :         if (controlstream) {
     110           0 :                 if (strpbrk(stream->mode, "wa+")) {
     111             :                         char tmp_line[512];
     112             :                         int result;
     113             : 
     114             :                         /* For write modes close data stream first to signal EOF to server */
     115           0 :                         result = GET_FTP_RESULT(controlstream);
     116           0 :                         if (result != 226 && result != 250) {
     117           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "FTP server error %d:%s", result, tmp_line);
     118           0 :                                 ret = EOF;
     119             :                         }
     120             :                 }
     121             : 
     122           0 :                 php_stream_write_string(controlstream, "QUIT\r\n");
     123           0 :                 php_stream_close(controlstream);
     124           0 :                 stream->wrapperthis = NULL;
     125             :         }
     126             : 
     127           0 :         return ret;
     128             : }
     129             : /* }}} */
     130             : 
     131             : /* {{{ php_ftp_fopen_connect
     132             :  */
     133           0 : static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context,
     134             :                                                                          php_stream **preuseid, php_url **presource, int *puse_ssl, int *puse_ssl_on_data TSRMLS_DC)
     135             : {
     136           0 :         php_stream *stream = NULL, *reuseid = NULL;
     137           0 :         php_url *resource = NULL;
     138           0 :         int result, use_ssl, use_ssl_on_data = 0, tmp_len;
     139             :         char tmp_line[512];
     140             :         char *transport;
     141             :         int transport_len;
     142             : 
     143           0 :         resource = php_url_parse(path);
     144           0 :         if (resource == NULL || resource->path == NULL) {
     145           0 :                 if (resource && presource) {
     146           0 :                         *presource = resource;
     147             :                 }
     148           0 :                 return NULL;
     149             :         }
     150             : 
     151           0 :         use_ssl = resource->scheme && (strlen(resource->scheme) > 3) && resource->scheme[3] == 's';
     152             : 
     153             :         /* use port 21 if one wasn't specified */
     154           0 :         if (resource->port == 0)
     155           0 :                 resource->port = 21;
     156             :         
     157           0 :         transport_len = spprintf(&transport, 0, "tcp://%s:%d", resource->host, resource->port);
     158           0 :         stream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL);
     159           0 :         efree(transport);
     160           0 :         if (stream == NULL) {
     161           0 :                 result = 0; /* silence */
     162           0 :                 goto connect_errexit;
     163             :         }
     164             : 
     165           0 :         php_stream_context_set(stream, context);
     166           0 :         php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);
     167             : 
     168             :         /* Start talking to ftp server */
     169           0 :         result = GET_FTP_RESULT(stream);
     170           0 :         if (result > 299 || result < 200) {
     171           0 :                 php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);
     172           0 :                 goto connect_errexit;
     173             :         }
     174             : 
     175           0 :         if (use_ssl)    {
     176             :         
     177             :                 /* send the AUTH TLS request name */
     178           0 :                 php_stream_write_string(stream, "AUTH TLS\r\n");
     179             : 
     180             :                 /* get the response */
     181           0 :                 result = GET_FTP_RESULT(stream);
     182           0 :                 if (result != 234) {
     183             :                         /* AUTH TLS not supported try AUTH SSL */
     184           0 :                         php_stream_write_string(stream, "AUTH SSL\r\n");
     185             :                         
     186             :                         /* get the response */
     187           0 :                         result = GET_FTP_RESULT(stream);
     188           0 :                         if (result != 334) {
     189           0 :                                 use_ssl = 0;
     190             :                         } else {
     191             :                                 /* we must reuse the old SSL session id */
     192             :                                 /* if we talk to an old ftpd-ssl */
     193           0 :                                 reuseid = stream;
     194             :                         }
     195             :                 } else {
     196             :                         /* encrypt data etc */
     197             : 
     198             : 
     199             :                 }
     200             : 
     201             :         }
     202             :         
     203           0 :         if (use_ssl) {
     204           0 :                 if (php_stream_xport_crypto_setup(stream,
     205             :                                 STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0
     206           0 :                                 || php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
     207           0 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
     208           0 :                         php_stream_close(stream);
     209           0 :                         stream = NULL;
     210           0 :                         goto connect_errexit;
     211             :                 }
     212             :         
     213             :                 /* set PBSZ to 0 */
     214           0 :                 php_stream_write_string(stream, "PBSZ 0\r\n");
     215             : 
     216             :                 /* ignore the response */
     217           0 :                 result = GET_FTP_RESULT(stream);
     218             :                 
     219             :                 /* set data connection protection level */
     220             : #if FTPS_ENCRYPT_DATA
     221           0 :                 php_stream_write_string(stream, "PROT P\r\n");
     222             : 
     223             :                 /* get the response */
     224           0 :                 result = GET_FTP_RESULT(stream);
     225           0 :                 use_ssl_on_data = (result >= 200 && result<=299) || reuseid;
     226             : #else
     227             :                 php_stream_write_string(stream, "PROT C\r\n");
     228             : 
     229             :                 /* get the response */
     230             :                 result = GET_FTP_RESULT(stream);
     231             : #endif
     232             :         }
     233             : 
     234             : #define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) {      \
     235             :         unsigned char *s = val, *e = s + val_len;       \
     236             :         while (s < e) {      \
     237             :                 if (iscntrl(*s)) {      \
     238             :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val); \
     239             :                         goto connect_errexit;   \
     240             :                 }       \
     241             :                 s++;    \
     242             :         }       \
     243             : } 
     244             : 
     245             :         /* send the user name */
     246           0 :         if (resource->user != NULL) {
     247           0 :                 tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));
     248             : 
     249           0 :                 PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
     250             : 
     251           0 :                 php_stream_printf(stream TSRMLS_CC, "USER %s\r\n", resource->user);
     252             :         } else {
     253           0 :                 php_stream_write_string(stream, "USER anonymous\r\n");
     254             :         }
     255             :         
     256             :         /* get the response */
     257           0 :         result = GET_FTP_RESULT(stream);
     258             :         
     259             :         /* if a password is required, send it */
     260           0 :         if (result >= 300 && result <= 399) {
     261           0 :                 php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0);
     262             : 
     263           0 :                 if (resource->pass != NULL) {
     264           0 :                         tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));
     265             : 
     266           0 :                         PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")
     267             : 
     268           0 :                         php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", resource->pass);
     269             :                 } else {
     270             :                         /* if the user has configured who they are,
     271             :                            send that as the password */
     272           0 :                         char *from_address = php_ini_string("from", sizeof("from"), 0);
     273           0 :                         if (from_address[0] != '\0') {
     274           0 :                                 php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", from_address);
     275             :                         } else {
     276           0 :                                 php_stream_write_string(stream, "PASS anonymous\r\n");
     277             :                         }
     278             :                 }
     279             : 
     280             :                 /* read the response */
     281           0 :                 result = GET_FTP_RESULT(stream);
     282             : 
     283           0 :                 if (result > 299 || result < 200) {
     284           0 :                         php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result);
     285             :                 } else {
     286           0 :                         php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result);
     287             :                 }
     288             :         }
     289           0 :         if (result > 299 || result < 200) {
     290             :                 goto connect_errexit;
     291             :         }
     292             : 
     293           0 :         if (puse_ssl) {
     294           0 :                 *puse_ssl = use_ssl;
     295             :         }
     296           0 :         if (puse_ssl_on_data) {
     297           0 :                 *puse_ssl_on_data = use_ssl_on_data;
     298             :         }
     299           0 :         if (preuseid) {
     300           0 :                 *preuseid = reuseid;
     301             :         }
     302           0 :         if (presource) {
     303           0 :                 *presource = resource;
     304             :         }
     305             : 
     306           0 :         return stream;
     307             : 
     308             : connect_errexit:
     309           0 :         if (resource) {
     310           0 :                 php_url_free(resource); 
     311             :         }
     312             : 
     313           0 :         if (stream) {
     314           0 :                 php_stream_close(stream);
     315             :         }
     316             : 
     317           0 :         return NULL;
     318             : }
     319             : /* }}} */
     320             : 
     321             : /* {{{ php_fopen_do_pasv
     322             :  */
     323           0 : static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_size, char **phoststart TSRMLS_DC)
     324             : {
     325             :         char tmp_line[512];
     326             :         int result, i;
     327             :         unsigned short portno;
     328           0 :         char *tpath, *ttpath, *hoststart=NULL;
     329             : 
     330             : #ifdef HAVE_IPV6
     331             :         /* We try EPSV first, needed for IPv6 and works on some IPv4 servers */
     332           0 :         php_stream_write_string(stream, "EPSV\r\n");
     333           0 :         result = GET_FTP_RESULT(stream);
     334             : 
     335             :         /* check if we got a 229 response */
     336           0 :         if (result != 229) {
     337             : #endif
     338             :                 /* EPSV failed, let's try PASV */
     339           0 :                 php_stream_write_string(stream, "PASV\r\n");
     340           0 :                 result = GET_FTP_RESULT(stream);
     341             :                 
     342             :                 /* make sure we got a 227 response */
     343           0 :                 if (result != 227) {
     344           0 :                         return 0;
     345             :                 }
     346             : 
     347             :                 /* parse pasv command (129, 80, 95, 25, 13, 221) */
     348           0 :                 tpath = tmp_line;
     349             :                 /* skip over the "227 Some message " part */
     350           0 :                 for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++);
     351           0 :                 if (!*tpath) {
     352           0 :                         return 0;
     353             :                 }
     354             :                 /* skip over the host ip, to get the port */
     355           0 :                 hoststart = tpath;
     356           0 :                 for (i = 0; i < 4; i++) {
     357           0 :                         for (; isdigit((int) *tpath); tpath++);
     358           0 :                         if (*tpath != ',') {
     359           0 :                                 return 0;
     360             :                         }
     361           0 :                         *tpath='.';     
     362           0 :                         tpath++;
     363             :                 }
     364           0 :                 tpath[-1] = '\0';
     365           0 :                 memcpy(ip, hoststart, ip_size);
     366           0 :                 ip[ip_size-1] = '\0';
     367           0 :                 hoststart = ip;
     368             :                 
     369             :                 /* pull out the MSB of the port */
     370           0 :                 portno = (unsigned short) strtoul(tpath, &ttpath, 10) * 256;
     371           0 :                 if (ttpath == NULL) {
     372             :                         /* didn't get correct response from PASV */
     373           0 :                         return 0;
     374             :                 }
     375           0 :                 tpath = ttpath;
     376           0 :                 if (*tpath != ',') {
     377           0 :                         return 0;
     378             :                 }
     379           0 :                 tpath++;
     380             :                 /* pull out the LSB of the port */
     381           0 :                 portno += (unsigned short) strtoul(tpath, &ttpath, 10);
     382             : #ifdef HAVE_IPV6
     383             :         } else {
     384             :                 /* parse epsv command (|||6446|) */
     385           0 :                 for (i = 0, tpath = tmp_line + 4; *tpath; tpath++) {
     386           0 :                         if (*tpath == '|') {
     387           0 :                                 i++;
     388           0 :                                 if (i == 3)
     389           0 :                                         break;
     390             :                         }
     391             :                 }
     392           0 :                 if (i < 3) {
     393           0 :                         return 0;
     394             :                 }
     395             :                 /* pull out the port */
     396           0 :                 portno = (unsigned short) strtoul(tpath + 1, &ttpath, 10);
     397             :         }
     398             : #endif  
     399           0 :         if (ttpath == NULL) {
     400             :                 /* didn't get correct response from EPSV/PASV */
     401           0 :                 return 0;
     402             :         }
     403             : 
     404           0 :         if (phoststart) {
     405           0 :                 *phoststart = hoststart;
     406             :         }       
     407             : 
     408           0 :         return portno;
     409             : }
     410             : /* }}} */
     411             : 
     412             : /* {{{ php_fopen_url_wrap_ftp
     413             :  */
     414           0 : 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)
     415             : {
     416           0 :         php_stream *stream = NULL, *datastream = NULL;
     417           0 :         php_url *resource = NULL;
     418             :         char tmp_line[512];
     419             :         char ip[sizeof("123.123.123.123")];
     420             :         unsigned short portno;
     421           0 :         char *hoststart = NULL;
     422           0 :         int result = 0, use_ssl, use_ssl_on_data=0;
     423           0 :         php_stream *reuseid=NULL;
     424           0 :         size_t file_size = 0;
     425             :         zval **tmpzval;
     426           0 :         int allow_overwrite = 0;
     427           0 :         int read_write = 0;
     428             :         char *transport;
     429             :         int transport_len;
     430             : 
     431           0 :         tmp_line[0] = '\0';
     432             : 
     433           0 :         if (strpbrk(mode, "r+")) {
     434           0 :                 read_write = 1; /* Open for reading */
     435             :         }
     436           0 :         if (strpbrk(mode, "wa+")) {
     437           0 :                 if (read_write) {
     438           0 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP does not support simultaneous read/write connections");
     439           0 :                         return NULL;
     440             :                 }
     441           0 :                 if (strchr(mode, 'a')) {
     442           0 :                         read_write = 3; /* Open for Appending */
     443             :                 } else {
     444           0 :                         read_write = 2; /* Open for writting */
     445             :                 }
     446             :         }
     447           0 :         if (!read_write) {
     448             :                 /* No mode specified? */
     449           0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unknown file open mode");
     450           0 :                 return NULL;
     451             :         }
     452             : 
     453           0 :         if (context &&
     454           0 :                 php_stream_context_get_option(context, "ftp", "proxy", &tmpzval) == SUCCESS) {
     455           0 :                 if (read_write == 1) {
     456             :                         /* Use http wrapper to proxy ftp request */
     457           0 :                         return php_stream_url_wrap_http(wrapper, path, mode, options, opened_path, context STREAMS_CC TSRMLS_CC);
     458             :                 } else {
     459             :                         /* ftp proxy is read-only */
     460           0 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP proxy may only be used in read mode");
     461           0 :                         return NULL;
     462             :                 }
     463             :         }
     464             : 
     465           0 :         stream = php_ftp_fopen_connect(wrapper, path, mode, options, opened_path, context, &reuseid, &resource, &use_ssl, &use_ssl_on_data TSRMLS_CC);
     466           0 :         if (!stream) {
     467           0 :                 goto errexit;
     468             :         }
     469             : 
     470             :         /* set the connection to be binary */
     471           0 :         php_stream_write_string(stream, "TYPE I\r\n");
     472           0 :         result = GET_FTP_RESULT(stream);
     473           0 :         if (result > 299 || result < 200)
     474             :                 goto errexit;
     475             :         
     476             :         /* find out the size of the file (verifying it exists) */
     477           0 :         php_stream_printf(stream TSRMLS_CC, "SIZE %s\r\n", resource->path);
     478             :         
     479             :         /* read the response */
     480           0 :         result = GET_FTP_RESULT(stream);
     481           0 :         if (read_write == 1) {
     482             :                 /* Read Mode */
     483             :                 char *sizestr;
     484             :                 
     485             :                 /* when reading file, it must exist */
     486           0 :                 if (result > 299 || result < 200) {
     487           0 :                         errno = ENOENT;
     488           0 :                         goto errexit;
     489             :                 }
     490             :                 
     491           0 :                 sizestr = strchr(tmp_line, ' ');
     492           0 :                 if (sizestr) {
     493           0 :                         sizestr++;
     494           0 :                         file_size = atoi(sizestr);
     495           0 :                         php_stream_notify_file_size(context, file_size, tmp_line, result);
     496             :                 }       
     497           0 :         } else if (read_write == 2) {
     498             :                 /* when writing file (but not appending), it must NOT exist, unless a context option exists which allows it */
     499           0 :                 if (context && php_stream_context_get_option(context, "ftp", "overwrite", &tmpzval) == SUCCESS) {
     500           0 :                         allow_overwrite = Z_LVAL_PP(tmpzval);
     501             :                 }
     502           0 :                 if (result <= 299 && result >= 200) {
     503           0 :                         if (allow_overwrite) {
     504             :                                 /* Context permits overwritting file, 
     505             :                                    so we just delete whatever's there in preparation */
     506           0 :                                 php_stream_printf(stream TSRMLS_CC, "DELE %s\r\n", resource->path);
     507           0 :                                 result = GET_FTP_RESULT(stream);
     508           0 :                                 if (result >= 300 || result <= 199) {
     509             :                                         goto errexit;
     510             :                                 }
     511             :                         } else {
     512           0 :                                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Remote file already exists and overwrite context option not specified");
     513           0 :                                 errno = EEXIST;
     514           0 :                                 goto errexit;
     515             :                         }
     516             :                 }
     517             :         }
     518             : 
     519             :         /* set up the passive connection */
     520           0 :         portno = php_fopen_do_pasv(stream, ip, sizeof(ip), &hoststart TSRMLS_CC);
     521             : 
     522           0 :         if (!portno) {
     523           0 :                 goto errexit;
     524             :         }
     525             : 
     526             :         /* Send RETR/STOR command */
     527           0 :         if (read_write == 1) {
     528             :                 /* set resume position if applicable */
     529           0 :                 if (context &&
     530           0 :                         php_stream_context_get_option(context, "ftp", "resume_pos", &tmpzval) == SUCCESS &&
     531           0 :                         Z_TYPE_PP(tmpzval) == IS_LONG &&
     532           0 :                         Z_LVAL_PP(tmpzval) > 0) {
     533           0 :                         php_stream_printf(stream TSRMLS_CC, "REST %ld\r\n", Z_LVAL_PP(tmpzval));
     534           0 :                         result = GET_FTP_RESULT(stream);
     535           0 :                         if (result < 300 || result > 399) {                       
     536           0 :                                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to resume from offset %ld", Z_LVAL_PP(tmpzval));
     537           0 :                                 goto errexit;
     538             :                         }
     539             :                 }
     540             : 
     541             :                 /* retrieve file */
     542           0 :                 memcpy(tmp_line, "RETR", sizeof("RETR"));
     543           0 :         } else if (read_write == 2) {
     544             :                 /* Write new file */
     545           0 :                 memcpy(tmp_line, "STOR", sizeof("STOR"));
     546             :         } else {
     547             :                 /* Append */
     548           0 :                 memcpy(tmp_line, "APPE", sizeof("APPE"));
     549             :         } 
     550           0 :         php_stream_printf(stream TSRMLS_CC, "%s %s\r\n", tmp_line, (resource->path != NULL ? resource->path : "/"));
     551             :         
     552             :         /* open the data channel */
     553           0 :         if (hoststart == NULL) {
     554           0 :                 hoststart = resource->host;
     555             :         }
     556           0 :         transport_len = spprintf(&transport, 0, "tcp://%s:%d", hoststart, portno);
     557           0 :         datastream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL);
     558           0 :         efree(transport);
     559           0 :         if (datastream == NULL) {
     560           0 :                 goto errexit;
     561             :         }
     562             : 
     563           0 :         result = GET_FTP_RESULT(stream);
     564           0 :         if (result != 150 && result != 125) {
     565             :                 /* Could not retrieve or send the file 
     566             :                  * this data will only be sent to us after connection on the data port was initiated.
     567             :                  */
     568           0 :                 php_stream_close(datastream);
     569           0 :                 datastream = NULL;
     570           0 :                 goto errexit;   
     571             :         }
     572             :         
     573           0 :         php_stream_context_set(datastream, context);
     574           0 :         php_stream_notify_progress_init(context, 0, file_size);
     575             : 
     576           0 :         if (use_ssl_on_data && (php_stream_xport_crypto_setup(datastream,
     577           0 :                         STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
     578           0 :                         php_stream_xport_crypto_enable(datastream, 1 TSRMLS_CC) < 0)) {
     579             : 
     580           0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
     581           0 :                 php_stream_close(datastream);
     582           0 :                 datastream = NULL;
     583           0 :                 goto errexit;
     584             :         }
     585             : 
     586             :         /* remember control stream */   
     587           0 :         datastream->wrapperthis = stream;
     588             : 
     589           0 :         php_url_free(resource);
     590           0 :         return datastream;
     591             : 
     592             : errexit:
     593           0 :         if (resource) {
     594           0 :                 php_url_free(resource);
     595             :         }
     596           0 :         if (stream) {
     597           0 :                 php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);
     598           0 :                 php_stream_close(stream);
     599             :         }
     600           0 :         if (tmp_line[0] != '\0')
     601           0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP server reports %s", tmp_line);
     602           0 :         return NULL;
     603             : }
     604             : /* }}} */
     605             : 
     606             : /* {{{ php_ftp_dirsteam_read
     607             :  */
     608           0 : static size_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     609             : {
     610           0 :         php_stream_dirent *ent = (php_stream_dirent *)buf;
     611             :         php_stream *innerstream;
     612             :         size_t tmp_len;
     613             :         char *basename;
     614             :         size_t basename_len;
     615             : 
     616           0 :         innerstream =  ((php_ftp_dirstream_data *)stream->abstract)->datastream;
     617             : 
     618           0 :         if (count != sizeof(php_stream_dirent)) {
     619           0 :                 return 0;
     620             :         }
     621             : 
     622           0 :         if (php_stream_eof(innerstream)) {
     623           0 :                 return 0;
     624             :         }
     625             : 
     626           0 :         if (!php_stream_get_line(innerstream, ent->d_name, sizeof(ent->d_name), &tmp_len)) {
     627           0 :                 return 0;
     628             :         }
     629             : 
     630           0 :         php_basename(ent->d_name, tmp_len, NULL, 0, &basename, &basename_len TSRMLS_CC);
     631           0 :         if (!basename) {
     632           0 :                 return 0;
     633             :         }
     634             : 
     635           0 :         if (!basename_len) {
     636           0 :                 efree(basename);
     637           0 :                 return 0;
     638             :         }
     639             : 
     640           0 :         tmp_len = MIN(sizeof(ent->d_name), basename_len - 1);
     641           0 :         memcpy(ent->d_name, basename, tmp_len);
     642           0 :         ent->d_name[tmp_len - 1] = '\0';
     643           0 :         efree(basename);
     644             : 
     645             :         /* Trim off trailing whitespace characters */
     646           0 :         tmp_len--;
     647           0 :         while (tmp_len >= 0 &&
     648           0 :                         (ent->d_name[tmp_len] == '\n' || ent->d_name[tmp_len] == '\r' ||
     649           0 :                          ent->d_name[tmp_len] == '\t' || ent->d_name[tmp_len] == ' ')) {
     650           0 :                 ent->d_name[tmp_len--] = '\0';
     651             :         }
     652             : 
     653           0 :         return sizeof(php_stream_dirent);
     654             : }
     655             : /* }}} */
     656             : 
     657             : /* {{{ php_ftp_dirstream_close
     658             :  */
     659           0 : static int php_ftp_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
     660             : {
     661           0 :         php_ftp_dirstream_data *data = stream->abstract;
     662             : 
     663             :         /* close control connection */
     664           0 :         if (data->controlstream) {
     665           0 :                 php_stream_close(data->controlstream);
     666           0 :                 data->controlstream = NULL;
     667             :         }
     668             :         /* close data connection */
     669           0 :         php_stream_close(data->datastream);
     670           0 :         data->datastream = NULL;
     671             :         
     672           0 :         efree(data);
     673           0 :         stream->abstract = NULL;
     674             : 
     675           0 :         return 0;
     676             : }
     677             : /* }}} */
     678             : 
     679             : /* ftp dirstreams only need to support read and close operations,
     680             :    They can't be rewound because the underlying ftp stream can't be rewound. */
     681             : static php_stream_ops php_ftp_dirstream_ops = {
     682             :         NULL, /* write */
     683             :         php_ftp_dirstream_read, /* read */
     684             :         php_ftp_dirstream_close, /* close */
     685             :         NULL, /* flush */
     686             :         "ftpdir",
     687             :         NULL, /* rewind */
     688             :         NULL, /* cast */
     689             :         NULL, /* stat */
     690             :         NULL  /* set option */
     691             : };
     692             : 
     693             : /* {{{ php_stream_ftp_opendir
     694             :  */
     695           0 : 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)
     696             : {
     697           0 :         php_stream *stream, *reuseid, *datastream = NULL;
     698             :         php_ftp_dirstream_data *dirsdata;
     699           0 :         php_url *resource = NULL;
     700           0 :         int result = 0, use_ssl, use_ssl_on_data = 0;
     701           0 :         char *hoststart = NULL, tmp_line[512];
     702             :         char ip[sizeof("123.123.123.123")];
     703             :         unsigned short portno;
     704             : 
     705           0 :         tmp_line[0] = '\0';
     706             : 
     707           0 :         stream = php_ftp_fopen_connect(wrapper, path, mode, options, opened_path, context, &reuseid, &resource, &use_ssl, &use_ssl_on_data TSRMLS_CC);
     708           0 :         if (!stream) {
     709           0 :                 goto opendir_errexit;   
     710             :         }
     711             : 
     712             :         /* set the connection to be ascii */
     713           0 :         php_stream_write_string(stream, "TYPE A\r\n");
     714           0 :         result = GET_FTP_RESULT(stream);
     715           0 :         if (result > 299 || result < 200)
     716             :                 goto opendir_errexit;
     717             : 
     718             :         /* set up the passive connection */
     719           0 :         portno = php_fopen_do_pasv(stream, ip, sizeof(ip), &hoststart TSRMLS_CC);
     720             : 
     721           0 :         if (!portno) {
     722           0 :                 goto opendir_errexit;
     723             :         }
     724             : 
     725           0 :         php_stream_printf(stream TSRMLS_CC, "NLST %s\r\n", (resource->path != NULL ? resource->path : "/"));
     726             :         
     727             :         /* open the data channel */
     728           0 :         if (hoststart == NULL) {
     729           0 :                 hoststart = resource->host;
     730             :         }
     731           0 :         datastream = php_stream_sock_open_host(hoststart, portno, SOCK_STREAM, 0, 0);
     732           0 :         if (datastream == NULL) {
     733           0 :                 goto opendir_errexit;
     734             :         }
     735             : 
     736           0 :         result = GET_FTP_RESULT(stream);
     737           0 :         if (result != 150 && result != 125) {
     738             :                 /* Could not retrieve or send the file 
     739             :                  * this data will only be sent to us after connection on the data port was initiated.
     740             :                  */
     741           0 :                 php_stream_close(datastream);
     742           0 :                 datastream = NULL;
     743           0 :                 goto opendir_errexit;   
     744             :         }
     745             :         
     746           0 :         php_stream_context_set(datastream, context);
     747             : 
     748           0 :         if (use_ssl_on_data && (php_stream_xport_crypto_setup(stream,
     749           0 :                         STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
     750           0 :                         php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0)) {
     751             : 
     752           0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode");
     753           0 :                 php_stream_close(datastream);
     754           0 :                 datastream = NULL;
     755           0 :                 goto opendir_errexit;
     756             :         }
     757             : 
     758           0 :         php_url_free(resource);
     759             : 
     760           0 :         dirsdata = emalloc(sizeof *dirsdata);
     761           0 :         dirsdata->datastream = datastream;
     762           0 :         dirsdata->controlstream = stream;
     763           0 :         dirsdata->dirstream = php_stream_alloc(&php_ftp_dirstream_ops, dirsdata, 0, mode);
     764             : 
     765           0 :         return dirsdata->dirstream;
     766             : 
     767             : opendir_errexit:
     768           0 :         if (resource) {
     769           0 :                 php_url_free(resource);
     770             :         }
     771           0 :         if (stream) {
     772           0 :                 php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);
     773           0 :                 php_stream_close(stream);
     774             :         }
     775           0 :         if (tmp_line[0] != '\0') {
     776           0 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "FTP server reports %s", tmp_line);
     777             :         }
     778           0 :         return NULL;
     779             : }
     780             : /* }}} */
     781             : 
     782             : /* {{{ php_stream_ftp_url_stat
     783             :  */
     784           0 : 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)
     785             : {
     786           0 :         php_stream *stream = NULL;
     787           0 :         php_url *resource = NULL;
     788             :         int result;
     789             :         char tmp_line[512];
     790             : 
     791             :         /* If ssb is NULL then someone is misbehaving */
     792           0 :         if (!ssb) return -1;
     793             : 
     794           0 :         stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, context, NULL, &resource, NULL, NULL TSRMLS_CC);
     795           0 :         if (!stream) {
     796           0 :                 goto stat_errexit;
     797             :         }
     798             : 
     799           0 :         ssb->sb.st_mode = 0644;                                                                      /* FTP won't give us a valid mode, so aproximate one based on being readable */
     800           0 :         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) */
     801           0 :         result = GET_FTP_RESULT(stream);
     802           0 :         if (result < 200 || result > 299) {
     803           0 :                 ssb->sb.st_mode |= S_IFREG;
     804             :         } else {
     805           0 :                 ssb->sb.st_mode |= S_IFDIR;
     806             :         }
     807             : 
     808           0 :         php_stream_write_string(stream, "TYPE I\r\n"); /* we need this since some servers refuse to accept SIZE command in ASCII mode */
     809             :         
     810           0 :         result = GET_FTP_RESULT(stream);
     811             : 
     812           0 :         if(result < 200 || result > 299) {
     813             :                 goto stat_errexit;
     814             :         }
     815             :         
     816           0 :         php_stream_printf(stream TSRMLS_CC, "SIZE %s\r\n", (resource->path != NULL ? resource->path : "/"));
     817           0 :         result = GET_FTP_RESULT(stream);
     818           0 :         if (result < 200 || result > 299) {
     819             :                 /* Failure either means it doesn't exist 
     820             :                    or it's a directory and this server
     821             :                    fails on listing directory sizes */
     822           0 :                 if (ssb->sb.st_mode & S_IFDIR) {
     823           0 :                         ssb->sb.st_size = 0;
     824             :                 } else {
     825           0 :                         goto stat_errexit;
     826             :                 }
     827             :         } else {
     828           0 :                 ssb->sb.st_size = atoi(tmp_line + 4);
     829             :         }
     830             : 
     831           0 :         php_stream_printf(stream TSRMLS_CC, "MDTM %s\r\n", (resource->path != NULL ? resource->path : "/"));
     832           0 :         result = GET_FTP_RESULT(stream);
     833           0 :         if (result == 213) {
     834           0 :                 char *p = tmp_line + 4;
     835             :                 int n;
     836             :                 struct tm tm, tmbuf, *gmt;
     837             :                 time_t stamp;
     838             : 
     839           0 :                 while (p - tmp_line < sizeof(tmp_line) && !isdigit(*p)) {
     840           0 :                         p++;
     841             :                 }
     842             : 
     843           0 :                 if (p - tmp_line > sizeof(tmp_line)) {
     844           0 :                         goto mdtm_error;
     845             :                 }
     846             : 
     847           0 :                 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);
     848           0 :                 if (n != 6) {
     849           0 :                         goto mdtm_error;
     850             :                 }
     851             : 
     852           0 :                 tm.tm_year -= 1900;
     853           0 :                 tm.tm_mon--;
     854           0 :                 tm.tm_isdst = -1;
     855             : 
     856             :                 /* figure out the GMT offset */
     857           0 :                 stamp = time(NULL);
     858           0 :                 gmt = php_gmtime_r(&stamp, &tmbuf);
     859           0 :                 if (!gmt) {
     860           0 :                         goto mdtm_error;
     861             :                 }
     862           0 :                 gmt->tm_isdst = -1;
     863             : 
     864             :                 /* apply the GMT offset */
     865           0 :                 tm.tm_sec += stamp - mktime(gmt);
     866           0 :                 tm.tm_isdst = gmt->tm_isdst;
     867             : 
     868           0 :                 ssb->sb.st_mtime = mktime(&tm);
     869             :         } else {
     870             :                 /* error or unsupported command */
     871             : mdtm_error:
     872           0 :                 ssb->sb.st_mtime = -1;
     873             :         }
     874             : 
     875           0 :         ssb->sb.st_ino = 0;                                          /* Unknown values */
     876           0 :         ssb->sb.st_dev = 0;
     877           0 :         ssb->sb.st_uid = 0;
     878           0 :         ssb->sb.st_gid = 0;
     879           0 :         ssb->sb.st_atime = -1;
     880           0 :         ssb->sb.st_ctime = -1;
     881             : 
     882           0 :         ssb->sb.st_nlink = 1;
     883           0 :         ssb->sb.st_rdev = -1;
     884             : #ifdef HAVE_ST_BLKSIZE
     885           0 :         ssb->sb.st_blksize = 4096;                           /* Guess since FTP won't expose this information */
     886             : #ifdef HAVE_ST_BLOCKS
     887           0 :         ssb->sb.st_blocks = (int)((4095 + ssb->sb.st_size) / ssb->sb.st_blksize); /* emulate ceil */
     888             : #endif
     889             : #endif
     890           0 :         php_stream_close(stream);
     891           0 :         php_url_free(resource);
     892           0 :         return 0;
     893             : 
     894             : stat_errexit:
     895           0 :         if (resource) {
     896           0 :                 php_url_free(resource);
     897             :         }
     898           0 :         if (stream) {
     899           0 :                 php_stream_close(stream);
     900             :         }
     901           0 :         return -1;
     902             : }
     903             : /* }}} */
     904             : 
     905             : /* {{{ php_stream_ftp_unlink
     906             :  */
     907           0 : static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
     908             : {
     909           0 :         php_stream *stream = NULL;
     910           0 :         php_url *resource = NULL;
     911             :         int result;
     912             :         char tmp_line[512];
     913             : 
     914           0 :         stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC);
     915           0 :         if (!stream) {
     916           0 :                 if (options & REPORT_ERRORS) {
     917           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", url);
     918             :                 }
     919           0 :                 goto unlink_errexit;
     920             :         }
     921             : 
     922           0 :         if (resource->path == NULL) {
     923           0 :                 if (options & REPORT_ERRORS) {
     924           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path provided in %s", url);
     925             :                 }
     926           0 :                 goto unlink_errexit;
     927             :         }
     928             : 
     929             :         /* Attempt to delete the file */
     930           0 :         php_stream_printf(stream TSRMLS_CC, "DELE %s\r\n", (resource->path != NULL ? resource->path : "/"));
     931             : 
     932           0 :         result = GET_FTP_RESULT(stream);
     933           0 :         if (result < 200 || result > 299) {
     934           0 :                 if (options & REPORT_ERRORS) {
     935           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error Deleting file: %s", tmp_line);
     936             :                 }
     937           0 :                 goto unlink_errexit;
     938             :         }
     939             : 
     940           0 :         php_url_free(resource);
     941           0 :         php_stream_close(stream);
     942           0 :         return 1;
     943             : 
     944             : unlink_errexit:
     945           0 :         if (resource) {
     946           0 :                 php_url_free(resource);
     947             :         }
     948           0 :         if (stream) {
     949           0 :                 php_stream_close(stream);
     950             :         }
     951           0 :         return 0;
     952             : }
     953             : /* }}} */
     954             : 
     955             : /* {{{ php_stream_ftp_rename
     956             :  */
     957           0 : static int php_stream_ftp_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
     958             : {
     959           0 :         php_stream *stream = NULL;
     960           0 :         php_url *resource_from = NULL, *resource_to = NULL;
     961             :         int result;
     962             :         char tmp_line[512];
     963             : 
     964           0 :         resource_from = php_url_parse(url_from);
     965           0 :         resource_to = php_url_parse(url_to);
     966             :         /* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port 
     967             :                 (or a 21/0 0/21 combination which is also "same") 
     968             :            Also require paths to/from */
     969           0 :         if (!resource_from ||
     970             :                 !resource_to ||
     971           0 :                 !resource_from->scheme ||
     972           0 :                 !resource_to->scheme ||
     973           0 :                 strcmp(resource_from->scheme, resource_to->scheme) ||
     974           0 :                 !resource_from->host ||
     975           0 :                 !resource_to->host ||
     976           0 :                 strcmp(resource_from->host, resource_to->host) ||
     977           0 :                 (resource_from->port != resource_to->port && 
     978           0 :                  resource_from->port * resource_to->port != 0 && 
     979           0 :                  resource_from->port + resource_to->port != 21) ||
     980           0 :                 !resource_from->path ||
     981           0 :                 !resource_to->path) {
     982             :                 goto rename_errexit;
     983             :         }
     984             : 
     985           0 :         stream = php_ftp_fopen_connect(wrapper, url_from, "r", 0, NULL, NULL, NULL, NULL, NULL, NULL TSRMLS_CC);
     986           0 :         if (!stream) {
     987           0 :                 if (options & REPORT_ERRORS) {
     988           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", resource_from->host);
     989             :                 }
     990           0 :                 goto rename_errexit;
     991             :         }
     992             : 
     993             :         /* Rename FROM */
     994           0 :         php_stream_printf(stream TSRMLS_CC, "RNFR %s\r\n", (resource_from->path != NULL ? resource_from->path : "/"));
     995             : 
     996           0 :         result = GET_FTP_RESULT(stream);
     997           0 :         if (result < 300 || result > 399) {
     998           0 :                 if (options & REPORT_ERRORS) {
     999           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error Renaming file: %s", tmp_line);
    1000             :                 }
    1001           0 :                 goto rename_errexit;
    1002             :         }
    1003             : 
    1004             :         /* Rename TO */
    1005           0 :         php_stream_printf(stream TSRMLS_CC, "RNTO %s\r\n", (resource_to->path != NULL ? resource_to->path : "/"));
    1006             : 
    1007           0 :         result = GET_FTP_RESULT(stream);
    1008           0 :         if (result < 200 || result > 299) {
    1009           0 :                 if (options & REPORT_ERRORS) {
    1010           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error Renaming file: %s", tmp_line);
    1011             :                 }
    1012           0 :                 goto rename_errexit;
    1013             :         }
    1014             : 
    1015           0 :         php_url_free(resource_from);
    1016           0 :         php_url_free(resource_to);
    1017           0 :         php_stream_close(stream);
    1018           0 :         return 1;
    1019             : 
    1020             : rename_errexit:
    1021           0 :         if (resource_from) {
    1022           0 :                 php_url_free(resource_from);
    1023             :         }
    1024           0 :         if (resource_to) {
    1025           0 :                 php_url_free(resource_to);
    1026             :         }
    1027           0 :         if (stream) {
    1028           0 :                 php_stream_close(stream);
    1029             :         }
    1030           0 :         return 0;
    1031             : }
    1032             : /* }}} */
    1033             : 
    1034             : /* {{{ php_stream_ftp_mkdir
    1035             :  */
    1036           0 : static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC)
    1037             : {
    1038           0 :         php_stream *stream = NULL;
    1039           0 :         php_url *resource = NULL;
    1040           0 :         int result, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
    1041             :         char tmp_line[512];
    1042             : 
    1043           0 :         stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC);
    1044           0 :         if (!stream) {
    1045           0 :                 if (options & REPORT_ERRORS) {
    1046           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", url);
    1047             :                 }
    1048           0 :                 goto mkdir_errexit;
    1049             :         }
    1050             : 
    1051           0 :         if (resource->path == NULL) {
    1052           0 :                 if (options & REPORT_ERRORS) {
    1053           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path provided in %s", url);
    1054             :                 }
    1055           0 :                 goto mkdir_errexit;
    1056             :         }
    1057             : 
    1058           0 :         if (!recursive) {
    1059           0 :                 php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", resource->path);
    1060           0 :                 result = GET_FTP_RESULT(stream);
    1061             :     } else {
    1062             :         /* we look for directory separator from the end of string, thus hopefuly reducing our work load */
    1063             :         char *p, *e, *buf;
    1064             : 
    1065           0 :         buf = estrdup(resource->path);
    1066           0 :         e = buf + strlen(buf);
    1067             : 
    1068             :         /* find a top level directory we need to create */
    1069           0 :         while ((p = strrchr(buf, '/'))) {
    1070           0 :             *p = '\0';
    1071           0 :                         php_stream_printf(stream TSRMLS_CC, "CWD %s\r\n", buf);
    1072           0 :                         result = GET_FTP_RESULT(stream);
    1073           0 :                         if (result >= 200 && result <= 299) {
    1074           0 :                                 *p = '/';
    1075           0 :                                 break;
    1076             :                         }
    1077             :         }
    1078           0 :         if (p == buf) {
    1079           0 :                         php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", resource->path);
    1080           0 :                         result = GET_FTP_RESULT(stream);
    1081             :         } else {
    1082           0 :                         php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", buf);
    1083           0 :                         result = GET_FTP_RESULT(stream);
    1084           0 :                         if (result >= 200 && result <= 299) {
    1085           0 :                                 if (!p) {
    1086           0 :                                         p = buf;
    1087             :                                 }
    1088             :                                 /* create any needed directories if the creation of the 1st directory worked */
    1089           0 :                                 while (++p != e) {
    1090           0 :                                         if (*p == '\0' && *(p + 1) != '\0') {
    1091           0 :                                                 *p = '/';
    1092           0 :                                                 php_stream_printf(stream TSRMLS_CC, "MKD %s\r\n", buf);
    1093           0 :                                                 result = GET_FTP_RESULT(stream);
    1094           0 :                                                 if (result < 200 || result > 299) {
    1095           0 :                                                         if (options & REPORT_ERRORS) {
    1096           0 :                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_line);
    1097             :                                                         }
    1098           0 :                                                         break;
    1099             :                                                 }
    1100             :                                         }
    1101             :                                 }
    1102             :                         }
    1103             :                 }
    1104           0 :         efree(buf);
    1105             :     }
    1106             : 
    1107           0 :         php_url_free(resource);
    1108           0 :         php_stream_close(stream);
    1109             : 
    1110           0 :         if (result < 200 || result > 299) {
    1111             :                 /* Failure */
    1112           0 :                 return 0;
    1113             :         }
    1114             : 
    1115           0 :         return 1;
    1116             : 
    1117             : mkdir_errexit:
    1118           0 :         if (resource) {
    1119           0 :                 php_url_free(resource);
    1120             :         }
    1121           0 :         if (stream) {
    1122           0 :                 php_stream_close(stream);
    1123             :         }
    1124           0 :         return 0;
    1125             : }
    1126             : /* }}} */
    1127             : 
    1128             : /* {{{ php_stream_ftp_rmdir
    1129             :  */
    1130           0 : static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
    1131             : {
    1132           0 :         php_stream *stream = NULL;
    1133           0 :         php_url *resource = NULL;
    1134             :         int result;
    1135             :         char tmp_line[512];
    1136             : 
    1137           0 :         stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC);
    1138           0 :         if (!stream) {
    1139           0 :                 if (options & REPORT_ERRORS) {
    1140           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to %s", url);
    1141             :                 }
    1142           0 :                 goto rmdir_errexit;
    1143             :         }
    1144             : 
    1145           0 :         if (resource->path == NULL) {
    1146           0 :                 if (options & REPORT_ERRORS) {
    1147           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path provided in %s", url);
    1148             :                 }
    1149           0 :                 goto rmdir_errexit;
    1150             :         }
    1151             : 
    1152           0 :         php_stream_printf(stream TSRMLS_CC, "RMD %s\r\n", resource->path);
    1153           0 :         result = GET_FTP_RESULT(stream);
    1154             : 
    1155           0 :         if (result < 200 || result > 299) {
    1156           0 :                 if (options & REPORT_ERRORS) {
    1157           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_line);
    1158             :                 }
    1159           0 :                 goto rmdir_errexit;
    1160             :         }
    1161             : 
    1162           0 :         php_url_free(resource);
    1163           0 :         php_stream_close(stream);
    1164             : 
    1165           0 :         return 1;
    1166             : 
    1167             : rmdir_errexit:
    1168           0 :         if (resource) {
    1169           0 :                 php_url_free(resource);
    1170             :         }
    1171           0 :         if (stream) {
    1172           0 :                 php_stream_close(stream);
    1173             :         }
    1174           0 :         return 0;
    1175             : }
    1176             : /* }}} */
    1177             : 
    1178             : static php_stream_wrapper_ops ftp_stream_wops = {
    1179             :         php_stream_url_wrap_ftp,
    1180             :         php_stream_ftp_stream_close, /* stream_close */
    1181             :         php_stream_ftp_stream_stat,
    1182             :         php_stream_ftp_url_stat, /* stat_url */
    1183             :         php_stream_ftp_opendir, /* opendir */
    1184             :         "ftp",
    1185             :         php_stream_ftp_unlink, /* unlink */
    1186             :         php_stream_ftp_rename, /* rename */
    1187             :         php_stream_ftp_mkdir,  /* mkdir */
    1188             :         php_stream_ftp_rmdir   /* rmdir */
    1189             : };
    1190             : 
    1191             : PHPAPI php_stream_wrapper php_stream_ftp_wrapper =      {
    1192             :         &ftp_stream_wops,
    1193             :         NULL,
    1194             :         1 /* is_url */
    1195             : };
    1196             : 
    1197             : 
    1198             : /*
    1199             :  * Local variables:
    1200             :  * tab-width: 4
    1201             :  * c-basic-offset: 4
    1202             :  * End:
    1203             :  * vim600: sw=4 ts=4 fdm=marker
    1204             :  * vim<600: sw=4 ts=4
    1205             :  */

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:37 +0000 (31 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.