php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77581 SFTP with files with # (hash) in name do not work
Submitted: 2019-02-07 22:03 UTC Modified: 2019-02-11 22:16 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: memso at memso dot net Assigned: ramsey (profile)
Status: Verified Package: ssh2 (PECL)
PHP Version: 7.3.2 OS: CentOS 7
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: memso at memso dot net
New email:
PHP Version: OS:

 

 [2019-02-07 22:03 UTC] memso at memso dot net
Description:
------------
Attempting to use the ssh2.sftp stream methods to access files with a hash (#) in the file name always fails.

This seems to occur with all file stream methods. I've tried stat, fopen and is_file, all act like the file does not exist.

Removing the # or changing it to another character fixes the problem, but I do not have control over a remote SFTP I am downloading from and cannot download their files which have a # in the file name.

Test script:
---------------
// Assuming a file named "Some#Test.txt" exists
$ssh2 = ssh2_connect("server", 22);
$sftp = ssh2_sftp($ssh2);
print_r(stat("ssh2.sftp://" . intval($sftp) . "/Some#Test.txt"));

Expected result:
----------------
Results for the "Some#Test.txt" file are expected.

Actual result:
--------------
"false" is output instead

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-02-10 00:28 UTC] ramsey@php.net
I've not seen intval() used on a resource like this. Should that work to allow the ssh2.sftp stream wrapper to connect to the server?

Have you tried using ssh2_sftp_stat() instead? For example:

print_r(ssh2_sftp_stat($sftp, 'Some#Test.txt'));

That works for me, though I was able to reproduce your particular issue, using the ssh2.sftp stream wrapper.

I don't think this is a bug. stat() uses URL wrappers, and a hash mark in URLs is the start of a fragment, so I think this behaves as expected.


To Reproduce Results:
---------------------

Start a Docker container for a local SFTP server:

docker run --rm -v "${PWD}/files:/home/foo" -p 2222:22 -d atmoz/sftp:alpine foo:pass:1001

Then create the following files in ${PWD}/files:

touch files/foo.txt
touch files/"Some#Test.txt"

Now, run the following script. It'll try to stat each file twice. Once with ssh2_sftp_stat() and once using stat() with the ssh2.sftp stream wrapper. Note how everything succeeds except the last stat() for Some#Test.txt.

<?php
$ssh2 = ssh2_connect('127.0.0.1', 2222);

if (ssh2_auth_password($ssh2, 'foo', 'pass')) {
    $sftp = ssh2_sftp($ssh2);

    print_r(ssh2_sftp_stat($sftp, 'foo.txt'));
    print_r(ssh2_sftp_stat($sftp, 'Some#Test.txt'));

    print_r(stat('ssh2.sftp://foo:pass@127.0.0.1:2222/foo.txt'));
    print_r(stat('ssh2.sftp://foo:pass@127.0.0.1:2222/Some#Test.txt'));
} else {
    echo 'Could not authenticate.' . PHP_EOL;
}
 [2019-02-10 12:31 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2019-02-10 12:31 UTC] cmb@php.net
> I've not seen intval() used on a resource like this. Should that
> work to allow the ssh2.sftp stream wrapper to connect to the
> server?

It's document this way in the manual[1], and relies on resource to
int conversion to give the unique resource number[2]. 

> I don't think this is a bug.

ACK.  The hash mark has to be properly escaped:

  print_r(stat("ssh2.sftp://" . intval($sftp) . "/Some%23Test.txt"));

[1] <http://php.net/manual/en/function.ssh2-sftp.php#refsect1-function.ssh2-sftp-examples>
[2] <http://php.net/manual/en/function.ssh2-sftp.php#refsect1-function.ssh2-sftp-examples>
 [2019-02-11 18:35 UTC] memso at memso dot net
@ cmb@php.net

Your solution does not work. If the SFTP code is supposed to convert URL encoded strings back to real strings before accessing files, it is not doing so.

To make it very clear what is happening, I created 2 files on the SFTP.

Some#Test.txt
Correct file

Some%23Test.txt
WRONG FILE

When I run the following code:
$ssh2 = ssh2_connect("server", 22);
$sftp = ssh2_sftp($ssh2);
print_r(file_get_contents("ssh2.sftp://" . intval($sftp) . "/Some%23Test.txt"));

The result is:
WRONG FILE
 [2019-02-11 18:43 UTC] cmb@php.net
-Status: Not a bug +Status: Open -Assigned To: cmb +Assigned To:
 [2019-02-11 18:43 UTC] cmb@php.net
Well, then there is something wrong.
 [2019-02-11 22:16 UTC] ramsey@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: ramsey
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Jul 24 07:01:26 2019 UTC