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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:21 +0000 (5 days ago)

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