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-23 Instrumented lines: 837
Code covered: 34.3 % Executed lines: 287
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

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

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