ID: 34742 User updated by: fcartegnie at nordnet dot fr Reported By: fcartegnie at nordnet dot fr -Status: Feedback +Status: Open Bug Type: FTP related Operating System: Linux PHP Version: 4.4.0 New Comment:
no luck (php5-200510060830) <b>Warning</b>: fopen(ftp://[EMAIL PROTECTED]:21/info.xml) [<a href='function.fopen'>function.fopen</a>]: failed to open stream: Broken pipe in <b>/tmp/a.php</b> on line <b>3</b><br /> <br /> Previous Comments: ------------------------------------------------------------------------ [2005-10-05 18:27:48] [EMAIL PROTECTED] Please try using this CVS snapshot: http://snaps.php.net/php5-latest.tar.gz For Windows: http://snaps.php.net/win32/php5-win32-latest.zip ------------------------------------------------------------------------ [2005-10-05 17:35:49] fcartegnie at nordnet dot fr I've read your bug #. I guess that this problem is then happening with more than one ftpserver. Minor changes in php would ensure compatibility. Also, splitting commands like 'USER' or 'PASS' in multiple packets does not make really sense. ------------------------------------------------------------------------ [2005-10-05 17:28:02] [EMAIL PROTECTED] I've been already hited by this problem (see bug #30516), but I was connecting to another FTP server. In that time, Konqueror and Mozilla weren't also able to connect to that server, so PHP isn't alone :) ------------------------------------------------------------------------ [2005-10-05 17:01:17] fcartegnie at nordnet dot fr 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 this bug report at http://bugs.php.net/?id=34742&edit=1