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

Generated by: LCOV version 1.10

Generated at Sat, 13 Sep 2014 16:24:34 +0000 (3 days ago)

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