tchwork / utf8

Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP
Apache License 2.0
627 stars 50 forks source link

Failed read the root directory on OS Windows 7 #14

Closed peter-gribanov closed 9 years ago

peter-gribanov commented 10 years ago
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
lstat('win://C:\Documents and Settings');
Warning: lstat(): Lstat failed for C:\DOCUME~1 in C:\Releases\test\vendor\patchwork\utf8\class\Patchwork\Utf8\WinFsStreamWrapper.php on line 389
Warning: lstat(): Lstat failed for win://C:\Documents and Settings in C:\Releases\test\vendor\test\app-bundle\src\Test\Bundle\AppBundle\Controller\FormController.php on line 125

lstat() is called when reading directory

Unknown error occurs in the class _comexception when calling

is_dir('win://C:\pagefile.sys');
peter-gribanov commented 10 years ago

It is the only cross-platform solution

$origin_path = $path;

// wrap fs
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
    stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
    $path = 'win://'.$path;
}

// scan directory
$folders = [];
/* @var $file \SplFileInfo */
foreach (new \DirectoryIterator($path) as $file) {
    if (
        !in_array($file->getFilename(), ['.', '..', '.Spotlight-V100', '.Trashes', 'pagefile.sys']) &&
        $file->isDir() && $file->isReadable()
    ) {
        $folders[$file->getFilename()] = [
            'name' => $file->getFilename(),
            'path' => $origin_path.$file->getFilename().DIRECTORY_SEPARATOR
        ];
    }
}
ksort($folders);

// add link on parent folder
if (substr_count($origin_path, DIRECTORY_SEPARATOR) > 1) {
    $pos = strrpos(substr($origin_path, 0, -1), DIRECTORY_SEPARATOR) + 1;
    array_unshift($folders, [
        'name' => '..',
        'path' => substr($origin_path, 0, $pos)
    ]);
}

Сhecked by:

nicolas-grekas commented 10 years ago

I currently don't have a WIndows to test... But I noted an idea from your comment : the stream prefix could be made to work both on windows and other systems, so that you don't have to do this "if (defined())", and just prefix with eg utf8:// and get portability. Can you find a patch to fix the pb?

peter-gribanov commented 10 years ago

I'll look for a solution, and if i find it i make a patch

nicolas-grekas commented 10 years ago

Thanks! I suggest you start by testing if the fs() function works as expected with paths in the root: https://github.com/nicolas-grekas/Patchwork-UTF8/blob/lab-windows-fs/class/Patchwork/Utf8/WinFsStreamWrapper.php#L38

nicolas-grekas commented 10 years ago

I still didn't find a Windows machine to test the problem, but I want to let you know that I just added a new Patchwork\Utf8::wrapPath($path = '') method which should help portability: is auto selects+registers the stream wrapper. I also renamed WinFsStreamWrapper to WindowsStreamWrapper, and merged this into master, tagged as v1.2.0-beta.

peter-gribanov commented 10 years ago

Thank you. I will be glad to take advantage

nicolas-grekas commented 9 years ago

Should be fixed by f1a973412b53b9b48355719e5f3619836cb0c3e4