php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #17347 fopen ftp wrapper gets wrong path
Submitted: 2002-05-21 21:00 UTC Modified: 2002-09-11 11:10 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: jamie dot anstice at sli-systems dot com Assigned:
Status: No Feedback Package: FTP related
PHP Version: 4.2.1 OS: Redhat 6.2
Private report: No CVE-ID: None
 [2002-05-21 21:00 UTC] jamie dot anstice at sli-systems dot com
The fopen ftp wrapper tries to look for files starting at the root of the file system, rather than the applicable ftp base directory.  RFC 1738 gives the specifics of how FTP URLS are to be interpreted - each segment of the path should be treated as a separate CWD command. RFC 1738 says that the slash separating the ftp server name from the path is not part of the path, and slashes included in the path should be encoded (so to ftp the file /etc/motd the url <ftp://myname@host.dom/%2Fetc/motd> should be used, which would correspond to CWD /etc ; RETR motd - wheras the url <ftp://myname@host.dom/etc/motd> corresponds to something like CWD etc; RETR motd - which would fetch the motd file from the user's etc directory).

RFC 2396 now rules that the slash following the server name is part of the path, but it's wrong to interpret this as meaning that the path requested is based on the file system root - in HTML the initial slash indicates that the path is absolute not relative, and it makes sense to continue to interpret FTP urls in the same manner, especially as there is a mechanism to address files outside the ftp file area.

There are a couple of implementation issues for resolving this problem - compatibility to previous behaviour and the method of getting to the destination directory.
Compatibility could be addressed by including a ftp_path_bug_behaviour variable, or preferably just fixing the behaviour and documenting the change in big letters.  
The issue of getting to the destination directory is probably only of interest to nit-pickers, but here it is.  It's not outside the bounds of possibility that an ftp server might perform magic when CWD'ing to a directory, so it might be preferable to get to the destination of the path by a series of CWD's.  However, it's also possible that the directory structure is set up with unaccessable directories between the start of the path and the end, so a one-hit grab might be in order. Both concerns could be accomodated by first attempting a series of CWD's to get to the destination directory, and if these are unsuccessful then attempt a one-hit command before giving up.  However, I suspect that the one-hit version would work for almost all users, and those users which need something else can use the FTP module

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-05-22 03:09 UTC] sander@php.net
Reclassified.
 [2002-05-22 18:18 UTC] jamie dot anstice at sli-systems dot com
Why complain when I can patch - how does this look? It's a one-hit version with no bug-compatibility, but it works in both test cases I've tried

==================================
--- php-4.2.1/ext/standard/ftp_fopen_wrapper.c	Thu Feb 28 21:26:45 2002
+++ patch-php-4.2.1/ext/standard/ftp_fopen_wrapper.c	Thu May 23 09:57:22 2002
@@ -89,6 +89,8 @@
 	int result;
 	int i;
 	char *tpath, *ttpath;
+    char *decoded_server_path = NULL;
+
 	
 	resource = php_url_parse((char *) path);
 	if (resource == NULL) {
@@ -101,6 +103,22 @@
 		*issock = BAD_URL;
 		return NULL;
 	}
+
+    /* remove leading slash if present */
+    if ( resource->path[0] == '/' && strlen( resource->path ) > 1) 
+        decoded_server_path = estrdup( resource->path+1 );
+    else
+        decoded_server_path = estrdup( resource->path );
+    
+    if ( decoded_server_path == NULL ) {
+        php_error( E_ERROR, "Memory Allocation error in ftp fopen wrapper" );
+        php_url_free( resource );
+        *issock = BAD_URL;
+        return NULL;
+    }
+        
+    php_url_decode( decoded_server_path, strlen( decoded_server_path) );
+    
 	/* use port 21 if one wasn't specified */
 	if (resource->port == 0)
 		resource->port = 21;
@@ -171,7 +189,7 @@
 	
 	/* find out the size of the file (verifying it exists) */
 	SOCK_WRITE("SIZE ", *socketd);
-	SOCK_WRITE(resource->path, *socketd);
+	SOCK_WRITE( decoded_server_path , *socketd);
 	SOCK_WRITE("\r\n", *socketd);
 	
 	/* read the response */
@@ -268,8 +286,8 @@
 		/* store file */
 		SOCK_WRITE("STOR ", *socketd);
 	} 
-	if (resource->path != NULL) {
-		SOCK_WRITE(resource->path, *socketd);
+	if (decoded_server_path != NULL) {
+		SOCK_WRITE(decoded_server_path, *socketd);
 	} else {
 		SOCK_WRITE("/", *socketd);
 	}

==================================

==ftp_test.php===
<?php

  $user = "xxx";
  $pass = "yyy";
  $server = "zzz";
  $url = "ftp://$user:$pass@$server/ftp/test.txt";
  $fh = fopen( $url, "r" );
  if ($fh ) {
    $l = fgets( $fh );
    print $l;
    fclose( $fh );
  }

  $url = "ftp://$user:$pass@$server/%2Fetc/wgetrc";
  $fh = fopen( $url, "r" );
  if ($fh ) {
    $l = fgets( $fh );
    print $l;
    fclose( $fh );
  }
?>
=================
 [2002-05-22 19:05 UTC] jamie dot anstice at sli-systems dot com
Of course a polite person would free decoded_server_path too.
 [2002-06-18 04:02 UTC] derick@php.net
Changing this like you proposed will break backward compability. DO you have another idea how to address this issue?

Derick
 [2002-09-11 11:10 UTC] sniper@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 15:01:28 2024 UTC