php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #52766 FTP need the ability to read from the output buffer without issuing a command
Submitted: 2010-09-02 18:05 UTC Modified: 2011-11-01 21:09 UTC
Votes:4
Avg. Score:3.8 ± 1.6
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: trevor dot lanyon at lanyonconsulting dot com Assigned: rasmus (profile)
Status: Closed Package: FTP related
PHP Version: 5.3.3 OS: Fedora 13
Private report: No CVE-ID: None
 [2010-09-02 18:05 UTC] trevor dot lanyon at lanyonconsulting dot com
Description:
------------
Working with ftp_raw there is a need for a function that allows interaction with 
the output buffer of the connection.  There are times when issuing commands 
leaves messages on the buffer thereby causing future commands to be out of sync 
with the output and no way to synchronize them.  Below is an example:

Using HylaFax's proprietary ftp interface I required the ability to issue a 
'STOT' command.

I issued a 'PASV' command to get the appropriate port to open a second 
connection to.  I open a second connection,  write a file, then close it.
The original connection now has a line on the output buffer similar to this:

226 Transfer complete (FILE: /tmp/doc94274.tmp)

But there is no way to grab this.

Issuing any command will return the buffered line.  Subsequent commands will 
return the output of the previous command.

For example if I now issue a 'NOOP' I will now get the:

226 Transfer complete (FILE: /tmp/doc94274.tmp).

and If I issue a second 'NOOP' I will get the response from the orginal 'NOOP':

200 NOOP command successful

With the second Noop now sitting on the out buffer of the ftp connection.

Test script:
---------------
<?php

/**
*  This example will require the use of a HylaFax Server with the -i option
*  enabled.
*/

    $fileName = '/foo/test.pdf';
    $hylaFaxServer = 'localhost';
    $user = 'Mr. Peters';






    function getResultCode( $resultString )
    {
        $resultCode = false;
    	if( strpos($resultString, ' ') > 2) {
    		$resultCode = substr($resultString, 0, strpos($resultString, ' ' ) );
            return $resultCode;
    	}
        return $resultCode;
    }

    function getResultToString( $resultArray, $glue = "\n" ) 
    {
        if ( is_array( $resultArray ) ) {
            return implode($resultArray, $glue );
        	
        }
        return false;
    }
    
    function sendFile( $localFileName, $connection, $hostName ) 
    {
        
        //Enter PASV mode
        if($results = getResultToString( ftp_raw($connection, 'PASV') )) {
            
            //Make sure we got the appropriate 227 back
            if(getResultCode( $results ) == 227) {
                
                //Grab the ip and ports out of the response                
                $ports = substr($results, strpos($results, '(')+1 ) ;
                
                //get rid of the extra ')' as the end
                $ports = substr($ports, 0, strlen($ports) - 1);
                
                //make an array of the results using the ',' as the seporator
                $ports = explode(",", $ports);
                
                //grab the last octet
                $lastOctet = array_pop($ports);
                
                //grab the first octet
                $firstOctet = array_pop($ports);
                
                //deduce the appropriate port to connect back to
                $port = $firstOctet * 256 + $lastOctet;
                
                //create a connection to listen on 
                if( $passiveSocket = fsockopen( $hostName, $port) ) {
                    
                    //Tell the ftp server to make a connection
                    if($results = getResultToString(ftp_raw( $connection, 'STOT' ) ) ) {
                        
                        //make sure the connection was successful
                        if(getResultCode($results) == 150) {
                            
                            //Write the file over the new socket
                            if( fwrite( $passiveSocket, $localFileName ) ) {
                                
                                //Close the socket
                                if(fclose( $passiveSocket ) ) {
                                    
                                    
                                    $results = getResultToString( ftp_raw( $connection, 'STAT' ) );
                                    echo "Results of stat:\n";
                                    echo $results;
                                    echo "Results of Noop:\n";
                                    $results = getResultToString( ftp_raw( $connection, 'noop' ) );
                                    echo $results;
        
                                } // socket closure
                            }  //file writing
                        } //result of STOT command to first socket
                    } else {  //issue the STOT Command to first socket
                        echo 'Unexpected result from STOR: ';
                        var_dump( $results )."\n";
                    }
                }  //Attempt to open second socket on local machine
            } else {  //Unexpected resultcode from pasv command 
            	echo 'Unexpected result code from passive mode: '.getResultCode ($results );
            } // review result code from PASV command
            return true;
        }  //Attempt to send PASV command to connection
        return false;
      
    }
    

  function output(&$item, $key) {

      echo $item."\n";
  }

    $connection = ftp_connect($hylaFaxServer , '4559');
    
    array_walk( ftp_raw($connection, 'USER '.$user), 'output' );
    array_walk( ftp_raw($connection, 'FORM PDF'), 'output' );
    array_walk( ftp_raw($connection, 'TYPE I'), 'output' );

    $uploadedFileName = sendFile($fileName, $connection, $hylaFaxServer);
    
    array_walk( ftp_raw($connection, 'JNEW'), 'output' );
    

    array_walk( ftp_raw($connection, 'JPARM FROMUSER "'.$user.'"'), 'output' );
    
    array_walk( ftp_raw($connection, 'JPARM LASTTIME 000259'), 'output' );
    
    array_walk( ftp_raw($connection, 'JPARM MAXDIALS 12'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM MAXTRIES 3'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM SCHEDPRI 127'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM DIALSTRING "3340746"'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM NOTIFYADDR "root@localhost.com"'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM VRES 196'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM PAGEWIDTH 215'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM PAGELENGTH 279'), 'output' );
    
    array_walk( ftp_raw($connection, 'JPARM NOTIFY "none"'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM PAGECHOP "none"'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM CHOPTHRESHOLD 3'), 'output' );
    array_walk( ftp_raw($connection, 'JPARM DOCUMENT '.$uploadedFileName ), 'output' );
    array_walk( ftp_raw($connection, 'JSUBM'), 'output' );
    

    ftp_close($connection);

?>

Expected result:
----------------
230 User Mr. Peters logged in.
200 Format set to PDF.
200 Type set to Image.
226 Transfer complete (FILE: /tmp/doc96.pdf).
Results of stat:
211-samadams.northrock.local HylaFAX server status:
    HylaFAX (tm) Version 5.4.2
    Connected to localhost.localdomain (127.0.0.1)
    Logged in as user Mr. Peters (uid 60002)
    "/" is the current directory
    Current job: (default)
    Time values are handled in GMT
    Idle timeout set to 900 seconds
    Using long replies
    No server down time currently scheduled
    HylaFAX scheduler reached at /FIFO (not connected)
    Server FIFO is /client/26610 (open)
    File cache: 17 lookups, 1 hits (5.9%), 1.1 avg probes
        16 entries (2.9 KB), 0 entries displaced, 0 entries flushed
    TYPE: Image; STRU: File; MODE: Stream; FORM: PDF
    No client data connection
211 End of status
Results of Noop:
200 NOOP command successful.
200 New job created: jobid: 73 groupid: 73.
213 FROMUSER set to "Mr. Peters".
213 LASTTIME set to 000259.
213 MAXDIALS set to 12.
213 MAXTRIES set to 3.
213 SCHEDPRI set to 127.
213 DIALSTRING set to "3340746".
213 NOTIFYADDR set to "root@localhost.com".
213 VRES set to 196.
213 PAGEWIDTH set to 215.
213 PAGELENGTH set to 279.
213 NOTIFY set to "none".
213 PAGECHOP set to "none".
213 CHOPTHRESHOLD set to 3.
550 1: No such file or directory.

Actual result:
--------------
230 User Mr. Peters logged in.
200 Format set to PDF.
200 Type set to Image.
Results of stat:
226 Transfer complete (FILE: /tmp/doc96.pdf).Results of Noop:
211-samadams.northrock.local HylaFAX server status:
    HylaFAX (tm) Version 5.4.2
    Connected to localhost.localdomain (127.0.0.1)
    Logged in as user Mr. Peters (uid 60002)
    "/" is the current directory
    Current job: (default)
    Time values are handled in GMT
    Idle timeout set to 900 seconds
    Using long replies
    No server down time currently scheduled
    HylaFAX scheduler reached at /FIFO (not connected)
    Server FIFO is /client/26610 (open)
    File cache: 17 lookups, 1 hits (5.9%), 1.1 avg probes
        16 entries (2.9 KB), 0 entries displaced, 0 entries flushed
    TYPE: Image; STRU: File; MODE: Stream; FORM: PDF
    No client data connection
211 End of status200 NOOP command successful.
200 New job created: jobid: 73 groupid: 73.
213 FROMUSER set to "Mr. Peters".
213 LASTTIME set to 000259.
213 MAXDIALS set to 12.
213 MAXTRIES set to 3.
213 SCHEDPRI set to 127.
213 DIALSTRING set to "3340746".
213 NOTIFYADDR set to "root@localhost.com".
213 VRES set to 196.
213 PAGEWIDTH set to 215.
213 PAGELENGTH set to 279.
213 NOTIFY set to "none".
213 PAGECHOP set to "none".
213 CHOPTHRESHOLD set to 3.
550 1: No such file or directory.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-09-13 20:50 UTC] 92spam92 at gmail dot com
hi, i have the same problem.
PHP 5.3.8
CentOS 6.

the only solution is to close the ftp connection and re-open it.
 [2011-11-01 17:57 UTC] bram at ebskamp dot me
This is caused by the bug I posted about yesterday:
https://bugs.php.net/bug.php?id=60183

(has been fixed in SVN today)
 [2011-11-01 21:09 UTC] rasmus@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: rasmus
 [2011-11-01 21:09 UTC] rasmus@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2012-11-16 20:36 UTC] bar at root dot co dot il
Hi,
seems that in PHP 5.3.19 this bug is still exists.
 [2013-04-11 13:31 UTC] e dot honda at coussi-net dot com
Issuing an empty command as ftp_raw($connection, '') to grab the response in the 
buffer.

It works like:

1) ftp_raw($connection, 'STOR');
   -> It returns "150 OK to send data".

2) ftp_raw($connection, '');
   -> It returns "226 Transfer complete".

3) ftp_raw($connection, 'NOOP');
   -> It returns "200 NOOP ok"

According to the server side log, the command '' is just ignored.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Dec 06 21:01:27 2024 UTC