PDA

View Full Version : Using function opendir on a network drive



goldd1gger
12-28-2007, 01:43 PM
Hello,

I need major help with the opendir function in php.
I have a network drive that I have access to by mapping to it.
This network drive can be access on the web as well in which
it display the directory tree of that drive.

Now what I am attempting to do is from my web server (M: drive),
I have a php page that I want to access the network drive (Z: drive) so
that I can display the directory tree in this php file or page. However,
I can not seem to get it to work.

I have tried several ways but I can not get it to access the network drive.
Please someone help me.

example of my code:

(1) $dir = "Z:\\mydirectory\htdocs";
(2) $dir = "Z:\\\\mydirectory\\htdocs";
(3) $dir = "Z://mydirectory/htdocs/";

if (is_dir($dir)) {
if ($dh = opendir($dir)) {
print "able to access directory tree.";}}
else {
print "not access tree.";}

Leafy
01-02-2008, 09:25 AM
Your problem arises when you escape the wrong characters.
The correct dir, when unescaped should be


Z:\mydirectory\htdocs


We need to escape both of the backslashes with a preceding backslash.

Your $dir 's are, as unescaped strings


Dir 1: Z:\mydirectory\\htdocs
Dir 2: Z:\\mydirectory\htdocs
Dir 3: Z://mydirectory/htdocs/


The problem with Dir 1 is that you forgot to escape the backslash before htdocs, so it escapes "\h" not the backslash, and since "\h" is not a special character, it becomes "\\h" (but you want it to be "\h")

The correct $dir would be


$dir = "Z:\\mydirectory\\htdocs";

goldd1gger
01-14-2008, 03:04 PM
Leafy,

I tried that and still it did not work. I am able to map to that drive but am not able to access it in my code. I don't know what I am doing wrong. Any suggestions?

Master_script_maker
01-14-2008, 09:03 PM
i have made a dir script that you can use if you want demo (http://masterproject.freehostia.com/dir/dir.php). just edit the
$defaultdir

DaveRandom
03-30-2009, 07:50 PM
SOLUTION

For anyone having this issue (this is the first page that google kept giving me when trying to resolve it), and indeed the original posters, here is how to get around this problem. I have found two methods that work, and here they are:



Use FTP instead of a network drive

PHP's opendir() accepts FTP site URL's. However, this method is flawed in a number of ways:


FTP is slower than a network drive unless you disable error correction, which is complicated and you don't want to do anyway.


If you are not accessing a machine with a built in FTP server (like win XP pro or a server OS) you have to use third party software.


Not all of PHP's file system functions can be performed via FTP.


FTP is VERY insecure.



Prefered Solution: Map a network drive using PHP at the beginning of the script

This solution is taken from Matt Grimm's posts on the opendir() page of the manual (http://uk3.php.net/function.opendir) at PHP.net


1) Ensure Apache (or IIS, or php.exe if your running the CLI) is running as an account that has permission to access the relevant resource (I think this is the major sticking point here, the SYSTEM account doesn't have access to mapped network drives!!, but this step alone does not solve the problem). I just ran it as "Administrator", but if you are worried about the (slight) security implications there, set up a new user account and run it under that. You can change this setting in Control Panel > Administrative Tools > Services, select the relevant service and get the properties, then select the "Log On" tab.


2) AT THE BEGINNING of your script, map the network drive with your PHP code, using the windows "net" command's "use" function (you can map network drives from cmd with this command as well... type "net /?" at a command prompt for a basic explanation of this powerful command).


Here's the line: (Matt Grimm got this slightly wrong)


system('net use Z: "\\servername\sharename" PASSWORD /user:USERNAME /persistent:no');


Notes:

Use the system() command, not exec(). No idea why, but it doesn't work if you use exec(), although the command executes successfully. I haven't tried passthru(), but then why you would use it in this context I don't know...


You can use any unused drive letter. "Z:" is just an example.


If your share name contains a space, you MUST surround the path in the command with double quotes. It's good practice to do this when specifying any path for a Windows command. You must also keep the single quotes in the PHP command, and you not need to escape any back slashes. You can use an IP address instead of a name for the server if you wish.


Yes, it goes password, then username. Also there is no "/password" tag. Wierd, I know, but that's Microsoft for you.

Obviously there is a bit of a security issue with storing the password in your code, essentially in plain text, so here (http://www.tonymarston.net/php-mysql/encryption.html) is a nice (albeit long) tutorial on a reversible password encryption method for PHP.


The "/persistent:no" part is essential. The network drive you map from PHP will not be visible in explorer, even if you specify your account as the logon account for Apache. If you don't turn "/persistent" off then it is still there, invisible, after a reboot, and the re-mapping attempt when you run the script again gets an error. You can, however, run the script multiple times during one session in Windows/PHP (ie one boot) without the error.



3) You can now access your network drive from a PHP command! Remember to escape any back slashes ( \ becomes \\ ) or you can just use forward slashes...

Z:/an/example/path

...is perfectly valid. (take note, because this makes writing cross-plaform scripts a lot easier and helps you avoid all those "spent an hour trying to find the problem and forgot to escape something" incidents)



This solution has been tested
with: Apache/2.0.63 (Win32) PHP/5.2.8
on: Windows XP Professional SP2/SP3, Windows Server 2003 R2 (various editions)

However, since the issue is basically an NT auth problem, this should work with any version of PHP (including command line) and any NT based OS.

DaveRandom
04-17-2009, 06:27 PM
Edit to the above post:

Since the system() command writes the output of the executed shell command straight to the output buffer, if you wish to hide the return of the command (i.e. "The command completed succesfully" or an error message) from a web browser, you need to alter the command that is sent to the shell so that the output of that command is hidden.

In the Windows command shell, this is done by sending both the output (1) and error (2) messages to "nul" using pipes, in other words...




// Define parameters for shell command
$letter = "Z";
$location = "\\servername\sharename";
$user = "USERNAME";
$pass = "PASSWORD";

Execute the command
system("net use " . $letter . ": \"".$location."\" ".$pass." /user:".$user." /persistent:no>nul 2>&1");



This differs drastically from the line above - you should be able to just take this code and put your value into the variables. The important bit is the >nul 2>&1 at the end.

Check out ss64.com (http://www.ss64.com/nt/syntax-redirection.html) for a great page on Windows command redirection and some more great reference pages for various languages.


As a further side note, I have successfully used either file_exists() or is_dir() to dynamically choose which drive letter to use (file_exists() doesn't always work in IIS/PHP4 for a reason I haven't yet figured out). Here (http://networkm.co.uk/static/chooseletter.html) is the function, with code, instructions and examples.