Skip to content

Instantly share code, notes, and snippets.

@stevebauman
Last active June 18, 2020 17:29
Show Gist options
  • Save stevebauman/08025714a7470f387ab34fca4b8e4802 to your computer and use it in GitHub Desktop.
Save stevebauman/08025714a7470f387ab34fca4b8e4802 to your computer and use it in GitHub Desktop.
PHP Windows Directory Mounter
<?php
use UnexpectedValueException;
class DirectoryMounter
{
/**
* The path to mount.
*
* @var string|null
*/
protected $path;
/**
* Constructor.
*
* @param string|null $path
*/
public function __construct($path = null)
{
$this->path = $path;
}
/**
* Destructor.
*
* Remove mounted drive upon destructing.
*/
public function __destruct()
{
$this->unmount();
}
/**
* Set the path to mount.
*
* @param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get the path that is being mounted.
*
* @return string|null
*/
public function getPath()
{
return $this->path;
}
/**
* Mounts the current path as a drive.
*
* @param string|null $username
* @param string|null $password
*
* @return bool
*/
public function mount($username = null, $password = null)
{
// Ensure our path isn't already mounted by forcing its removal.
$this->unmount();
// Escape the command args for safety.
$args = array_map(function ($value) {
return escapeshellarg($value);
}, array_filter([$this->path, $username, $password]));
// Determine the mount command to execute.
$command = empty($username) && empty($password) ?
$this->getMountCommand(...$args) :
$this->getAuthenticatedMountCommand(...$args);
return $this->execute($command) === 0;
}
/**
* Un-mounts the current drive path.
*
* @return bool
*
* @throws UnexpectedValueException
*/
public function unmount()
{
if (empty($this->path)) {
throw new UnexpectedValueException('A path must be given to unmount.');
}
return $this->execute(
$this->getUnmountCommand(escapeshellarg($this->path))
) === 0;
}
/**
* Get an authenticated Windows mount command for the given path.
*
* @param string $path
* @param string $username
* @param string|null $password
*
* @return string
*/
protected function getAuthenticatedMountCommand($path, $username, $password = null)
{
return sprintf('net use %s %s /user:%s /persistent:no 2>&1', $path, $password, $username);
}
/**
* Get an unauthenticated Windows mount command for the given path.
*
* @param string $path
*
* @return string
*/
protected function getMountCommand($path)
{
return sprintf('net use %s /persistent:no 2>&1', $path);
}
/**
* Get the Windows unmount command for the given path.
*
* @param string $path
*
* @return string
*/
protected function getUnmountCommand($path)
{
return sprintf('net use /delete %s', $path);
}
/**
* Execute and return the commands response.
*
* @param string $command
*
* @return mixed
*/
protected function execute($command)
{
exec($command, $out, $return);
return $return;
}
}
@Braunson
Copy link

Assuming I'm using this correctly, the mount command only returns bool true/false.

$win = new DirectoryMounter($path);
var_dump($win->mount($user, $pass));

Is this correct? The goal is to grab the directories/file listing of the mounted directory.

@stevebauman
Copy link
Author

stevebauman commented Jun 18, 2020

Yes, the DirectoryMounter simply mounts the network directory so PHP has access to it. You can then use native PHP or Laravel's File facade to get list files and directories at the given path:

use Illuminate\Support\Facades\File;

$win = new DirectoryMounter($path);

if ($win->mount($user, $pass)) {
    $files = File::files($path);

    foreach ($files as $file) {}
}

@stevebauman
Copy link
Author

stevebauman commented Jun 18, 2020

@Braunson By the way, if you're using an IIS as your web server, you will need to change the IIS Application Pool that your Laravel / PHP application is running under to run as a NetworkService account, instead of ApplicationPoolIdentity or another:

Otherwise, your PHP application won't be able to access any network resources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment