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

LTP GCOV extension - code coverage report
Current view: directory - standard - ftp_fopen_wrapper.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 521
Code covered: 0.0 % Executed lines: 0
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:11 +0000 (3 days ago)

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