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-23 Instrumented lines: 521
Code covered: 0.0 % Executed lines: 0
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:42 +0000 (34 hours ago)

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