* @version 1.1.1 (August 10, 2005)
* @package AutoIndex
*/
class Admin
{
/**
* @var int The level of the logged in user
*/
private $level;
/**
* @var string The name of the logged in user
*/
private $username;
/**
* @param string $path The path of the directory to create
* @return bool True on success, false on failure
*/
public static function mkdir_recursive($path)
{
$path = Item::make_sure_slash($path);
if (@is_dir($path))
{
return true;
}
if (!self::mkdir_recursive(dirname($path)))
{
return false;
}
return @mkdir($path, 0755);
}
/**
* Deletes a directory and all its contents.
*
* @param string $path The path of the directory to delete
* @return bool True on success, false on failure
*/
private static function rmdir_recursive($path)
{
$path = Item::make_sure_slash($path);
$list = @scandir($path);
if ($list === false)
{
return false;
}
foreach ($list as $file)
{
if ($file == '' || $file == '.' || $file == '..')
{
continue;
}
$dir = "$path$file/";
@is_dir($dir) ? self::rmdir_recursive($dir) : @unlink($dir);
}
return @rmdir($path);
}
/**
* Copies a remote file to the local server.
*
* @param string $protocol Either ftp:// or http://
* @param string $url The rest of the URL after the protocol
*/
private static function copy_remote_file($protocol, $url)
{
if ($protocol == '' || $url == '')
{
throw new ExceptionDisplay('Please go back and enter a file to copy.');
}
global $dir;
$local_file = $dir . Item::get_basename($url);
if (@file_exists($local_file))
{
throw new ExceptionDisplay('The file already exists in this directory.');
}
$remote = $protocol . $url;
$r = @fopen($remote, 'rb');
if ($r === false)
{
throw new ExceptionDisplay('Cannot open remote file for reading: '
. Url::html_output($remote) . '');
}
$l = @fopen($local_file, 'wb');
if ($l === false)
{
throw new ExceptionDisplay('Cannot open local file for writing.');
}
while (true)
{
$temp = fread($r, 8192);
if ($temp === '')
{
break;
}
fwrite($l, $temp);
}
fclose($l);
fclose($r);
}
/**
* @param string $filename The path to the file that stores the info
* @param string $old_name The old name of the file or folder to update inside of $filename
* @param string $new_name The new name of the file or folder
*/
private static function update_file_info($filename, $old_name, $new_name)
{
if (!@is_file($filename))
{
throw new ExceptionDisplay('The file '
. Url::html_output($filename) . ' does not exist.');
}
$text = @file_get_contents($filename);
if ($text === false)
{
throw new ExceptionDisplay('Cannot open file '
. Url::html_output($filename) . ' for reading.');
}
$h = @fopen($filename, 'wb');
if ($h === false)
{
throw new ExceptionDisplay('Cannot open file '
. Url::html_output($filename) . ' for writing.');
}
fwrite($h, preg_replace('/^' . preg_quote($old_name, '/')
. '/m', $new_name, $text));
fclose($h);
}
/**
* Validates a potential new password.
*
* @param string $pass1 The new password
* @param string $pass2 The new password typed again
*/
private static function validate_new_password($pass1, $pass2)
{
if ($pass1 != $pass2)
{
throw new ExceptionDisplay('Passwords do not match.');
}
if (strlen($pass1) < 6)
{
throw new ExceptionDisplay('Password must be at least 6 characters long.');
}
}
/**
* Changes a user's password.
*
* @param string $username The username
* @param string $old_pass The user's old password
* @param string $new_pass1 The new password
* @param string $new_pass2 The new password typed again
*/
private static function change_password($username, $old_pass, $new_pass1, $new_pass2)
{
self::validate_new_password($new_pass1, $new_pass2);
$accounts = new Accounts();
if (!$accounts -> user_exists($username))
{
throw new ExceptionDisplay('Cannot change password: username does not exist.');
}
if (!$accounts -> is_valid_user(new User($username, sha1($old_pass))))
{
throw new ExceptionDisplay('Incorrect old password.');
}
global $config;
$h = @fopen($config -> __get('user_list'), 'wb');
if ($h === false)
{
throw new ExceptionDisplay("Could not open file $user_list for writing."
. ' Make sure PHP has write permission to this file.');
}
foreach ($accounts as $this_user)
{
if (strcasecmp($this_user -> username, $username) === 0)
{
$this_user = new User($username, sha1($new_pass1), $this_user -> level, $this_user -> home_dir);
}
fwrite($h, $this_user -> __toString());
}
fclose($h);
$_SESSION['password'] = sha1($new_pass1);
throw new ExceptionDisplay('Password successfully changed.');
}
/**
* Changes a user's level.
*
* @param string $username The username
* @param int $new_level The user's new level
*/
private static function change_user_level($username, $new_level)
{
if ($new_level < BANNED || $new_level > ADMIN)
{
throw new ExceptionDisplay('Invalid user level.');
}
$accounts = new Accounts();
if (!$accounts -> user_exists($username))
{
throw new ExceptionDisplay('Cannot change level: username does not exist.');
}
global $config;
$h = @fopen($config -> __get('user_list'), 'wb');
if ($h === false)
{
throw new ExceptionDisplay("Could not open file $user_list for writing."
. ' Make sure PHP has write permission to this file.');
}
foreach ($accounts as $this_user)
{
if (strcasecmp($this_user -> username, $username) === 0)
{
$this_user = new User($username, $this_user -> sha1_pass, $new_level, $this_user -> home_dir);
}
fwrite($h, $this_user -> __toString());
}
fclose($h);
throw new ExceptionDisplay('User level successfully changed.');
}
/**
* @param string $username The name of the new user to create
* @param string $pass1 The raw password
* @param string $pass2 The raw password repeated again for verification
* @param int $level The level of the user (use GUEST USER ADMIN constants)
* @param string $home_dir The home directory of the user, or blank for the default
*/
private static function add_user($username, $pass1, $pass2, $level, $home_dir = '')
{
self::validate_new_password($pass1, $pass2);
$username_reg_exp = '/^[A-Za-z0-9_-]+$/';
if (!preg_match($username_reg_exp, $username))
{
throw new ExceptionDisplay('The username must only contain alpha-numeric characters, underscores, or dashes.'
. '
It must match the regular expression: '
. Url::html_output($username_reg_exp) . '');
}
if ($home_dir != '')
{
$home_dir = Item::make_sure_slash($home_dir);
if (!@is_dir($home_dir))
{
throw new ExceptionDisplay('The user\'s home directory is not valid directory.');
}
}
$list = new Accounts();
if ($list -> user_exists($username))
{
throw new ExceptionDisplay('This username already exists.');
}
global $config;
$h = @fopen($config -> __get('user_list'), 'ab');
if ($h === false)
{
throw new ExceptionDisplay('User list file could not be opened for writing.');
}
$new_user = new User($username, sha1($pass1), $level, $home_dir);
fwrite($h, $new_user -> __toString());
fclose($h);
throw new ExceptionDisplay('User successfully added.');
}
/**
* @param string $username Deletes user with the name $username
*/
private static function del_user($username)
{
$accounts = new Accounts();
if (!$accounts -> user_exists($username))
{
throw new ExceptionDisplay('Cannot delete user: username does not exist.');
}
global $config;
$h = @fopen($config -> __get('user_list'), 'wb');
if ($h === false)
{
throw new ExceptionDisplay("Could not open file $user_list for writing."
. ' Make sure PHP has write permission to this file.');
}
foreach ($accounts as $this_user)
{
if (strcasecmp($this_user -> username, $username) !== 0)
{
fwrite($h, $this_user -> __toString());
}
}
fclose($h);
throw new ExceptionDisplay('User successfully removed.');
}
/**
* @param User $current_user This user is checked to make sure it really is an admin
*/
public function __construct(User $current_user)
{
if (!($current_user instanceof UserLoggedIn))
{
throw new ExceptionDisplay('You must be logged in to access this section.');
}
$this -> level = $current_user -> level;
$this -> username = $current_user -> username;
}
/**
* @param string $action
*/
public function action($action)
{
//This is a list of the actions moderators can do (otherwise, the user must be an admin)
$mod_actions = array('edit_description', 'change_password', 'ftp');
if (in_array(strtolower($action), $mod_actions))
{
if ($this -> level < MODERATOR)
{
throw new ExceptionDisplay('You must be a moderator to access this section.');
}
}
else if ($this -> level < ADMIN)
{
throw new ExceptionDisplay('You must be an administrator to access this section.');
}
switch (strtolower($action))
{
case 'config':
{
/** Include the config generator file. */
if (!@include_once(CONFIG_GENERATOR))
{
throw new ExceptionDisplay('Error including file '
. CONFIG_GENERATOR . '');
}
die();
}
case 'rename':
{
if (!isset($_GET['filename']))
{
throw new ExceptionDisplay('No filenames specified.');
}
global $dir;
$old = $dir . Url::clean_input($_GET['filename']);
if (!@file_exists($old))
{
header('HTTP/1.0 404 Not Found');
throw new ExceptionDisplay('Specified file could not be found.');
}
if (isset($_GET['new_name']))
{
$new = $dir . Url::clean_input($_GET['new_name']);
if ($old == $new)
{
throw new ExceptionDisplay('Filename unchanged.');
}
if (@file_exists($new))
{
throw new ExceptionDisplay('Cannot overwrite existing file.');
}
if (@rename($old, $new))
{
global $config;
if (DOWNLOAD_COUNT)
{
self::update_file_info($config -> __get('download_count'), $old, $new);
}
if (DESCRIPTION_FILE)
{
self::update_file_info($config -> __get('description_file'), $old, $new);
}
throw new ExceptionDisplay('File renamed successfully.');
}
throw new ExceptionDisplay('Error renaming file.');
}
global $words, $subdir;
throw new ExceptionDisplay('
' . $words -> __get('renaming') . ' ' . Url::html_output($_GET['filename']) . '
' . $words -> __get('new filename')
. ':
('
. $words -> __get('you can also move the file by specifying a path')
. ')
' . $words -> __get('are you sure you want to delete the file') . ' ' . Url::html_output($_GET['filename']) . '?
' . ''); } case 'add_user': { if (isset($_POST['username'], $_POST['pass1'], $_POST['pass2'], $_POST['level'], $_POST['home_dir'])) { self::add_user($_POST['username'], $_POST['pass1'], $_POST['pass2'], (int)$_POST['level'], $_POST['home_dir']); } global $words; throw new ExceptionDisplay($words -> __get('add user') . ':'); } case 'change_password': { if (isset($_POST['pass1'], $_POST['pass2'], $_POST['old_pass'])) { self::change_password($this -> username, $_POST['old_pass'], $_POST['pass1'], $_POST['pass2']); } throw new ExceptionDisplay(''); } case 'change_user_level': { if (isset($_POST['username'], $_POST['level'])) { self::change_user_level($_POST['username'], (int)$_POST['level']); } $accounts = new Accounts(); $out = ''); } case 'del_user': { if (isset($_POST['username'])) { if (isset($_POST['sure'])) { self::del_user($_POST['username']); } global $words; throw new ExceptionDisplay('' . $words -> __get('are you sure you want to remove the user') . ' '.$_POST['username'] . '?
' . ''); } global $words; $accounts = new Accounts(); $out = '' . $words -> __get('select user to remove') . ':
'); } case 'edit_description': { if (isset($_GET['filename'])) { global $dir; $filename = $dir . $_GET['filename']; if (isset($_GET['description'])) { global $descriptions, $config; if (DESCRIPTION_FILE && $descriptions -> is_set($filename)) //if it's already set, update the old description { //update the new description on disk $h = @fopen($config -> __get('description_file'), 'wb'); if ($h === false) { throw new ExceptionDisplay('Could not open description file for writing.' . ' Make sure PHP has write permission to this file.'); } foreach ($descriptions as $file => $info) { fwrite($h, "$file\t" . (($file == $filename) ? $_GET['description'] : $info) . "\n"); } fclose($h); //update the new description in memory $descriptions -> set($filename, $_GET['description']); } else if ($_GET['description'] != '') //if it's not set, add it to the end { $h = @fopen($config -> __get('description_file'), 'ab'); if ($h === false) { throw new ExceptionDisplay('Could not open description file for writing.' . ' Make sure PHP has write permission to this file.'); } fwrite($h, "$filename\t" . $_GET['description'] . "\n"); fclose($h); //read the description file with the updated data $descriptions = new ConfigData($config -> __get('description_file')); } } else { global $words, $subdir, $descriptions; $current_desc = (DESCRIPTION_FILE && $descriptions -> is_set($filename) ? $descriptions -> __get($filename) : ''); throw new ExceptionDisplay('' . $words -> __get('enter the new description for the file') . ' ' . Url::html_output($_GET['filename']) . ':
'); } } else { throw new ExceptionDisplay('No filename specified.'); } break; } case 'edit_hidden': { if (!HIDDEN_FILES) { throw new ExceptionDisplay('The file hiding system is not in use. To enable it, reconfigure the script.'); } global $hidden_list; if (isset($_GET['add']) && $_GET['add'] != '') { global $config; $h = @fopen($config -> __get('hidden_files'), 'ab'); if ($h === false) { throw new ExceptionDisplay('Unable to open hidden files list for writing.'); } fwrite($h, $_GET['add'] . "\n"); fclose($h); throw new ExceptionDisplay('Hidden file added.'); } if (isset($_GET['remove'])) { global $config; $h = @fopen($config -> __get('hidden_files'), 'wb'); if ($h === false) { throw new ExceptionDisplay('Unable to open hidden files list for writing.'); } foreach ($hidden_list as $hid) { if ($hid != $_GET['remove']) { fwrite($h, $hid . "\n"); } } fclose($h); throw new ExceptionDisplay('Hidden file removed.'); } global $words; $str = 'You can also use wildcards (?, *, +) for each entry.
'
. 'If you want to do the opposite of "hidden files" - show only certain files - '
. 'put a colon in front of those entries.
' . $words -> __get('enter the new name') . ':
'); } break; } case 'copy_url': { if (isset($_GET['protocol'], $_GET['copy_file'])) { self::copy_remote_file(rawurldecode($_GET['protocol']), rawurldecode($_GET['copy_file'])); throw new ExceptionDisplay('Copy was successful.'); } global $dir; $text = '|
Enter the name of the remote file you would like to copy: |
Logout successful. Go back.
'; } else if (isset($_SESSION['ftp'])) { try { $ftp = new Ftp($_SESSION['ftp']['host'], $_SESSION['ftp']['port'], $_SESSION['ftp']['passive'], $_SESSION['ftp']['directory'], $_SESSION['ftp']['username'], $_SESSION['ftp']['password']); } catch (ExceptionFatal $e) { unset($_SESSION['ftp']); throw $e; } if (isset($_GET['filename']) && $_GET['filename'] != '') //transfer local to FTP { global $dir; $name = rawurldecode($_GET['filename']); $ftp -> put_file($dir . $name, Item::get_basename($name)); throw new ExceptionDisplay('File successfully transferred to FTP server.'); } if (isset($_GET['transfer']) && $_GET['transfer'] != '') //transfer FTP to local { global $dir; $name = rawurldecode($_GET['transfer']); $ftp -> get_file($dir . Item::get_basename($name), $name); throw new ExceptionDisplay('File successfully transferred from FTP server.'); } global $words; $text = 'Logout of FTP server
Back to index.
' . $words -> __get('reconfigure script') . '
'
. $words -> __get('edit list of hidden files') . '
'
. $words -> __get('edit ban list') . '
' . $words -> __get('create new directory in this folder')
. '
' . $words -> __get('copy url') . '
'
. $words -> __get('view entries from log file') . '
'
. $words -> __get('view statistics from log file') . '
'
. $words -> __get('add new user') . '
'
. $words -> __get('delete user') . '
Change a user\'s level