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: 164 542 30.3 %
Date: 2016-09-27 Functions: 7 14 50.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:08 +0000 (4 days ago)

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