From:             fcartegnie at nordnet dot fr
Operating system: Linux
PHP version:      4.4.0
PHP Bug Type:     FTP related
Bug description:  FTP Fopen Wrappers doesn't work work with every server

Description:
------------
I was stuck with a fopen("ftp://...
resulting in a 
"failed to open stream: FTP server reports 220 Serv-U FTP Server v6.0 for
WinSock ready..."
This URL was working with any other software (WGET, CURL).

After analysing and tracing the code, I found the reason:  This ftpserver
(or maybe firewall) expects only full line commands. The FTP_fopen_wrapper
outputs commands while generating then. TCPdumping the flow shows the php
client
sends "USER " in a single packet, then the remaining of the command.
Thoses servers answers after the packet, and php read a wrong command
result so.




Reproduce code:
---------------
I can give privately IP/login/pass for reproducing.

Expected result:
----------------
Commands in a single line/packet.
Patch follows.

Actual result:
--------------
--- php-4.4.0/ext/standard/ftp_fopen_wrapper.c  2005-06-27
10:27:23.000000000 +0200
+++ php-4.4.0_modifie/ext/standard/ftp_fopen_wrapper.c  2005-10-05
16:46:03.000000000 +0200
@@ -139,7 +139,7 @@
        php_url *resource=NULL;
        char tmp_line[512];
        char ip[sizeof("123.123.123.123")];
-       unsigned short portno;
+       unsigned short portno;char *commandbuffer=NULL;
        char *scratch;
        int result;
        int i, use_ssl, tmp_len;
@@ -255,18 +255,19 @@
 }
 
        /* send the user name */
-       php_stream_write_string(stream, "USER ");
        if (resource->user != NULL) {
                unsigned char *s, *e;
                tmp_len = php_raw_url_decode(resource->user, 
strlen(resource->user));
                
                PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
                
-               php_stream_write_string(stream, resource->user);
+               commandbuffer = (char *) malloc((strlen("USER \r\n") +
strlen(resource->user) + 1) * sizeof(char));
+               commandbuffer[0]='\0';  commandbuffer = strcat( strcat(
strcat(commandbuffer,"USER "), resource->user), "\r\n");
+               php_stream_write_string(stream, commandbuffer);
+               free(commandbuffer);
        } else {
-               php_stream_write_string(stream, "anonymous");
+               php_stream_write_string(stream, "USER anonymous\r\n");
        }
-       php_stream_write_string(stream, "\r\n");
        
        /* get the response */
        result = GET_FTP_RESULT(stream);
@@ -275,23 +276,27 @@
        if (result >= 300 && result <= 399) {
                php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED,
tmp_line, 0);
 
-               php_stream_write_string(stream, "PASS ");
                if (resource->pass != NULL) {
                        tmp_len = php_raw_url_decode(resource->pass, 
strlen(resource->pass));
                        
                        PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid 
password %s")
                        
-                       php_stream_write_string(stream, resource->pass);
+                       commandbuffer = (char *) malloc((strlen("PASS \r\n") +
strlen(resource->pass) + 1) * sizeof(char));
+                       commandbuffer[0]='\0'; commandbuffer = strcat( strcat(
strcat(commandbuffer,"PASS "), resource->pass), "\r\n");
+                       php_stream_write_string(stream, commandbuffer);
+                       free(commandbuffer);
                } else {
                        /* if the user has configured who they are,
                           send that as the password */
                        if (cfg_get_string("from", &scratch) == SUCCESS) {
-                               php_stream_write_string(stream, scratch);
+                               commandbuffer = (char *) malloc((strlen("PASS 
\r\n") +
strlen(scratch) + 1) * sizeof(char));
+                               commandbuffer[0]='\0'; commandbuffer = strcat( 
strcat(
strcat(commandbuffer,"PASS "), scratch), "\r\n");
+                               php_stream_write_string(stream, commandbuffer);
+                               free(commandbuffer);
                        } else {
-                               php_stream_write_string(stream, "anonymous");
+                               php_stream_write_string(stream, "PASS 
anonymous\r\n");
                        }
                }
-               php_stream_write_string(stream, "\r\n");
                
                /* read the response */
                result = GET_FTP_RESULT(stream);
@@ -312,9 +317,10 @@
                goto errexit;
        
        /* find out the size of the file (verifying it exists) */
-       php_stream_write_string(stream, "SIZE ");
-       php_stream_write_string(stream, resource->path);
-       php_stream_write_string(stream, "\r\n");
+       commandbuffer = (char *) malloc((strlen("SIZE \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+       commandbuffer[0]='\0'; commandbuffer = strcat( strcat(
strcat(commandbuffer,"SIZE "), resource->path), "\r\n");
+       php_stream_write_string(stream, commandbuffer);
+       free(commandbuffer);
        
        /* read the response */
        result = GET_FTP_RESULT(stream);
@@ -411,17 +417,27 @@
        
        if (mode[0] == 'r') {
                /* retrieve file */
-               php_stream_write_string(stream, "RETR ");
+               if (resource->path == NULL) {
+                       php_stream_write_string(stream, "RETR / \r\n");
+               } else {
+                       commandbuffer = (char *) malloc((strlen("RETR \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+                       commandbuffer[0]='\0'; 
+                       commandbuffer = strcat( strcat( strcat(commandbuffer, 
"RETR "),
resource->path), "\r\n");
+                       php_stream_write_string(stream, commandbuffer);
+                       free(commandbuffer);
+               }
        } else {
                /* store file */
-               php_stream_write_string(stream, "STOR ");
-       } 
-       if (resource->path != NULL) {
-               php_stream_write_string(stream, resource->path);
-       } else {
-               php_stream_write_string(stream, "/");
+               if (resource->path == NULL) {
+                       php_stream_write_string(stream, "STOR / \r\n");
+               } else {
+                       commandbuffer = (char *) malloc((strlen("STOR \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+                       commandbuffer[0]='\0'; 
+                       commandbuffer = strcat( strcat( strcat(commandbuffer, 
"STOR "),
resource->path), "\r\n");
+                       php_stream_write_string(stream, commandbuffer);
+                       free(commandbuffer);
+               }
        }
-       php_stream_write_string(stream, "\r\n");
        
        /* open the data channel */
        if (hoststart == NULL) {


-- 
Edit bug report at http://bugs.php.net/?id=34742&edit=1
-- 
Try a CVS snapshot (php4):   http://bugs.php.net/fix.php?id=34742&r=trysnapshot4
Try a CVS snapshot (php5.0): 
http://bugs.php.net/fix.php?id=34742&r=trysnapshot50
Try a CVS snapshot (php5.1): 
http://bugs.php.net/fix.php?id=34742&r=trysnapshot51
Fixed in CVS:                http://bugs.php.net/fix.php?id=34742&r=fixedcvs
Fixed in release:            http://bugs.php.net/fix.php?id=34742&r=alreadyfixed
Need backtrace:              http://bugs.php.net/fix.php?id=34742&r=needtrace
Need Reproduce Script:       http://bugs.php.net/fix.php?id=34742&r=needscript
Try newer version:           http://bugs.php.net/fix.php?id=34742&r=oldversion
Not developer issue:         http://bugs.php.net/fix.php?id=34742&r=support
Expected behavior:           http://bugs.php.net/fix.php?id=34742&r=notwrong
Not enough info:             
http://bugs.php.net/fix.php?id=34742&r=notenoughinfo
Submitted twice:             
http://bugs.php.net/fix.php?id=34742&r=submittedtwice
register_globals:            http://bugs.php.net/fix.php?id=34742&r=globals
PHP 3 support discontinued:  http://bugs.php.net/fix.php?id=34742&r=php3
Daylight Savings:            http://bugs.php.net/fix.php?id=34742&r=dst
IIS Stability:               http://bugs.php.net/fix.php?id=34742&r=isapi
Install GNU Sed:             http://bugs.php.net/fix.php?id=34742&r=gnused
Floating point limitations:  http://bugs.php.net/fix.php?id=34742&r=float
No Zend Extensions:          http://bugs.php.net/fix.php?id=34742&r=nozend
MySQL Configuration Error:   http://bugs.php.net/fix.php?id=34742&r=mysqlcfg

Reply via email to