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 - ftp - ftp.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 837
Code covered: 56.9 % Executed lines: 476
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: Andrew Skalski <askalski@chek.com>                          |
      16                 :    |          Stefan Esser <sesser@php.net> (resume functions)            |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: ftp.c 288034 2009-09-04 07:59:48Z srinatar $ */
      21                 : 
      22                 : #ifdef HAVE_CONFIG_H
      23                 : #include "config.h"
      24                 : #endif
      25                 : 
      26                 : #include "php.h"
      27                 : 
      28                 : #if HAVE_FTP
      29                 : 
      30                 : #include <stdio.h>
      31                 : #include <ctype.h>
      32                 : #include <stdlib.h>
      33                 : #ifdef HAVE_UNISTD_H
      34                 : #include <unistd.h>
      35                 : #endif
      36                 : #include <fcntl.h>
      37                 : #include <string.h>
      38                 : #include <time.h>
      39                 : #ifdef PHP_WIN32
      40                 : #include <winsock2.h>
      41                 : #elif defined(NETWARE)
      42                 : #ifdef USE_WINSOCK    /* Modified to use Winsock (NOVSOCK2.H), atleast for now */
      43                 : #include <novsock2.h>
      44                 : #else
      45                 : #include <sys/socket.h>
      46                 : #include <netinet/in.h>
      47                 : #include <netdb.h>
      48                 : #endif
      49                 : #else
      50                 : #ifdef HAVE_SYS_TYPES_H
      51                 : #include <sys/types.h>
      52                 : #endif
      53                 : #include <sys/socket.h>
      54                 : #include <netinet/in.h>
      55                 : #include <arpa/inet.h>
      56                 : #include <netdb.h>
      57                 : #endif
      58                 : #include <errno.h>
      59                 : 
      60                 : #if HAVE_SYS_TIME_H
      61                 : #include <sys/time.h>
      62                 : #endif
      63                 : 
      64                 : #ifdef HAVE_SYS_SELECT_H
      65                 : #include <sys/select.h>
      66                 : #endif
      67                 : 
      68                 : #if HAVE_OPENSSL_EXT
      69                 : #include <openssl/ssl.h>
      70                 : #endif
      71                 : 
      72                 : #include "ftp.h"
      73                 : #include "ext/standard/fsock.h"
      74                 : 
      75                 : /* Additional headers for NetWare */
      76                 : #if defined(NETWARE) && !defined(USE_WINSOCK)
      77                 : #include <sys/select.h>
      78                 : #endif
      79                 : 
      80                 : /* sends an ftp command, returns true on success, false on error.
      81                 :  * it sends the string "cmd args\r\n" if args is non-null, or
      82                 :  * "cmd\r\n" if args is null
      83                 :  */
      84                 : static int              ftp_putcmd(     ftpbuf_t *ftp,
      85                 :                                         const char *cmd,
      86                 :                                         const char *args);
      87                 : 
      88                 : /* wrapper around send/recv to handle timeouts */
      89                 : static int              my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len);
      90                 : static int              my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len);
      91                 : static int              my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen);
      92                 : 
      93                 : /* reads a line the socket , returns true on success, false on error */
      94                 : static int              ftp_readline(ftpbuf_t *ftp);
      95                 : 
      96                 : /* reads an ftp response, returns true on success, false on error */
      97                 : static int              ftp_getresp(ftpbuf_t *ftp);
      98                 : 
      99                 : /* sets the ftp transfer type */
     100                 : static int              ftp_type(ftpbuf_t *ftp, ftptype_t type);
     101                 : 
     102                 : /* opens up a data stream */
     103                 : static databuf_t*       ftp_getdata(ftpbuf_t *ftp TSRMLS_DC);
     104                 : 
     105                 : /* accepts the data connection, returns updated data buffer */
     106                 : static databuf_t*       data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC);
     107                 : 
     108                 : /* closes the data connection, returns NULL */
     109                 : static databuf_t*       data_close(ftpbuf_t *ftp, databuf_t *data);
     110                 : 
     111                 : /* generic file lister */
     112                 : static char**           ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC);
     113                 : 
     114                 : /* IP and port conversion box */
     115                 : union ipbox {
     116                 :         struct in_addr  ia[2];
     117                 :         unsigned short  s[4];
     118                 :         unsigned char   c[8];
     119                 : };
     120                 : 
     121                 : /* {{{ ftp_open
     122                 :  */
     123                 : ftpbuf_t*
     124                 : ftp_open(const char *host, short port, long timeout_sec TSRMLS_DC)
     125              29 : {
     126                 :         ftpbuf_t                *ftp;
     127                 :         socklen_t                size;
     128                 :         struct timeval tv;
     129                 : 
     130                 : 
     131                 :         /* alloc the ftp structure */
     132              29 :         ftp = ecalloc(1, sizeof(*ftp));
     133                 : 
     134              29 :         tv.tv_sec = timeout_sec;
     135              29 :         tv.tv_usec = 0;
     136                 : 
     137              29 :         ftp->fd = php_network_connect_socket_to_host(host,
     138                 :                         (unsigned short) (port ? port : 21), SOCK_STREAM,
     139                 :                         0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC);
     140              29 :         if (ftp->fd == -1) {
     141               1 :                 goto bail;
     142                 :         }
     143                 : 
     144                 :         /* Default Settings */
     145              28 :         ftp->timeout_sec = timeout_sec;
     146              28 :         ftp->nb = 0;
     147                 : 
     148              28 :         size = sizeof(ftp->localaddr);
     149              28 :         memset(&ftp->localaddr, 0, size);
     150              28 :         if (getsockname(ftp->fd, (struct sockaddr*) &ftp->localaddr, &size) != 0) {
     151               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "getsockname failed: %s (%d)", strerror(errno), errno);
     152               0 :                 goto bail;
     153                 :         }
     154                 : 
     155              28 :         if (!ftp_getresp(ftp) || ftp->resp != 220) {
     156                 :                 goto bail;
     157                 :         }
     158                 : 
     159              28 :         return ftp;
     160                 : 
     161               1 : bail:
     162               1 :         if (ftp->fd != -1) {
     163               0 :                 closesocket(ftp->fd);
     164                 :         }
     165               1 :         efree(ftp);
     166               1 :         return NULL;
     167                 : }
     168                 : /* }}} */
     169                 : 
     170                 : /* {{{ ftp_close
     171                 :  */
     172                 : ftpbuf_t*
     173                 : ftp_close(ftpbuf_t *ftp)
     174              28 : {
     175              28 :         if (ftp == NULL) {
     176               0 :                 return NULL;
     177                 :         }
     178              28 :         if (ftp->data) {
     179               3 :                 data_close(ftp, ftp->data);
     180                 :         }
     181              28 :         if (ftp->fd != -1) {
     182                 : #if HAVE_OPENSSL_EXT
     183              28 :                 if (ftp->ssl_active) {
     184               1 :                         SSL_shutdown(ftp->ssl_handle);
     185                 :                 }
     186                 : #endif          
     187              28 :                 closesocket(ftp->fd);
     188                 :         }       
     189              28 :         ftp_gc(ftp);
     190              28 :         efree(ftp);
     191              28 :         return NULL;
     192                 : }
     193                 : /* }}} */
     194                 : 
     195                 : /* {{{ ftp_gc
     196                 :  */
     197                 : void
     198                 : ftp_gc(ftpbuf_t *ftp)
     199              28 : {
     200              28 :         if (ftp == NULL) {
     201               0 :                 return;
     202                 :         }
     203              28 :         if (ftp->pwd) {
     204               1 :                 efree(ftp->pwd);
     205               1 :                 ftp->pwd = NULL;
     206                 :         }
     207              28 :         if (ftp->syst) {
     208               2 :                 efree(ftp->syst);
     209               2 :                 ftp->syst = NULL;
     210                 :         }
     211                 : }
     212                 : /* }}} */
     213                 : 
     214                 : /* {{{ ftp_quit
     215                 :  */
     216                 : int
     217                 : ftp_quit(ftpbuf_t *ftp)
     218               9 : {
     219               9 :         if (ftp == NULL) {
     220               0 :                 return 0;
     221                 :         }
     222                 : 
     223               9 :         if (!ftp_putcmd(ftp, "QUIT", NULL)) {
     224               0 :                 return 0;
     225                 :         }
     226               9 :         if (!ftp_getresp(ftp) || ftp->resp != 221) {
     227               9 :                 return 0;
     228                 :         }
     229                 : 
     230               0 :         if (ftp->pwd) {
     231               0 :                 efree(ftp->pwd);
     232               0 :                 ftp->pwd = NULL;
     233                 :         }
     234                 : 
     235               0 :         return 1;
     236                 : }
     237                 : /* }}} */
     238                 : 
     239                 : /* {{{ ftp_login
     240                 :  */
     241                 : int
     242                 : ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
     243              29 : {
     244                 : #if HAVE_OPENSSL_EXT
     245              29 :         SSL_CTX *ctx = NULL;
     246                 : #endif
     247              29 :         if (ftp == NULL) {
     248               0 :                 return 0;
     249                 :         }
     250                 : 
     251                 : #if HAVE_OPENSSL_EXT
     252              29 :         if (ftp->use_ssl && !ftp->ssl_active) {
     253               2 :                 if (!ftp_putcmd(ftp, "AUTH", "TLS")) {
     254               0 :                         return 0;
     255                 :                 }
     256               2 :                 if (!ftp_getresp(ftp)) {
     257               0 :                         return 0;
     258                 :                 }
     259                 :                         
     260               2 :                 if (ftp->resp != 234) {
     261               1 :                         if (!ftp_putcmd(ftp, "AUTH", "SSL")) {
     262               0 :                                 return 0;
     263                 :                         }
     264               1 :                         if (!ftp_getresp(ftp)) {
     265               0 :                                 return 0;
     266                 :                         }
     267                 :                                 
     268               1 :                         if (ftp->resp != 334) {
     269               1 :                                 return 0;
     270                 :                         } else {
     271               0 :                                 ftp->old_ssl = 1;
     272               0 :                                 ftp->use_ssl_for_data = 1;
     273                 :                         }
     274                 :                 }
     275                 :                 
     276               1 :                 ctx = SSL_CTX_new(SSLv23_client_method());
     277               1 :                 if (ctx == NULL) {
     278               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL context");
     279               0 :                         return 0;
     280                 :                 }
     281                 : 
     282               1 :                 SSL_CTX_set_options(ctx, SSL_OP_ALL);
     283                 : 
     284               1 :                 ftp->ssl_handle = SSL_new(ctx);
     285               1 :                 if (ftp->ssl_handle == NULL) {
     286               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL handle");
     287               0 :                         SSL_CTX_free(ctx);
     288               0 :                         return 0;
     289                 :                 }
     290                 : 
     291               1 :                 SSL_set_fd(ftp->ssl_handle, ftp->fd);
     292                 : 
     293               1 :                 if (SSL_connect(ftp->ssl_handle) <= 0) {
     294               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS handshake failed");
     295               0 :                         SSL_shutdown(ftp->ssl_handle);
     296               0 :                         return 0;
     297                 :                 }
     298                 : 
     299               1 :                 ftp->ssl_active = 1;
     300                 : 
     301               1 :                 if (!ftp->old_ssl) {
     302                 : 
     303                 :                         /* set protection buffersize to zero */
     304               1 :                         if (!ftp_putcmd(ftp, "PBSZ", "0")) {
     305               0 :                                 return 0;
     306                 :                         }
     307               1 :                         if (!ftp_getresp(ftp)) {
     308               0 :                                 return 0;
     309                 :                         }
     310                 : 
     311                 :                         /* enable data conn encryption */
     312               1 :                         if (!ftp_putcmd(ftp, "PROT", "P")) {
     313               0 :                                 return 0;
     314                 :                         }
     315               1 :                         if (!ftp_getresp(ftp)) {
     316               0 :                                 return 0;
     317                 :                         }
     318                 :                         
     319               1 :                         ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299);           
     320                 :                 }
     321                 :         }
     322                 : #endif
     323                 : 
     324              28 :         if (!ftp_putcmd(ftp, "USER", user)) {
     325               0 :                 return 0;
     326                 :         }
     327              28 :         if (!ftp_getresp(ftp)) {
     328               0 :                 return 0;
     329                 :         }
     330              28 :         if (ftp->resp == 230) {
     331               4 :                 return 1;
     332                 :         }
     333              24 :         if (ftp->resp != 331) {
     334               0 :                 return 0;
     335                 :         }
     336              24 :         if (!ftp_putcmd(ftp, "PASS", pass)) {
     337               0 :                 return 0;
     338                 :         }
     339              24 :         if (!ftp_getresp(ftp)) {
     340               0 :                 return 0;
     341                 :         }
     342              24 :         return (ftp->resp == 230);
     343                 : }
     344                 : /* }}} */
     345                 : 
     346                 : /* {{{ ftp_reinit
     347                 :  */
     348                 : int
     349                 : ftp_reinit(ftpbuf_t *ftp)
     350               0 : {
     351               0 :         if (ftp == NULL) {
     352               0 :                 return 0;
     353                 :         }       
     354                 : 
     355               0 :         ftp_gc(ftp);
     356                 : 
     357               0 :         ftp->nb = 0;
     358                 : 
     359               0 :         if (!ftp_putcmd(ftp, "REIN", NULL)) {
     360               0 :                 return 0;
     361                 :         }
     362               0 :         if (!ftp_getresp(ftp) || ftp->resp != 220) {
     363               0 :                 return 0;
     364                 :         }
     365                 : 
     366               0 :         return 1;
     367                 : }
     368                 : /* }}} */
     369                 : 
     370                 : /* {{{ ftp_syst
     371                 :  */
     372                 : const char*
     373                 : ftp_syst(ftpbuf_t *ftp)
     374               3 : {
     375                 :         char *syst, *end;
     376                 : 
     377               3 :         if (ftp == NULL) {
     378               0 :                 return NULL;
     379                 :         }
     380                 : 
     381                 :         /* default to cached value */
     382               3 :         if (ftp->syst) {
     383               0 :                 return ftp->syst;
     384                 :         }
     385               3 :         if (!ftp_putcmd(ftp, "SYST", NULL)) {
     386               0 :                 return NULL;
     387                 :         }
     388               3 :         if (!ftp_getresp(ftp) || ftp->resp != 215) { 
     389               1 :                 return NULL;
     390                 :         }
     391               2 :         syst = ftp->inbuf;
     392               6 :         while (*syst == ' ') {
     393               2 :                 syst++;
     394                 :         }
     395               2 :         if ((end = strchr(syst, ' '))) {
     396               2 :                 *end = 0;
     397                 :         }
     398               2 :         ftp->syst = estrdup(syst);
     399               2 :         if (end) {
     400               2 :                 *end = ' ';
     401                 :         }
     402               2 :         return ftp->syst;
     403                 : }
     404                 : /* }}} */
     405                 : 
     406                 : /* {{{ ftp_pwd
     407                 :  */
     408                 : const char*
     409                 : ftp_pwd(ftpbuf_t *ftp)
     410               6 : {
     411                 :         char *pwd, *end;
     412                 : 
     413               6 :         if (ftp == NULL) {
     414               0 :                 return NULL;
     415                 :         }
     416                 : 
     417                 :         /* default to cached value */
     418               6 :         if (ftp->pwd) {
     419               0 :                 return ftp->pwd;
     420                 :         }
     421               6 :         if (!ftp_putcmd(ftp, "PWD", NULL)) {
     422               0 :                 return NULL;
     423                 :         }
     424               6 :         if (!ftp_getresp(ftp) || ftp->resp != 257) { 
     425               1 :                 return NULL;
     426                 :         }
     427                 :         /* copy out the pwd from response */
     428               5 :         if ((pwd = strchr(ftp->inbuf, '"')) == NULL) { 
     429               0 :                 return NULL;
     430                 :         }
     431               5 :         if ((end = strrchr(++pwd, '"')) == NULL) { 
     432               0 :                 return NULL;
     433                 :         }
     434               5 :         ftp->pwd = estrndup(pwd, end - pwd);
     435                 : 
     436               5 :         return ftp->pwd;
     437                 : }
     438                 : /* }}} */
     439                 : 
     440                 : /* {{{ ftp_exec
     441                 :  */
     442                 : int
     443                 : ftp_exec(ftpbuf_t *ftp, const char *cmd)
     444               2 : {
     445               2 :         if (ftp == NULL) {
     446               0 :                 return 0;
     447                 :         }
     448               2 :         if (!ftp_putcmd(ftp, "SITE EXEC", cmd)) {
     449               0 :                 return 0;
     450                 :         }
     451               2 :         if (!ftp_getresp(ftp) || ftp->resp != 200) {
     452               1 :                 return 0;
     453                 :         }
     454                 : 
     455               1 :         return 1;
     456                 : }
     457                 : /* }}} */
     458                 : 
     459                 : /* {{{ ftp_raw
     460                 :  */
     461                 : void
     462                 : ftp_raw(ftpbuf_t *ftp, const char *cmd, zval *return_value)
     463               4 : {
     464               4 :         if (ftp == NULL || cmd == NULL) {
     465               0 :                 RETURN_NULL();
     466                 :         }
     467               4 :         if (!ftp_putcmd(ftp, cmd, NULL)) {
     468               0 :                 RETURN_NULL();
     469                 :         }
     470               4 :         array_init(return_value);
     471              14 :         while (ftp_readline(ftp)) {
     472              10 :                 add_next_index_string(return_value, ftp->inbuf, 1);
     473              10 :                 if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
     474               4 :                         return;
     475                 :                 }
     476                 :         }
     477                 : }
     478                 : /* }}} */
     479                 : 
     480                 : /* {{{ ftp_chdir
     481                 :  */
     482                 : int
     483                 : ftp_chdir(ftpbuf_t *ftp, const char *dir)
     484               4 : {
     485               4 :         if (ftp == NULL) {
     486               0 :                 return 0;
     487                 :         }
     488                 : 
     489               4 :         if (ftp->pwd) {
     490               3 :                 efree(ftp->pwd);
     491               3 :                 ftp->pwd = NULL;
     492                 :         }
     493                 : 
     494               4 :         if (!ftp_putcmd(ftp, "CWD", dir)) {
     495               0 :                 return 0;
     496                 :         }
     497               4 :         if (!ftp_getresp(ftp) || ftp->resp != 250) {
     498               1 :                 return 0;
     499                 :         }
     500               3 :         return 1;
     501                 : }
     502                 : /* }}} */
     503                 : 
     504                 : /* {{{ ftp_cdup
     505                 :  */
     506                 : int
     507                 : ftp_cdup(ftpbuf_t *ftp)
     508               2 : {
     509               2 :         if (ftp == NULL) {
     510               0 :                 return 0;
     511                 :         }
     512                 : 
     513               2 :         if (ftp->pwd) {
     514               1 :                 efree(ftp->pwd);
     515               1 :                 ftp->pwd = NULL;
     516                 :         }
     517                 : 
     518               2 :         if (!ftp_putcmd(ftp, "CDUP", NULL)) {
     519               0 :                 return 0;
     520                 :         }
     521               2 :         if (!ftp_getresp(ftp) || ftp->resp != 250) {
     522               1 :                 return 0;
     523                 :         }
     524               1 :         return 1;
     525                 : }
     526                 : /* }}} */
     527                 : 
     528                 : /* {{{ ftp_mkdir
     529                 :  */
     530                 : char*
     531                 : ftp_mkdir(ftpbuf_t *ftp, const char *dir)
     532               3 : {
     533                 :         char *mkd, *end;
     534                 : 
     535               3 :         if (ftp == NULL) {
     536               0 :                 return NULL;
     537                 :         }
     538               3 :         if (!ftp_putcmd(ftp, "MKD", dir)) {
     539               0 :                 return NULL;
     540                 :         }
     541               3 :         if (!ftp_getresp(ftp) || ftp->resp != 257) {
     542               1 :                 return NULL;
     543                 :         }
     544                 :         /* copy out the dir from response */
     545               2 :         if ((mkd = strchr(ftp->inbuf, '"')) == NULL) {
     546               1 :                 mkd = estrdup(dir);
     547               1 :                 return mkd;
     548                 :         }
     549               1 :         if ((end = strrchr(++mkd, '"')) == NULL) {
     550               0 :                 return NULL;
     551                 :         }
     552               1 :         *end = 0;
     553               1 :         mkd = estrdup(mkd);
     554               1 :         *end = '"';
     555                 : 
     556               1 :         return mkd;
     557                 : }
     558                 : /* }}} */
     559                 : 
     560                 : /* {{{ ftp_rmdir
     561                 :  */
     562                 : int
     563                 : ftp_rmdir(ftpbuf_t *ftp, const char *dir)
     564               2 : {
     565               2 :         if (ftp == NULL) {
     566               0 :                 return 0;
     567                 :         }
     568               2 :         if (!ftp_putcmd(ftp, "RMD", dir)) {
     569               0 :                 return 0;
     570                 :         }
     571               2 :         if (!ftp_getresp(ftp) || ftp->resp != 250) {
     572               1 :                 return 0;
     573                 :         }
     574               1 :         return 1;
     575                 : }
     576                 : /* }}} */
     577                 : 
     578                 : /* {{{ ftp_chmod
     579                 :  */
     580                 : int
     581                 : ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filename_len)
     582               2 : {
     583                 :         char *buffer;
     584                 : 
     585               2 :         if (ftp == NULL || filename_len <= 0) {
     586               0 :                 return 0;
     587                 :         }
     588                 : 
     589               2 :         spprintf(&buffer, 0, "CHMOD %o %s", mode, filename);
     590                 : 
     591               2 :         if (!ftp_putcmd(ftp, "SITE", buffer)) {
     592               0 :                 efree(buffer);
     593               0 :                 return 0;
     594                 :         }
     595                 : 
     596               2 :         efree(buffer);
     597                 : 
     598               2 :         if (!ftp_getresp(ftp) || ftp->resp != 200) {
     599               1 :                 return 0;
     600                 :         }
     601                 :         
     602               1 :         return 1;
     603                 : }
     604                 : /* }}} */
     605                 : 
     606                 : /* {{{ ftp_alloc
     607                 :  */
     608                 : int
     609                 : ftp_alloc(ftpbuf_t *ftp, const int size, char **response)
     610               3 : {
     611                 :         char buffer[64];
     612                 : 
     613               3 :         if (ftp == NULL || size <= 0) {
     614               0 :                 return 0;
     615                 :         }
     616                 : 
     617               3 :         snprintf(buffer, sizeof(buffer) - 1, "%d", size);
     618                 : 
     619               3 :         if (!ftp_putcmd(ftp, "ALLO", buffer)) {
     620               0 :                 return 0;
     621                 :         }
     622                 : 
     623               3 :         if (!ftp_getresp(ftp)) {
     624               0 :                 return 0;
     625                 :         }
     626                 : 
     627               3 :         if (response && ftp->inbuf) {
     628               1 :                 *response = estrdup(ftp->inbuf);
     629                 :         }
     630                 : 
     631               3 :         if (ftp->resp < 200 || ftp->resp >= 300) {
     632               1 :                 return 0;
     633                 :         }
     634                 : 
     635               2 :         return 1;       
     636                 : }
     637                 : /* }}} */
     638                 : 
     639                 : /* {{{ ftp_nlist
     640                 :  */
     641                 : char**
     642                 : ftp_nlist(ftpbuf_t *ftp, const char *path TSRMLS_DC)
     643               6 : {
     644               6 :         return ftp_genlist(ftp, "NLST", path TSRMLS_CC);
     645                 : }
     646                 : /* }}} */
     647                 : 
     648                 : /* {{{ ftp_list
     649                 :  */
     650                 : char**
     651                 : ftp_list(ftpbuf_t *ftp, const char *path, int recursive TSRMLS_DC)
     652               1 : {
     653               1 :         return ftp_genlist(ftp, ((recursive) ? "LIST -R" : "LIST"), path TSRMLS_CC);
     654                 : }
     655                 : /* }}} */
     656                 : 
     657                 : /* {{{ ftp_type
     658                 :  */
     659                 : int
     660                 : ftp_type(ftpbuf_t *ftp, ftptype_t type)
     661              22 : {
     662              22 :         char typechar[2] = "?";
     663                 : 
     664              22 :         if (ftp == NULL) {
     665               0 :                 return 0;
     666                 :         }
     667              22 :         if (type == ftp->type) { 
     668               4 :                 return 1;
     669                 :         }
     670              18 :         if (type == FTPTYPE_ASCII) {
     671              14 :                 typechar[0] = 'A';
     672               4 :         } else if (type == FTPTYPE_IMAGE) {
     673               4 :                 typechar[0] = 'I';
     674                 :         } else {
     675               0 :                 return 0;
     676                 :         }
     677              18 :         if (!ftp_putcmd(ftp, "TYPE", typechar)) {
     678               0 :                 return 0;
     679                 :         }
     680              18 :         if (!ftp_getresp(ftp) || ftp->resp != 200) {
     681               1 :                 return 0;
     682                 :         }
     683              17 :         ftp->type = type;
     684                 : 
     685              17 :         return 1;
     686                 : }
     687                 : /* }}} */
     688                 : 
     689                 : /* {{{ ftp_pasv
     690                 :  */
     691                 : int
     692                 : ftp_pasv(ftpbuf_t *ftp, int pasv)
     693               0 : {
     694                 :         char                    *ptr;
     695                 :         union ipbox             ipbox;
     696                 :         unsigned long           b[6];
     697                 :         socklen_t                       n;
     698                 :         struct sockaddr *sa;
     699                 :         struct sockaddr_in *sin;
     700                 : 
     701               0 :         if (ftp == NULL) {
     702               0 :                 return 0;
     703                 :         }
     704               0 :         if (pasv && ftp->pasv == 2) {
     705               0 :                 return 1;
     706                 :         }
     707               0 :         ftp->pasv = 0;
     708               0 :         if (!pasv) {
     709               0 :                 return 1;
     710                 :         }
     711               0 :         n = sizeof(ftp->pasvaddr);
     712               0 :         memset(&ftp->pasvaddr, 0, n);
     713               0 :         sa = (struct sockaddr *) &ftp->pasvaddr;
     714                 : 
     715                 : #if HAVE_IPV6
     716               0 :         if (getpeername(ftp->fd, sa, &n) < 0) {
     717               0 :                 return 0;
     718                 :         }
     719               0 :         if (sa->sa_family == AF_INET6) {
     720               0 :                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
     721                 :                 char *endptr, delimiter;
     722                 : 
     723                 :                 /* try EPSV first */
     724               0 :                 if (!ftp_putcmd(ftp, "EPSV", NULL)) {
     725               0 :                         return 0;
     726                 :                 }
     727               0 :                 if (!ftp_getresp(ftp)) {
     728               0 :                         return 0;
     729                 :                 }
     730               0 :                 if (ftp->resp == 229) {
     731                 :                         /* parse out the port */
     732               0 :                         for (ptr = ftp->inbuf; *ptr && *ptr != '('; ptr++);
     733               0 :                         if (!*ptr) {
     734               0 :                                 return 0;
     735                 :                         }
     736               0 :                         delimiter = *++ptr;
     737               0 :                         for (n = 0; *ptr && n < 3; ptr++) {
     738               0 :                                 if (*ptr == delimiter) {
     739               0 :                                         n++;
     740                 :                                 }
     741                 :                         }
     742                 : 
     743               0 :                         sin6->sin6_port = htons((unsigned short) strtoul(ptr, &endptr, 10));
     744               0 :                         if (ptr == endptr || *endptr != delimiter) {
     745               0 :                                 return 0;
     746                 :                         }
     747               0 :                         ftp->pasv = 2;
     748               0 :                         return 1;
     749                 :                 }
     750                 :         }
     751                 : 
     752                 :         /* fall back to PASV */
     753                 : #endif
     754                 : 
     755               0 :         if (!ftp_putcmd(ftp, "PASV", NULL)) {
     756               0 :                 return 0;
     757                 :         }
     758               0 :         if (!ftp_getresp(ftp) || ftp->resp != 227) { 
     759               0 :                 return 0;
     760                 :         }
     761                 :         /* parse out the IP and port */
     762               0 :         for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
     763               0 :         n = sscanf(ptr, "%lu,%lu,%lu,%lu,%lu,%lu", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]);
     764               0 :         if (n != 6) {
     765               0 :                 return 0;
     766                 :         }
     767               0 :         for (n = 0; n < 6; n++) {
     768               0 :                 ipbox.c[n] = (unsigned char) b[n];
     769                 :         }
     770               0 :         sin = (struct sockaddr_in *) sa;
     771               0 :         sin->sin_family = AF_INET;
     772               0 :         sin->sin_addr = ipbox.ia[0];
     773               0 :         sin->sin_port = ipbox.s[2];
     774                 : 
     775               0 :         ftp->pasv = 2;
     776                 : 
     777               0 :         return 1;
     778                 : }
     779                 : /* }}} */
     780                 : 
     781                 : /* {{{ ftp_get
     782                 :  */
     783                 : int
     784                 : ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC)
     785               9 : {
     786               9 :         databuf_t               *data = NULL;
     787                 :         int                     lastch;
     788                 :         size_t                  rcvd;
     789                 :         char                    arg[11];
     790                 : 
     791               9 :         if (ftp == NULL) {
     792               0 :                 return 0;
     793                 :         }
     794               9 :         if (!ftp_type(ftp, type)) {
     795               0 :                 goto bail;
     796                 :         }
     797                 : 
     798               9 :         if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
     799               0 :                 goto bail;
     800                 :         }
     801                 :         
     802               9 :         ftp->data = data;
     803                 : 
     804               9 :         if (resumepos > 0) {
     805                 :                 if (resumepos > 2147483647) {
     806                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483647 bytes.");
     807                 :                         goto bail;
     808                 :                 }
     809               2 :                 snprintf(arg, sizeof(arg), "%u", resumepos);
     810               2 :                 if (!ftp_putcmd(ftp, "REST", arg)) {
     811               0 :                         goto bail;
     812                 :                 }
     813               2 :                 if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
     814                 :                         goto bail;
     815                 :                 }
     816                 :         }
     817                 : 
     818               9 :         if (!ftp_putcmd(ftp, "RETR", path)) {
     819               0 :                 goto bail;
     820                 :         }
     821               9 :         if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
     822                 :                 goto bail;
     823                 :         }
     824                 : 
     825               7 :         if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
     826               0 :                 goto bail;
     827                 :         }
     828                 : 
     829               7 :         lastch = 0;
     830              21 :         while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
     831               7 :                 if (rcvd == -1) {
     832               0 :                         goto bail;
     833                 :                 }
     834                 : 
     835               7 :                 if (type == FTPTYPE_ASCII) {
     836                 : #ifndef PHP_WIN32
     837                 :                         char *s;
     838                 : #endif
     839               5 :                         char *ptr = data->buf;
     840               5 :                         char *e = ptr + rcvd;
     841                 :                         /* logic depends on the OS EOL
     842                 :                          * Win32 -> \r\n
     843                 :                          * Everything Else \n
     844                 :                          */
     845                 : #ifdef PHP_WIN32
     846                 :                         php_stream_write(outstream, ptr, (e - ptr));
     847                 :                         ptr = e;
     848                 : #else
     849              15 :                         while (e > ptr && (s = memchr(ptr, '\r', (e - ptr)))) {
     850               5 :                                 php_stream_write(outstream, ptr, (s - ptr));
     851               5 :                                 if (*(s + 1) == '\n') {
     852               5 :                                         s++;
     853               5 :                                         php_stream_putc(outstream, '\n');
     854                 :                                 }
     855               5 :                                 ptr = s + 1;
     856                 :                         }
     857                 : #endif
     858               5 :                         if (ptr < e) {
     859               0 :                                 php_stream_write(outstream, ptr, (e - ptr));
     860                 :                         }
     861               2 :                 } else if (rcvd != php_stream_write(outstream, data->buf, rcvd)) {
     862               0 :                         goto bail;
     863                 :                 }
     864                 :         }
     865                 : 
     866               7 :         ftp->data = data = data_close(ftp, data);
     867                 : 
     868               7 :         if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
     869                 :                 goto bail;
     870                 :         }
     871                 : 
     872               7 :         return 1;
     873               2 : bail:
     874               2 :         ftp->data = data_close(ftp, data);
     875               2 :         return 0;
     876                 : }
     877                 : /* }}} */
     878                 : 
     879                 : /* {{{ ftp_put
     880                 :  */
     881                 : int
     882                 : ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC)
     883               2 : {
     884               2 :         databuf_t               *data = NULL;
     885                 :         int                     size;
     886                 :         char                    *ptr;
     887                 :         int                     ch;
     888                 :         char                    arg[11];
     889                 : 
     890               2 :         if (ftp == NULL) {
     891               0 :                 return 0;
     892                 :         }
     893               2 :         if (!ftp_type(ftp, type)) {
     894               0 :                 goto bail;
     895                 :         }
     896               2 :         if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
     897               0 :                 goto bail;
     898                 :         }
     899               2 :         ftp->data = data;    
     900                 : 
     901               2 :         if (startpos > 0) {
     902                 :                 if (startpos > 2147483647) {
     903                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes.");
     904                 :                         goto bail;
     905                 :                 }
     906               0 :                 snprintf(arg, sizeof(arg), "%u", startpos);
     907               0 :                 if (!ftp_putcmd(ftp, "REST", arg)) {
     908               0 :                         goto bail;
     909                 :                 }
     910               0 :                 if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
     911                 :                         goto bail;
     912                 :                 }
     913                 :         }
     914                 : 
     915               2 :         if (!ftp_putcmd(ftp, "STOR", path)) {
     916               0 :                 goto bail;
     917                 :         }
     918               2 :         if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
     919                 :                 goto bail;
     920                 :         }
     921               2 :         if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
     922               0 :                 goto bail;
     923                 :         }
     924                 : 
     925               2 :         size = 0;
     926               2 :         ptr = data->buf;
     927            1050 :         while (!php_stream_eof(instream) && (ch = php_stream_getc(instream))!=EOF) {
     928                 :                 /* flush if necessary */
     929            1046 :                 if (FTP_BUFSIZE - size < 2) {
     930               0 :                         if (my_send(ftp, data->fd, data->buf, size) != size) {
     931               0 :                                 goto bail;
     932                 :                         }
     933               0 :                         ptr = data->buf;
     934               0 :                         size = 0;
     935                 :                 }
     936                 : 
     937            1046 :                 if (ch == '\n' && type == FTPTYPE_ASCII) {
     938              25 :                         *ptr++ = '\r';
     939              25 :                         size++;
     940                 :                 }
     941                 : 
     942            1046 :                 *ptr++ = ch;
     943            1046 :                 size++;
     944                 :         }
     945                 : 
     946               2 :         if (size && my_send(ftp, data->fd, data->buf, size) != size) {
     947               0 :                 goto bail;
     948                 :         }
     949               2 :         ftp->data = data = data_close(ftp, data);
     950                 : 
     951               2 :         if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
     952                 :                 goto bail;
     953                 :         }
     954               2 :         return 1;
     955               0 : bail:
     956               0 :         ftp->data = data_close(ftp, data);
     957               0 :         return 0;
     958                 : }
     959                 : /* }}} */
     960                 : 
     961                 : /* {{{ ftp_size
     962                 :  */
     963                 : int
     964                 : ftp_size(ftpbuf_t *ftp, const char *path)
     965               1 : {
     966               1 :         if (ftp == NULL) {
     967               0 :                 return -1;
     968                 :         }
     969               1 :         if (!ftp_type(ftp, FTPTYPE_IMAGE)) {
     970               1 :                 return -1;
     971                 :         }
     972               0 :         if (!ftp_putcmd(ftp, "SIZE", path)) {
     973               0 :                 return -1;
     974                 :         }
     975               0 :         if (!ftp_getresp(ftp) || ftp->resp != 213) {
     976               0 :                 return -1;
     977                 :         }
     978               0 :         return atoi(ftp->inbuf);
     979                 : }
     980                 : /* }}} */
     981                 : 
     982                 : /* {{{ ftp_mdtm
     983                 :  */
     984                 : time_t
     985                 : ftp_mdtm(ftpbuf_t *ftp, const char *path)
     986               7 : {
     987                 :         time_t          stamp;
     988                 :         struct tm       *gmt, tmbuf;
     989                 :         struct tm       tm;
     990                 :         char            *ptr;
     991                 :         int             n;
     992                 : 
     993               7 :         if (ftp == NULL) {
     994               0 :                 return -1;
     995                 :         }
     996               7 :         if (!ftp_putcmd(ftp, "MDTM", path)) {
     997               0 :                 return -1;
     998                 :         }
     999               7 :         if (!ftp_getresp(ftp) || ftp->resp != 213) {
    1000               3 :                 return -1;
    1001                 :         }
    1002                 :         /* parse out the timestamp */
    1003               4 :         for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
    1004               4 :         n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
    1005               4 :         if (n != 6) {
    1006               0 :                 return -1;
    1007                 :         }
    1008               4 :         tm.tm_year -= 1900;
    1009               4 :         tm.tm_mon--;
    1010               4 :         tm.tm_isdst = -1;
    1011                 : 
    1012                 :         /* figure out the GMT offset */
    1013               4 :         stamp = time(NULL);
    1014               4 :         gmt = php_gmtime_r(&stamp, &tmbuf);
    1015               4 :         if (!gmt) {
    1016               0 :                 return -1;
    1017                 :         }
    1018               4 :         gmt->tm_isdst = -1;
    1019                 : 
    1020                 :         /* apply the GMT offset */
    1021               4 :         tm.tm_sec += stamp - mktime(gmt);
    1022               4 :         tm.tm_isdst = gmt->tm_isdst;
    1023                 : 
    1024               4 :         stamp = mktime(&tm);
    1025                 : 
    1026               4 :         return stamp;
    1027                 : }
    1028                 : /* }}} */
    1029                 : 
    1030                 : /* {{{ ftp_delete
    1031                 :  */
    1032                 : int
    1033                 : ftp_delete(ftpbuf_t *ftp, const char *path)
    1034               1 : {
    1035               1 :         if (ftp == NULL) {
    1036               0 :                 return 0;
    1037                 :         }
    1038               1 :         if (!ftp_putcmd(ftp, "DELE", path)) {
    1039               0 :                 return 0;
    1040                 :         }
    1041               1 :         if (!ftp_getresp(ftp) || ftp->resp != 250) {
    1042               1 :                 return 0;
    1043                 :         }
    1044                 : 
    1045               0 :         return 1;
    1046                 : }
    1047                 : /* }}} */
    1048                 : 
    1049                 : /* {{{ ftp_rename
    1050                 :  */
    1051                 : int
    1052                 : ftp_rename(ftpbuf_t *ftp, const char *src, const char *dest)
    1053               0 : {
    1054               0 :         if (ftp == NULL) {
    1055               0 :                 return 0;
    1056                 :         }
    1057               0 :         if (!ftp_putcmd(ftp, "RNFR", src)) {
    1058               0 :                 return 0;
    1059                 :         }
    1060               0 :         if (!ftp_getresp(ftp) || ftp->resp != 350) {
    1061               0 :                 return 0;
    1062                 :         }
    1063               0 :         if (!ftp_putcmd(ftp, "RNTO", dest)) {
    1064               0 :                 return 0;
    1065                 :         }
    1066               0 :         if (!ftp_getresp(ftp) || ftp->resp != 250) {
    1067               0 :                 return 0;
    1068                 :         }
    1069               0 :         return 1;
    1070                 : }
    1071                 : /* }}} */
    1072                 : 
    1073                 : /* {{{ ftp_site
    1074                 :  */
    1075                 : int
    1076                 : ftp_site(ftpbuf_t *ftp, const char *cmd)
    1077               0 : {
    1078               0 :         if (ftp == NULL) {
    1079               0 :                 return 0;
    1080                 :         }
    1081               0 :         if (!ftp_putcmd(ftp, "SITE", cmd)) {
    1082               0 :                 return 0;
    1083                 :         }
    1084               0 :         if (!ftp_getresp(ftp) || ftp->resp < 200 || ftp->resp >= 300) {
    1085               0 :                 return 0;
    1086                 :         }
    1087                 : 
    1088               0 :         return 1;
    1089                 : }
    1090                 : /* }}} */
    1091                 : 
    1092                 : /* static functions */
    1093                 : 
    1094                 : /* {{{ ftp_putcmd
    1095                 :  */
    1096                 : int
    1097                 : ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args)
    1098             169 : {
    1099                 :         int             size;
    1100                 :         char            *data;
    1101                 : 
    1102             169 :         if (strpbrk(cmd, "\r\n")) {
    1103               0 :                 return 0;
    1104                 :         } 
    1105                 :         /* build the output buffer */
    1106             311 :         if (args && args[0]) {
    1107                 :                 /* "cmd args\r\n\0" */
    1108             142 :                 if (strlen(cmd) + strlen(args) + 4 > FTP_BUFSIZE) {
    1109               0 :                         return 0;
    1110                 :                 }
    1111             142 :                 if (strpbrk(args, "\r\n")) {
    1112               0 :                         return 0;
    1113                 :                 }
    1114             142 :                 size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s %s\r\n", cmd, args);
    1115                 :         } else {
    1116                 :                 /* "cmd\r\n\0" */
    1117              27 :                 if (strlen(cmd) + 3 > FTP_BUFSIZE) {
    1118               0 :                         return 0;
    1119                 :                 }
    1120              27 :                 size = slprintf(ftp->outbuf, sizeof(ftp->outbuf), "%s\r\n", cmd);
    1121                 :         }
    1122                 : 
    1123             169 :         data = ftp->outbuf;
    1124                 : 
    1125             169 :         if (my_send(ftp, ftp->fd, data, size) != size) {
    1126               0 :                 return 0;
    1127                 :         }
    1128             169 :         return 1;
    1129                 : }
    1130                 : /* }}} */
    1131                 : 
    1132                 : /* {{{ ftp_readline
    1133                 :  */
    1134                 : int
    1135                 : ftp_readline(ftpbuf_t *ftp)
    1136             243 : {
    1137                 :         int             size, rcvd;
    1138                 :         char            *data, *eol;
    1139                 : 
    1140                 :         /* shift the extra to the front */
    1141             243 :         size = FTP_BUFSIZE;
    1142             243 :         rcvd = 0;
    1143             243 :         if (ftp->extra) {
    1144              31 :                 memmove(ftp->inbuf, ftp->extra, ftp->extralen);
    1145              31 :                 rcvd = ftp->extralen;
    1146                 :         }
    1147                 : 
    1148             243 :         data = ftp->inbuf;
    1149                 : 
    1150                 :         do {
    1151             446 :                 size -= rcvd;
    1152            6033 :                 for (eol = data; rcvd; rcvd--, eol++) {
    1153            5821 :                         if (*eol == '\r') {
    1154             234 :                                 *eol = 0;
    1155             234 :                                 ftp->extra = eol + 1;
    1156             234 :                                 if (rcvd > 1 && *(eol + 1) == '\n') {
    1157             234 :                                         ftp->extra++;
    1158             234 :                                         rcvd--;
    1159                 :                                 }
    1160             234 :                                 if ((ftp->extralen = --rcvd) == 0) {
    1161             203 :                                         ftp->extra = NULL;
    1162                 :                                 }
    1163             234 :                                 return 1;
    1164            5587 :                         } else if (*eol == '\n') {
    1165               0 :                                 *eol = 0;
    1166               0 :                                 ftp->extra = eol + 1;
    1167               0 :                                 if ((ftp->extralen = --rcvd) == 0) {
    1168               0 :                                         ftp->extra = NULL;
    1169                 :                                 }
    1170               0 :                                 return 1;
    1171                 :                         }
    1172                 :                 }
    1173                 : 
    1174             212 :                 data = eol;
    1175             212 :                 if ((rcvd = my_recv(ftp, ftp->fd, data, size)) < 1) {
    1176               9 :                         return 0;
    1177                 :                 }
    1178             203 :         } while (size);
    1179                 : 
    1180               0 :         return 0;
    1181                 : }
    1182                 : /* }}} */
    1183                 : 
    1184                 : /* {{{ ftp_getresp
    1185                 :  */
    1186                 : int
    1187                 : ftp_getresp(ftpbuf_t *ftp)
    1188             205 : {
    1189                 :         char *buf;
    1190                 : 
    1191             205 :         if (ftp == NULL) {
    1192               0 :                 return 0;
    1193                 :         }
    1194             205 :         buf = ftp->inbuf;
    1195             205 :         ftp->resp = 0;
    1196                 : 
    1197                 :         while (1) {
    1198                 : 
    1199             233 :                 if (!ftp_readline(ftp)) {
    1200               9 :                         return 0;
    1201                 :                 }
    1202                 : 
    1203                 :                 /* Break out when the end-tag is found */
    1204             224 :                 if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
    1205             196 :                         break;
    1206                 :                 }
    1207              28 :         }
    1208                 : 
    1209                 :         /* translate the tag */
    1210             196 :         if (!isdigit(ftp->inbuf[0]) || !isdigit(ftp->inbuf[1]) || !isdigit(ftp->inbuf[2])) {
    1211               0 :                 return 0;
    1212                 :         }
    1213                 : 
    1214             196 :         ftp->resp = 100 * (ftp->inbuf[0] - '0') + 10 * (ftp->inbuf[1] - '0') + (ftp->inbuf[2] - '0');
    1215                 : 
    1216             196 :         memmove(ftp->inbuf, ftp->inbuf + 4, FTP_BUFSIZE - 4);
    1217                 : 
    1218             196 :         if (ftp->extra) {
    1219               0 :                 ftp->extra -= 4;
    1220                 :         }
    1221             196 :         return 1;
    1222                 : }
    1223                 : /* }}} */
    1224                 : 
    1225                 : /* {{{ my_send
    1226                 :  */
    1227                 : int
    1228                 : my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
    1229             171 : {
    1230                 :         int             n, size, sent;
    1231                 : 
    1232             171 :         size = len;
    1233             513 :         while (size) {
    1234             171 :                 n = php_pollfd_for_ms(s, POLLOUT, ftp->timeout_sec * 1000);
    1235                 : 
    1236             171 :                 if (n < 1) {
    1237                 : 
    1238                 : #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
    1239               0 :                         if (n == 0) {
    1240               0 :                                 errno = ETIMEDOUT;
    1241                 :                         }
    1242                 : #endif
    1243               0 :                         return -1;
    1244                 :                 }
    1245                 : 
    1246                 : #if HAVE_OPENSSL_EXT
    1247             178 :                 if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
    1248               7 :                         sent = SSL_write(ftp->ssl_handle, buf, size);
    1249             164 :                 } else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {     
    1250               0 :                         sent = SSL_write(ftp->data->ssl_handle, buf, size);
    1251                 :                 } else {
    1252                 : #endif
    1253             164 :                         sent = send(s, buf, size, 0);
    1254                 : #if HAVE_OPENSSL_EXT
    1255                 :                 }
    1256                 : #endif
    1257             171 :                 if (sent == -1) {
    1258               0 :                         return -1;
    1259                 :                 }
    1260                 : 
    1261             171 :                 buf = (char*) buf + sent;
    1262             171 :                 size -= sent;
    1263                 :         }
    1264                 : 
    1265             171 :         return len;
    1266                 : }
    1267                 : /* }}} */
    1268                 : 
    1269                 : /* {{{ my_recv
    1270                 :  */
    1271                 : int
    1272                 : my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
    1273             234 : {
    1274                 :         int             n, nr_bytes;
    1275                 : 
    1276             234 :         n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000);
    1277             234 :         if (n < 1) {
    1278                 : #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
    1279               0 :                 if (n == 0) {
    1280               0 :                         errno = ETIMEDOUT;
    1281                 :                 }
    1282                 : #endif
    1283               0 :                 return -1;
    1284                 :         }
    1285                 : 
    1286                 : #if HAVE_OPENSSL_EXT
    1287             244 :         if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
    1288              10 :                 nr_bytes = SSL_read(ftp->ssl_handle, buf, len);
    1289             224 :         } else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {     
    1290               0 :                 nr_bytes = SSL_read(ftp->data->ssl_handle, buf, len);
    1291                 :         } else {
    1292                 : #endif
    1293             224 :                 nr_bytes = recv(s, buf, len, 0);
    1294                 : #if HAVE_OPENSSL_EXT
    1295                 :         }
    1296                 : #endif  
    1297             234 :         return (nr_bytes);
    1298                 : }
    1299                 : /* }}} */
    1300                 : 
    1301                 : /* {{{ data_available
    1302                 :  */
    1303                 : int
    1304                 : data_available(ftpbuf_t *ftp, php_socket_t s)
    1305               3 : {
    1306                 :         int             n;
    1307                 : 
    1308               3 :         n = php_pollfd_for_ms(s, PHP_POLLREADABLE, 1000);
    1309               3 :         if (n < 1) {
    1310                 : #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
    1311               0 :                 if (n == 0) {
    1312               0 :                         errno = ETIMEDOUT;
    1313                 :                 }
    1314                 : #endif
    1315               0 :                 return 0;
    1316                 :         }
    1317                 : 
    1318               3 :         return 1;
    1319                 : }
    1320                 : /* }}} */
    1321                 : /* {{{ data_writeable
    1322                 :  */
    1323                 : int
    1324                 : data_writeable(ftpbuf_t *ftp, php_socket_t s)
    1325               0 : {
    1326                 :         int             n;
    1327                 : 
    1328               0 :         n = php_pollfd_for_ms(s, POLLOUT, 1000);
    1329               0 :         if (n < 1) {
    1330                 : #ifndef PHP_WIN32
    1331               0 :                 if (n == 0) {
    1332               0 :                         errno = ETIMEDOUT;
    1333                 :                 }
    1334                 : #endif
    1335               0 :                 return 0;
    1336                 :         }
    1337                 : 
    1338               0 :         return 1;
    1339                 : }
    1340                 : /* }}} */
    1341                 : 
    1342                 : /* {{{ my_accept
    1343                 :  */
    1344                 : int
    1345                 : my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen)
    1346              15 : {
    1347                 :         int             n;
    1348                 : 
    1349              15 :         n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000);
    1350              15 :         if (n < 1) {
    1351                 : #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
    1352               0 :                 if (n == 0) {
    1353               0 :                         errno = ETIMEDOUT;
    1354                 :                 }
    1355                 : #endif
    1356               0 :                 return -1;
    1357                 :         }
    1358                 : 
    1359              15 :         return accept(s, addr, addrlen);
    1360                 : }
    1361                 : /* }}} */
    1362                 : 
    1363                 : /* {{{ ftp_getdata
    1364                 :  */
    1365                 : databuf_t*
    1366                 : ftp_getdata(ftpbuf_t *ftp TSRMLS_DC)
    1367              21 : {
    1368              21 :         int                     fd = -1;
    1369                 :         databuf_t               *data;
    1370                 :         php_sockaddr_storage addr;
    1371                 :         struct sockaddr *sa;
    1372                 :         socklen_t               size;
    1373                 :         union ipbox             ipbox;
    1374                 :         char                    arg[sizeof("255, 255, 255, 255, 255, 255")];
    1375                 :         struct timeval  tv;
    1376                 : 
    1377                 : 
    1378                 :         /* ask for a passive connection if we need one */
    1379              21 :         if (ftp->pasv && !ftp_pasv(ftp, 1)) {
    1380               0 :                 return NULL;
    1381                 :         }
    1382                 :         /* alloc the data structure */
    1383              21 :         data = ecalloc(1, sizeof(*data));
    1384              21 :         data->listener = -1;
    1385              21 :         data->fd = -1;
    1386              21 :         data->type = ftp->type;
    1387                 : 
    1388              21 :         sa = (struct sockaddr *) &ftp->localaddr;
    1389                 :         /* bind/listen */
    1390              21 :         if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == SOCK_ERR) {
    1391               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "socket() failed: %s (%d)", strerror(errno), errno);
    1392               0 :                 goto bail;
    1393                 :         }
    1394                 : 
    1395                 :         /* passive connection handler */
    1396              21 :         if (ftp->pasv) {
    1397                 :                 /* clear the ready status */
    1398               0 :                 ftp->pasv = 1;
    1399                 : 
    1400                 :                 /* connect */
    1401                 :                 /* Win 95/98 seems not to like size > sizeof(sockaddr_in) */
    1402               0 :                 size = php_sockaddr_size(&ftp->pasvaddr);
    1403               0 :                 tv.tv_sec = ftp->timeout_sec;
    1404               0 :                 tv.tv_usec = 0;
    1405               0 :                 if (php_connect_nonb(fd, (struct sockaddr*) &ftp->pasvaddr, size, &tv) == -1) {
    1406               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_connect_nonb() failed: %s (%d)", strerror(errno), errno);
    1407               0 :                         goto bail;
    1408                 :                 }
    1409                 : 
    1410               0 :                 data->fd = fd;
    1411                 : 
    1412               0 :                 ftp->data = data;
    1413               0 :                 return data;
    1414                 :         }
    1415                 : 
    1416                 : 
    1417                 :         /* active (normal) connection */
    1418                 : 
    1419                 :         /* bind to a local address */
    1420              21 :         php_any_addr(sa->sa_family, &addr, 0);
    1421              21 :         size = php_sockaddr_size(&addr);
    1422                 : 
    1423              21 :         if (bind(fd, (struct sockaddr*) &addr, size) != 0) {
    1424               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "bind() failed: %s (%d)", strerror(errno), errno);
    1425               0 :                 goto bail;
    1426                 :         }
    1427                 : 
    1428              21 :         if (getsockname(fd, (struct sockaddr*) &addr, &size) != 0) {
    1429               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "getsockname() failed: %s (%d)", strerror(errno), errno);
    1430               0 :                 goto bail;
    1431                 :         }
    1432                 : 
    1433              21 :         if (listen(fd, 5) != 0) {
    1434               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "listen() failed: %s (%d)", strerror(errno), errno);
    1435               0 :                 goto bail;
    1436                 :         }
    1437                 : 
    1438              21 :         data->listener = fd;
    1439                 : 
    1440                 : #if HAVE_IPV6
    1441              21 :         if (sa->sa_family == AF_INET6) {
    1442                 :                 /* need to use EPRT */
    1443                 :                 char eprtarg[INET6_ADDRSTRLEN + sizeof("|x||xxxxx|")];
    1444                 :                 char out[INET6_ADDRSTRLEN];
    1445               0 :                 inet_ntop(AF_INET6, &((struct sockaddr_in6*) sa)->sin6_addr, out, sizeof(out));
    1446               0 :                 snprintf(eprtarg, sizeof(eprtarg), "|2|%s|%hu|", out, ntohs(((struct sockaddr_in6 *) &addr)->sin6_port));
    1447                 : 
    1448               0 :                 if (!ftp_putcmd(ftp, "EPRT", eprtarg)) {
    1449               0 :                         goto bail;
    1450                 :                 }
    1451                 : 
    1452               0 :                 if (!ftp_getresp(ftp) || ftp->resp != 200) {
    1453                 :                         goto bail;
    1454                 :                 }
    1455                 : 
    1456               0 :                 ftp->data = data;
    1457               0 :                 return data;
    1458                 :         }
    1459                 : #endif
    1460                 : 
    1461                 :         /* send the PORT */
    1462              21 :         ipbox.ia[0] = ((struct sockaddr_in*) sa)->sin_addr;
    1463              21 :         ipbox.s[2] = ((struct sockaddr_in*) &addr)->sin_port;
    1464              21 :         snprintf(arg, sizeof(arg), "%u,%u,%u,%u,%u,%u", ipbox.c[0], ipbox.c[1], ipbox.c[2], ipbox.c[3], ipbox.c[4], ipbox.c[5]);
    1465                 : 
    1466              21 :         if (!ftp_putcmd(ftp, "PORT", arg)) {
    1467               0 :                 goto bail;
    1468                 :         }
    1469              21 :         if (!ftp_getresp(ftp) || ftp->resp != 200) {
    1470                 :                 goto bail;
    1471                 :         }
    1472                 : 
    1473              21 :         ftp->data = data;
    1474              21 :         return data;
    1475                 : 
    1476               0 : bail:
    1477               0 :         if (fd != -1) {
    1478               0 :                 closesocket(fd);
    1479                 :         }
    1480               0 :         efree(data);
    1481               0 :         return NULL;
    1482                 : }
    1483                 : /* }}} */
    1484                 : 
    1485                 : /* {{{ data_accept
    1486                 :  */
    1487                 : databuf_t*
    1488                 : data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC)
    1489              15 : {
    1490                 :         php_sockaddr_storage addr;
    1491                 :         socklen_t                       size;
    1492                 : 
    1493                 : #if HAVE_OPENSSL_EXT
    1494                 :         SSL_CTX         *ctx;
    1495                 : #endif
    1496                 : 
    1497              15 :         if (data->fd != -1) {
    1498               0 :                 goto data_accepted;
    1499                 :         }
    1500              15 :         size = sizeof(addr);
    1501              15 :         data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size);
    1502              15 :         closesocket(data->listener);
    1503              15 :         data->listener = -1;
    1504                 : 
    1505              15 :         if (data->fd == -1) {
    1506               0 :                 efree(data);
    1507               0 :                 return NULL;
    1508                 :         }
    1509                 : 
    1510              15 : data_accepted:
    1511                 : #if HAVE_OPENSSL_EXT
    1512                 :         
    1513                 :         /* now enable ssl if we need to */
    1514              15 :         if (ftp->use_ssl && ftp->use_ssl_for_data) {
    1515               0 :                 ctx = SSL_CTX_new(SSLv23_client_method());
    1516               0 :                 if (ctx == NULL) {
    1517               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to create the SSL context");
    1518               0 :                         return 0;
    1519                 :                 }
    1520                 : 
    1521               0 :                 SSL_CTX_set_options(ctx, SSL_OP_ALL);
    1522                 : 
    1523               0 :                 data->ssl_handle = SSL_new(ctx);
    1524               0 :                 if (data->ssl_handle == NULL) {
    1525               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to create the SSL handle");
    1526               0 :                         SSL_CTX_free(ctx);
    1527               0 :                         return 0;
    1528                 :                 }
    1529                 :                         
    1530                 :                 
    1531               0 :                 SSL_set_fd(data->ssl_handle, data->fd);
    1532                 : 
    1533               0 :                 if (ftp->old_ssl) {
    1534               0 :                         SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle);
    1535                 :                 }
    1536                 :                         
    1537               0 :                 if (SSL_connect(data->ssl_handle) <= 0) {
    1538               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: SSL/TLS handshake failed");
    1539               0 :                         SSL_shutdown(data->ssl_handle);
    1540               0 :                         return 0;
    1541                 :                 }
    1542                 :                         
    1543               0 :                 data->ssl_active = 1;
    1544                 :         }       
    1545                 : 
    1546                 : #endif
    1547                 : 
    1548              15 :         return data;
    1549                 : }
    1550                 : /* }}} */
    1551                 : 
    1552                 : /* {{{ data_close
    1553                 :  */
    1554                 : databuf_t*
    1555                 : data_close(ftpbuf_t *ftp, databuf_t *data)
    1556              21 : {
    1557              21 :         if (data == NULL) {
    1558               0 :                 return NULL;
    1559                 :         }
    1560              21 :         if (data->listener != -1) {
    1561                 : #if HAVE_OPENSSL_EXT
    1562               6 :                 if (data->ssl_active) {
    1563               0 :                         SSL_shutdown(data->ssl_handle);
    1564               0 :                         data->ssl_active = 0;
    1565                 :                 }
    1566                 : #endif                          
    1567               6 :                 closesocket(data->listener);
    1568                 :         }       
    1569              21 :         if (data->fd != -1) {
    1570                 : #if HAVE_OPENSSL_EXT
    1571              15 :                 if (data->ssl_active) {
    1572               0 :                         SSL_shutdown(data->ssl_handle);
    1573               0 :                         data->ssl_active = 0;
    1574                 :                 }
    1575                 : #endif                          
    1576              15 :                 closesocket(data->fd);
    1577                 :         }       
    1578              21 :         if (ftp) {
    1579              21 :                 ftp->data = NULL;
    1580                 :         }
    1581              21 :         efree(data);
    1582              21 :         return NULL;
    1583                 : }
    1584                 : /* }}} */
    1585                 : 
    1586                 : /* {{{ ftp_genlist
    1587                 :  */
    1588                 : char**
    1589                 : ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC)
    1590               7 : {
    1591               7 :         php_stream      *tmpstream = NULL;
    1592               7 :         databuf_t       *data = NULL;
    1593                 :         char            *ptr;
    1594                 :         int             ch, lastch;
    1595                 :         int             size, rcvd;
    1596                 :         int             lines;
    1597               7 :         char            **ret = NULL;
    1598                 :         char            **entry;
    1599                 :         char            *text;
    1600                 : 
    1601                 : 
    1602               7 :         if ((tmpstream = php_stream_fopen_tmpfile()) == NULL) {
    1603               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create temporary file.  Check permissions in temporary files directory.");
    1604               0 :                 return NULL;
    1605                 :         }
    1606                 : 
    1607               7 :         if (!ftp_type(ftp, FTPTYPE_ASCII)) {
    1608               0 :                 goto bail;
    1609                 :         }
    1610                 : 
    1611               7 :         if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
    1612               0 :                 goto bail;
    1613                 :         }
    1614               7 :         ftp->data = data;    
    1615                 : 
    1616               7 :         if (!ftp_putcmd(ftp, cmd, path)) {
    1617               0 :                 goto bail;
    1618                 :         }
    1619               7 :         if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125 && ftp->resp != 226)) {
    1620                 :                 goto bail;
    1621                 :         }
    1622                 : 
    1623                 :         /* some servers don't open a ftp-data connection if the directory is empty */
    1624               4 :         if (ftp->resp == 226) {
    1625               1 :                 ftp->data = data_close(ftp, data);
    1626               1 :                 php_stream_close(tmpstream);
    1627               1 :                 return ecalloc(1, sizeof(char**));
    1628                 :         }
    1629                 : 
    1630                 :         /* pull data buffer into tmpfile */
    1631               3 :         if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
    1632               0 :                 goto bail;
    1633                 :         }
    1634               3 :         size = 0;
    1635               3 :         lines = 0;
    1636               3 :         lastch = 0;
    1637               8 :         while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
    1638               2 :                 if (rcvd == -1) {
    1639               0 :                         goto bail;
    1640                 :                 }
    1641                 : 
    1642               2 :                 php_stream_write(tmpstream, data->buf, rcvd);
    1643                 : 
    1644               2 :                 size += rcvd;
    1645              52 :                 for (ptr = data->buf; rcvd; rcvd--, ptr++) {
    1646              56 :                         if (*ptr == '\n' && lastch == '\r') {
    1647               6 :                                 lines++;
    1648                 :                         } else {
    1649              44 :                                 size++;
    1650                 :                         }
    1651              50 :                         lastch = *ptr;
    1652                 :                 }
    1653                 :         }
    1654                 : 
    1655               3 :         ftp->data = data = data_close(ftp, data);
    1656                 : 
    1657               3 :         php_stream_rewind(tmpstream);
    1658                 : 
    1659               3 :         ret = safe_emalloc((lines + 1), sizeof(char**), size * sizeof(char*));
    1660                 : 
    1661               3 :         entry = ret;
    1662               3 :         text = (char*) (ret + lines + 1);
    1663               3 :         *entry = text;
    1664               3 :         lastch = 0;
    1665              56 :         while ((ch = php_stream_getc(tmpstream)) != EOF) {
    1666              56 :                 if (ch == '\n' && lastch == '\r') {
    1667               6 :                         *(text - 1) = 0;
    1668               6 :                         *++entry = text;
    1669                 :                 } else {
    1670              44 :                         *text++ = ch;
    1671                 :                 }
    1672              50 :                 lastch = ch;
    1673                 :         }
    1674               3 :         *entry = NULL;
    1675                 : 
    1676               3 :         php_stream_close(tmpstream);
    1677                 : 
    1678               3 :         if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
    1679               0 :                 efree(ret);
    1680               0 :                 return NULL;
    1681                 :         }
    1682                 : 
    1683               3 :         return ret;
    1684               3 : bail:
    1685               3 :         ftp->data = data_close(ftp, data);
    1686               3 :         php_stream_close(tmpstream);
    1687               3 :         if (ret)
    1688               0 :                 efree(ret);
    1689               3 :         return NULL;
    1690                 : }
    1691                 : /* }}} */
    1692                 : 
    1693                 : /* {{{ ftp_nb_get
    1694                 :  */
    1695                 : int
    1696                 : ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC)
    1697               3 : {
    1698               3 :         databuf_t               *data = NULL;
    1699                 :         char                    arg[11];
    1700                 : 
    1701               3 :         if (ftp == NULL) {
    1702               0 :                 goto bail;
    1703                 :         }
    1704                 : 
    1705               3 :         if (!ftp_type(ftp, type)) {
    1706               0 :                 goto bail;
    1707                 :         }
    1708                 : 
    1709               3 :         if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
    1710               0 :                 goto bail;
    1711                 :         }
    1712                 : 
    1713               3 :         if (resumepos>0) {
    1714                 :                 /* We are working on an architecture that supports 64-bit integers
    1715                 :                  * since php is 32 bit by design, we bail out with warning
    1716                 :                  */
    1717                 :                 if (resumepos > 2147483647) {
    1718                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483648 bytes.");
    1719                 :                         goto bail;
    1720                 :                 }
    1721               2 :                 snprintf(arg, sizeof(arg), "%u", resumepos);
    1722               2 :                 if (!ftp_putcmd(ftp, "REST", arg)) {
    1723               0 :                         goto bail;
    1724                 :                 }
    1725               2 :                 if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
    1726                 :                         goto bail;
    1727                 :                 }
    1728                 :         }
    1729                 : 
    1730               3 :         if (!ftp_putcmd(ftp, "RETR", path)) {
    1731               0 :                 goto bail;
    1732                 :         }
    1733               3 :         if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
    1734                 :                 goto bail;
    1735                 :         }
    1736                 : 
    1737               3 :         if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) {
    1738               0 :                 goto bail;
    1739                 :         }
    1740                 : 
    1741               3 :         ftp->data = data;
    1742               3 :         ftp->stream = outstream;
    1743               3 :         ftp->lastch = 0;
    1744               3 :         ftp->nb = 1;
    1745                 : 
    1746               3 :         return (ftp_nb_continue_read(ftp TSRMLS_CC));
    1747                 : 
    1748               0 : bail:
    1749               0 :         ftp->data = data_close(ftp, data);
    1750               0 :         return PHP_FTP_FAILED;
    1751                 : }
    1752                 : /* }}} */
    1753                 : 
    1754                 : /* {{{ ftp_nb_continue_read
    1755                 :  */
    1756                 : int
    1757                 : ftp_nb_continue_read(ftpbuf_t *ftp TSRMLS_DC)
    1758               3 : {
    1759               3 :         databuf_t       *data = NULL;
    1760                 :         char            *ptr;
    1761                 :         int             lastch;
    1762                 :         size_t          rcvd;
    1763                 :         ftptype_t       type;
    1764                 : 
    1765               3 :         data = ftp->data;
    1766                 : 
    1767                 :         /* check if there is already more data */
    1768               3 :         if (!data_available(ftp, data->fd)) {
    1769               0 :                 return PHP_FTP_MOREDATA;
    1770                 :         }
    1771                 : 
    1772               3 :         type = ftp->type;
    1773                 : 
    1774               3 :         lastch = ftp->lastch;
    1775               3 :         if ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
    1776               3 :                 if (rcvd == -1) {
    1777               0 :                         goto bail;
    1778                 :                 }
    1779                 : 
    1780               3 :                 if (type == FTPTYPE_ASCII) {
    1781              26 :                         for (ptr = data->buf; rcvd; rcvd--, ptr++) {
    1782              23 :                                 if (lastch == '\r' && *ptr != '\n') {
    1783               0 :                                         php_stream_putc(ftp->stream, '\r');
    1784                 :                                 }
    1785              23 :                                 if (*ptr != '\r') {
    1786              20 :                                         php_stream_putc(ftp->stream, *ptr);
    1787                 :                                 }
    1788              23 :                                 lastch = *ptr;
    1789                 :                         }
    1790               0 :                 } else if (rcvd != php_stream_write(ftp->stream, data->buf, rcvd)) {
    1791               0 :                         goto bail;
    1792                 :                 }
    1793                 : 
    1794               3 :                 ftp->lastch = lastch;
    1795               3 :                 return PHP_FTP_MOREDATA;
    1796                 :         }
    1797                 : 
    1798               0 :         if (type == FTPTYPE_ASCII && lastch == '\r') {
    1799               0 :                 php_stream_putc(ftp->stream, '\r');
    1800                 :         }
    1801                 : 
    1802               0 :         ftp->data = data = data_close(ftp, data);
    1803                 : 
    1804               0 :         if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
    1805                 :                 goto bail;
    1806                 :         }
    1807                 : 
    1808               0 :         ftp->nb = 0;
    1809               0 :         return PHP_FTP_FINISHED;
    1810               0 : bail:
    1811               0 :         ftp->nb = 0;
    1812               0 :         ftp->data = data_close(ftp, data);
    1813               0 :         return PHP_FTP_FAILED;
    1814                 : }
    1815                 : /* }}} */
    1816                 : 
    1817                 : /* {{{ ftp_nb_put
    1818                 :  */
    1819                 : int
    1820                 : ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC)
    1821               0 : {
    1822               0 :         databuf_t               *data = NULL;
    1823                 :         char                    arg[11];
    1824                 : 
    1825               0 :         if (ftp == NULL) {
    1826               0 :                 return 0;
    1827                 :         }
    1828               0 :         if (!ftp_type(ftp, type)) {
    1829               0 :                 goto bail;
    1830                 :         }
    1831               0 :         if ((data = ftp_getdata(ftp TSRMLS_CC)) == NULL) {
    1832               0 :                 goto bail;
    1833                 :         }
    1834               0 :         if (startpos > 0) {
    1835                 :                 if (startpos > 2147483647) {
    1836                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes.");
    1837                 :                         goto bail;
    1838                 :                 }
    1839               0 :                 snprintf(arg, sizeof(arg), "%u", startpos);
    1840               0 :                 if (!ftp_putcmd(ftp, "REST", arg)) {
    1841               0 :                         goto bail;
    1842                 :                 }
    1843               0 :                 if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
    1844                 :                         goto bail;
    1845                 :                 }
    1846                 :         }
    1847                 : 
    1848               0 :         if (!ftp_putcmd(ftp, "STOR", path)) {
    1849               0 :                 goto bail;
    1850                 :         }
    1851               0 :         if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
    1852                 :                 goto bail;
    1853                 :         }
    1854               0 :         if ((data = data_accept(data, ftp TSRMLS_CC)) == NULL) { 
    1855               0 :                 goto bail;
    1856                 :         }
    1857               0 :         ftp->data = data;
    1858               0 :         ftp->stream = instream;
    1859               0 :         ftp->lastch = 0;
    1860               0 :         ftp->nb = 1;
    1861                 : 
    1862               0 :         return (ftp_nb_continue_write(ftp TSRMLS_CC));
    1863                 : 
    1864               0 : bail:
    1865               0 :         ftp->data = data_close(ftp, data);
    1866               0 :         return PHP_FTP_FAILED;
    1867                 : }
    1868                 : /* }}} */
    1869                 : 
    1870                 : 
    1871                 : /* {{{ ftp_nb_continue_write
    1872                 :  */
    1873                 : int
    1874                 : ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC)
    1875               0 : {
    1876                 :         int                     size;
    1877                 :         char                    *ptr;
    1878                 :         int                     ch;
    1879                 : 
    1880                 :         /* check if we can write more data */
    1881               0 :         if (!data_writeable(ftp, ftp->data->fd)) {
    1882               0 :                 return PHP_FTP_MOREDATA;
    1883                 :         }
    1884                 : 
    1885               0 :         size = 0;
    1886               0 :         ptr = ftp->data->buf;
    1887               0 :         while (!php_stream_eof(ftp->stream) && (ch = php_stream_getc(ftp->stream)) != EOF) {
    1888                 : 
    1889               0 :                 if (ch == '\n' && ftp->type == FTPTYPE_ASCII) {
    1890               0 :                         *ptr++ = '\r';
    1891               0 :                         size++;
    1892                 :                 }
    1893                 : 
    1894               0 :                 *ptr++ = ch;
    1895               0 :                 size++;
    1896                 : 
    1897                 :                 /* flush if necessary */
    1898               0 :                 if (FTP_BUFSIZE - size < 2) {
    1899               0 :                         if (my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size) {
    1900               0 :                                 goto bail;
    1901                 :                         }
    1902               0 :                         return PHP_FTP_MOREDATA;
    1903                 :                 }
    1904                 :         }
    1905                 : 
    1906               0 :         if (size && my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size) {
    1907               0 :                 goto bail;
    1908                 :         }
    1909               0 :         ftp->data = data_close(ftp, ftp->data);
    1910                 :  
    1911               0 :         if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
    1912                 :                 goto bail;
    1913                 :         }
    1914               0 :         ftp->nb = 0;
    1915               0 :         return PHP_FTP_FINISHED;
    1916               0 : bail:
    1917               0 :         ftp->data = data_close(ftp, ftp->data);
    1918               0 :         ftp->nb = 0;
    1919               0 :         return PHP_FTP_FAILED;
    1920                 : }
    1921                 : /* }}} */
    1922                 : 
    1923                 : #endif /* HAVE_FTP */
    1924                 : 
    1925                 : /*
    1926                 :  * Local variables:
    1927                 :  * tab-width: 4
    1928                 :  * c-basic-offset: 4
    1929                 :  * End:
    1930                 :  * vim600: sw=4 ts=4 fdm=marker
    1931                 :  * vim<600: sw=4 ts=4
    1932                 :  */

Generated by: LTP GCOV extension version 1.5

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

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