I'm having trouble navigating my directory structure using php's ftp
functions (such as ftp_chdir and ftp_cdup.) I'm writing a program that
allows a user to easily create robot.txt files and upload them to
their server. They should be able to log in to their server using ftp
and browse their directory structure, specifying which robots to allow
into each directory.
When the user logs into their server, they are presented with a list
of directories displayed as links. Clicking a directories link will
take them into that directory and will present them with the
sub-directories contained in that directory. I have the program
running at
http://www.storeminder.biz/robots/
Each time is link is clicked, the page is refreshed and ftp_connect
called, meaning that the user is logged back in to their root
directory. I have a stack containing the directories that have been
navigated, so that the program can direct the user to the drectory
they intend to be in.
This seems overly complicated. Is it possible to do what I am trying
to do just using php's ftp functions, without storing a session
variable containing all the directories that have been navigated? Is
is possible to not have to re-login to the root directory every time a
page that uses ftp functions is called?
The solution I have seems to work well and handles symbolic links, but
has the drawback that I can't navigate above the directory that the
user originally logs into. It also just doesn't seem like the correct
way to do this. I'm sure there is a simpler, more proper way.
Any ideas would be greatly appreciated.
I'm posting my code below. I tried to make it well commented and easy
to understand.
Thanks,
Esoos
<?php
include 'include.php';
session_start();
//If $_POST variables are set then we are logging in for the first
time and set $_SESSION variables accordingly
if (isset($_POST['server'])) {
$post = clean_post($_POST);
$_SESSION['ftp_server'] = $post['server'];
$_SESSION['ftp_username'] = $post['username'];
$_SESSION['ftp_password'] = $post['password'];
//Create a stack/array which holds the name of the directories we
have traversed
$_SESSION['directories'] = Array();
}
//if we are not connected to a server then redirect to the login page
if (!isset($_SESSION['ftp_server'])) {
header("Location: login.php");
exit;
}
//If $_GET variables are set then we are actively navigating the
directory structure
if (isset($_GET['dir'])) {
$get = clean_get($_GET);
$ftp_dir = $get['dir'];
}
// set up a connection or die
$conn_id = ftp_connect($_SESSION['ftp_server']) or die("Couldn't
connect to " . $_SESSION['ftp_server'] . "<br>");
// try to login
if (@ftp_login($conn_id, $_SESSION['ftp_username'],
$_SESSION['ftp_password'])) {
echo "Connected as " . $_SESSION['ftp_username'] . "@" .
$_SESSION['ftp_server'] . "<br>";
$_SESSION['username'] = $_SESSION['ftp_username'];
} else {
echo "Couldn't connect as " . $_SESSION['ftp_username'] . "<br>";
}
// turn passive mode on
ftp_pasv($conn_id, true);
//If we are navigating the directoty structure
if (isset($ftp_dir)) {
//if we are navigating to the parent directory pop the name of the
current directory off the stack
if($_GET['act'] == 'cdup') {
array_pop($_SESSION['directories']);
}
//otherwise we are navigating to a child directory
else {
//grab the name of the current directory and push it on the
$_SESSION['directories'] stack
$pieces = explode("/", $ftp_dir);
$relative_path_dir = array_pop($pieces);
array_push($_SESSION['directories'], $relative_path_dir);
}
//Since the stateless nature of http forces us to always login to
the root directory
//we use the $_SESSION['directories'] stack/array to navigate to
child directory we are trying to access
foreach($_SESSION['directories'] as $rel_dir) {
if (ftp_chdir($conn_id, $rel_dir)) {
//do nothing for now
} else {
echo "Couldn't change directory\n";
}
}
//we are in the child directory, so display the path
echo "Current directory is now: " . ftp_pwd($conn_id) . "\n";
}
else {
//we are in the root directory, so display the path
echo "Current directory is now: " . ftp_pwd($conn_id) . "\n";
}
function create_dir_tree() {
global $conn_id;
$files = ftp_nlist($conn_id, ""); //get files in directory
if(is_array($files)) {
//display a link to the parent directory
echo "<br /><a href=index.php?&act=cdup&dir=" . ftp_pwd($conn_id)
.. ">parent directory</a>";
foreach ($files as $file) {
$isfile = ftp_size($conn_id, $file);
if($isfile == "-1") { //Is it a directory? (as opposed to a file)
//display a link to each child directory
$string = "<br /><a href=index.php?&dir=" . ftp_pwd($conn_id) .
"/" . $file . ">" . $file . "</a>";
//replace any double slashes with single slashes
$url = preg_replace("/\/\//", "/", $string);
print $url;
}
}
}
else echo "<br /><a href=index.php?&act=cdup&dir=" .
ftp_pwd($conn_id) . ">parent directory</a>";
}
?>
<html>
<head></head>
<body>
<table border="1" cellSpacing="3" cellPadding="3" width="100%">
<tr>
<td>
<?php create_dir_tree(); ?>
</td>
<td>
<form method="post" action="create_text.php">
<table border="1" cellSpacing="3" cellPadding="3" width="100%">
<tr>
<td>
<ul>
<li><input type="checkbox" id="all" name="all">* (all
spiders)</input></li>
<li><input type="checkbox" id="googlebot"
name="googlebot">googlebot</input></li>
<li><input type="checkbox" id="askjeeves"
name="askjeeves">askjeeves</input></li>
<li><input type="checkbox" id="slurp" name="slurp">inktomi
slurp</input></li>
<li><input type="checkbox" id="scooter"
name="scooter">altavista scooter</input></li>
<input type="hidden" name="path" value="<?php echo
ftp_pwd($conn_id) ?>"></input>
</ul>
</td>
</tr>
<tr>
<td align="center">
<input type="submit" value="Submit"></input>
<input type="hidden" name="activity"
value="logging_in"></input>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>
<?php
// close the connection
ftp_close($conn_id);
?>