Example #1
0
 /**
  * Allow the admin to reset permissions on files.
  */
 public function action_perms()
 {
     global $context, $txt, $modSettings, $package_ftp;
     // Let's try and be good, yes?
     checkSession('get');
     // If we're restoring permissions this is just a pass through really.
     if (isset($_GET['restore'])) {
         create_chmod_control(array(), array(), true);
         fatal_lang_error('no_access', false);
     }
     // This is a time and memory eating ...
     setMemoryLimit('128M');
     @set_time_limit(600);
     // Load up some FTP stuff.
     create_chmod_control();
     if (empty($package_ftp) && !isset($_POST['skip_ftp'])) {
         require_once SUBSDIR . '/FtpConnection.class.php';
         $ftp = new Ftp_Connection(null);
         list($username, $detect_path, $found_path) = $ftp->detect_path(BOARDDIR);
         $context['package_ftp'] = array('server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', 'username' => empty($username) ? isset($modSettings['package_username']) ? $modSettings['package_username'] : '' : $username, 'path' => $detect_path, 'form_elements_only' => true);
     } else {
         $context['ftp_connected'] = true;
     }
     // Define the template.
     $context['page_title'] = $txt['package_file_perms'];
     $context['sub_template'] = 'file_permissions';
     // Define what files we're interested in, as a tree.
     $context['file_tree'] = array(strtr(BOARDDIR, array('\\' => '/')) => array('type' => 'dir', 'contents' => array('agreement.txt' => array('type' => 'file', 'writable_on' => 'standard'), 'Settings.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'Settings_bak.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'attachments' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'avatars' => array('type' => 'dir', 'writable_on' => 'standard'), 'cache' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'custom_avatar_dir' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'smileys' => array('type' => 'dir_recursive', 'writable_on' => 'standard'), 'sources' => array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'), 'themes' => array('type' => 'dir_recursive', 'writable_on' => 'standard', 'contents' => array('default' => array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))))), 'packages' => array('type' => 'dir', 'writable_on' => 'standard', 'contents' => array('temp' => array('type' => 'dir'), 'backup' => array('type' => 'dir'), 'installed.list' => array('type' => 'file', 'writable_on' => 'standard'))))));
     // Directories that can move.
     if (substr(SOURCEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['sources']);
         $context['file_tree'][strtr(SOURCEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard');
     }
     // Moved the cache?
     if (substr(CACHEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['cache']);
         $context['file_tree'][strtr(CACHEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => false, 'writable_on' => 'restrictive');
     }
     // Are we using multiple attachment directories?
     if (!empty($modSettings['currentAttachmentUploadDir'])) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']);
         if (!is_array($modSettings['attachmentUploadDir'])) {
             $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
         }
         // @todo Should we suggest non-current directories be read only?
         foreach ($modSettings['attachmentUploadDir'] as $dir) {
             $context['file_tree'][strtr($dir, array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
         }
     } elseif (substr($modSettings['attachmentUploadDir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']);
         $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
     }
     if (substr($modSettings['smileys_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['smileys']);
         $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'writable_on' => 'standard');
     }
     if (substr($modSettings['avatar_directory'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['avatars']);
         $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'standard');
     }
     if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['custom_avatar_dir']);
         $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
     }
     // Load up any custom themes.
     require_once SUBSDIR . '/Themes.subs.php';
     $themes = getCustomThemes();
     foreach ($themes as $id => $theme) {
         // Skip the default
         if ($id == 1) {
             continue;
         }
         if (substr(strtolower(strtr($theme['theme_dir'], array('\\' => '/'))), 0, strlen(BOARDDIR) + 7) === strtolower(strtr(BOARDDIR, array('\\' => '/')) . '/themes')) {
             $context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['themes']['contents'][substr($theme['theme_dir'], strlen(BOARDDIR) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true)));
         } else {
             $context['file_tree'][strtr($theme['theme_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true)));
         }
     }
     // If we're submitting then let's move on to another function to keep things cleaner..
     if (isset($_POST['action_changes'])) {
         return $this->action_perms_save();
     }
     $context['look_for'] = array();
     // Are we looking for a particular tree - normally an expansion?
     if (!empty($_REQUEST['find'])) {
         $context['look_for'][] = base64_decode($_REQUEST['find']);
     }
     // Only that tree?
     $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : '';
     if ($context['only_find']) {
         $context['look_for'][] = $context['only_find'];
     }
     // Have we got a load of back-catalogue trees to expand from a submit etc?
     if (!empty($_GET['back_look'])) {
         $potententialTrees = unserialize(base64_decode($_GET['back_look']));
         foreach ($potententialTrees as $tree) {
             $context['look_for'][] = $tree;
         }
     }
     // ... maybe posted?
     if (!empty($_POST['back_look'])) {
         $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']);
     }
     $context['back_look_data'] = base64_encode(serialize(array_slice($context['look_for'], 0, 15)));
     // Are we finding more files than first thought?
     $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0;
     // Don't list more than this many files in a directory.
     $context['file_limit'] = 150;
     // How many levels shall we show?
     $context['default_level'] = empty($context['only_find']) ? 2 : 25;
     // This will be used if we end up catching XML data.
     $context['xml_data'] = array('roots' => array('identifier' => 'root', 'children' => array(array('value' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])))), 'folders' => array('identifier' => 'folder', 'children' => array()));
     foreach ($context['file_tree'] as $path => $data) {
         // Run this directory.
         if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) {
             // Get the first level down only.
             fetchPerms__recursive($path, $context['file_tree'][$path], 1);
             $context['file_tree'][$path]['perms'] = array('chmod' => @is_writable($path), 'perms' => @fileperms($path));
         } else {
             unset($context['file_tree'][$path]);
         }
     }
     // Is this actually xml?
     if (isset($_GET['xml'])) {
         loadTemplate('Xml');
         $context['sub_template'] = 'generic_xml';
         Template_Layers::getInstance()->removeAll();
     }
 }
Example #2
0
/**
 * Check files are writable - make them writable if necessary...
 *
 * @param array $files
 */
function makeFilesWritable(&$files)
{
    global $upcontext;
    if (empty($files)) {
        return true;
    }
    $failure = false;
    // On linux, it's easy - just use is_writable!
    if (substr(__FILE__, 1, 2) != ':\\') {
        foreach ($files as $k => $file) {
            if (!is_writable($file)) {
                @chmod($file, 0755);
                // Well, 755 hopefully worked... if not, try 777.
                if (!is_writable($file) && !@chmod($file, 0777)) {
                    $failure = true;
                } else {
                    unset($files[$k]);
                }
            } else {
                unset($files[$k]);
            }
        }
    } else {
        foreach ($files as $k => $file) {
            // Folders can't be opened for write... but the index.php in them can ;).
            if (is_dir($file)) {
                $file .= '/index.php';
            }
            // Funny enough, chmod actually does do something on windows - it removes the read only attribute.
            @chmod($file, 0777);
            $fp = @fopen($file, 'r+');
            // Hmm, okay, try just for write in that case...
            if (!$fp) {
                $fp = @fopen($file, 'w');
            }
            if (!$fp) {
                $failure = true;
            } else {
                unset($files[$k]);
            }
            @fclose($fp);
        }
    }
    if (empty($files)) {
        return true;
    }
    if (!isset($_SERVER)) {
        return !$failure;
    }
    // What still needs to be done?
    $upcontext['chmod']['files'] = $files;
    // If it's windows it's a mess...
    if ($failure && substr(__FILE__, 1, 2) == ':\\') {
        $upcontext['chmod']['ftp_error'] = 'total_mess';
        return false;
    } elseif ($failure) {
        // Load any session data we might have...
        if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp'])) {
            $upcontext['chmod']['server'] = $_SESSION['installer_temp_ftp']['server'];
            $upcontext['chmod']['port'] = $_SESSION['installer_temp_ftp']['port'];
            $upcontext['chmod']['username'] = $_SESSION['installer_temp_ftp']['username'];
            $upcontext['chmod']['password'] = $_SESSION['installer_temp_ftp']['password'];
            $upcontext['chmod']['path'] = $_SESSION['installer_temp_ftp']['path'];
        } elseif (isset($_POST['ftp_username'])) {
            $upcontext['chmod']['server'] = $_POST['ftp_server'];
            $upcontext['chmod']['port'] = $_POST['ftp_port'];
            $upcontext['chmod']['username'] = $_POST['ftp_username'];
            $upcontext['chmod']['password'] = $_POST['ftp_password'];
            $upcontext['chmod']['path'] = $_POST['ftp_path'];
        }
        if (isset($upcontext['chmod']['username'])) {
            $ftp = new Ftp_Connection($upcontext['chmod']['server'], $upcontext['chmod']['port'], $upcontext['chmod']['username'], $upcontext['chmod']['password']);
            if ($ftp->error === false) {
                // Try it without /home/abc just in case they messed up.
                if (!$ftp->chdir($upcontext['chmod']['path'])) {
                    $upcontext['chmod']['ftp_error'] = $ftp->last_message;
                    $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $upcontext['chmod']['path']));
                }
            }
        }
        if (!isset($ftp) || $ftp->error !== false) {
            if (!isset($ftp)) {
                $ftp = new Ftp_Connection(null);
            } elseif ($ftp->error !== false && !isset($upcontext['chmod']['ftp_error'])) {
                $upcontext['chmod']['ftp_error'] = $ftp->last_message === null ? '' : $ftp->last_message;
            }
            list($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__));
            if ($found_path || !isset($upcontext['chmod']['path'])) {
                $upcontext['chmod']['path'] = $detect_path;
            }
            if (!isset($upcontext['chmod']['username'])) {
                $upcontext['chmod']['username'] = $username;
            }
            return false;
        } else {
            // We want to do a relative path for FTP.
            if (!in_array($upcontext['chmod']['path'], array('', '/'))) {
                $ftp_root = strtr(BOARDDIR, array($upcontext['chmod']['path'] => ''));
                if (substr($ftp_root, -1) == '/' && ($upcontext['chmod']['path'] == '' || $upcontext['chmod']['path'][0] === '/')) {
                    $ftp_root = substr($ftp_root, 0, -1);
                }
            } else {
                $ftp_root = BOARDDIR;
            }
            // Save the info for next time!
            $_SESSION['installer_temp_ftp'] = array('server' => $upcontext['chmod']['server'], 'port' => $upcontext['chmod']['port'], 'username' => $upcontext['chmod']['username'], 'password' => $upcontext['chmod']['password'], 'path' => $upcontext['chmod']['path'], 'root' => $ftp_root);
            foreach ($files as $k => $file) {
                if (!is_writable($file)) {
                    $ftp->chmod($file, 0755);
                }
                if (!is_writable($file)) {
                    $ftp->chmod($file, 0777);
                }
                // Assuming that didn't work calculate the path without the boarddir.
                if (!is_writable($file)) {
                    if (strpos($file, BOARDDIR) === 0) {
                        $ftp_file = strtr($file, array($_SESSION['installer_temp_ftp']['root'] => ''));
                        $ftp->chmod($ftp_file, 0755);
                        if (!is_writable($file)) {
                            $ftp->chmod($ftp_file, 0777);
                        }
                        // Sometimes an extra slash can help...
                        $ftp_file = '/' . $ftp_file;
                        if (!is_writable($file)) {
                            $ftp->chmod($ftp_file, 0755);
                        }
                        if (!is_writable($file)) {
                            $ftp->chmod($ftp_file, 0777);
                        }
                    }
                }
                if (is_writable($file)) {
                    unset($files[$k]);
                }
            }
            $ftp->close();
        }
    }
    // What remains?
    $upcontext['chmod']['files'] = $files;
    if (empty($files)) {
        return true;
    }
    return false;
}
Example #3
0
/**
 * Delete the installer and its additional files.
 * Called by ?delete
 */
function action_deleteInstaller()
{
    global $databases;
    if (isset($_SESSION['installer_temp_ftp'])) {
        $ftp = new Ftp_Connection($_SESSION['installer_temp_ftp']['server'], $_SESSION['installer_temp_ftp']['port'], $_SESSION['installer_temp_ftp']['username'], $_SESSION['installer_temp_ftp']['password']);
        $ftp->chdir($_SESSION['installer_temp_ftp']['path']);
        $ftp->unlink('install.php');
        foreach ($databases as $key => $dummy) {
            $ftp->unlink('install_' . DB_SCRIPT_VERSION . '_' . $key . '.sql');
        }
        $ftp->close();
        unset($_SESSION['installer_temp_ftp']);
    } else {
        @unlink(__FILE__);
        foreach ($databases as $key => $dummy) {
            @unlink(dirname(__FILE__) . '/install_' . DB_SCRIPT_VERSION . '_' . $key . '.sql');
        }
    }
    // Now just redirect to a blank.png...
    header('Location: http://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT']) . dirname($_SERVER['PHP_SELF']) . '/themes/default/images/blank.png');
    exit;
}
Example #4
0
/**
 * Get the contents of a URL, irrespective of allow_url_fopen.
 *
 * - reads the contents of an http or ftp address and retruns the page in a string
 * - will accept up to 3 page redirections (redirectio_level in the function call is private)
 * - if post_data is supplied, the value and lenght is posted to the given url as form data
 * - URL must be supplied in lowercase
 *
 * @package Packages
 * @param string $url
 * @param string $post_data = ''
 * @param bool $keep_alive = false
 * @param int $redirection_level = 2
 * @return string
 */
function fetch_web_data($url, $post_data = '', $keep_alive = false, $redirection_level = 2)
{
    global $webmaster_email;
    static $keep_alive_dom = null, $keep_alive_fp = null;
    preg_match('~^(http|ftp)(s)?://([^/:]+)(:(\\d+))?(.+)$~', $url, $match);
    // An FTP url. We should try connecting and RETRieving it...
    if (empty($match[1])) {
        return false;
    } elseif ($match[1] == 'ftp') {
        // Include the file containing the Ftp_Connection class.
        require_once SOURCEDIR . '/FtpConnection.class.php';
        // Establish a connection and attempt to enable passive mode.
        $ftp = new Ftp_Connection(($match[2] ? 'ssl://' : '') . $match[3], empty($match[5]) ? 21 : $match[5], 'anonymous', $webmaster_email);
        if ($ftp->error !== false || !$ftp->passive()) {
            return false;
        }
        // I want that one *points*!
        fwrite($ftp->connection, 'RETR ' . $match[6] . "\r\n");
        // Since passive mode worked (or we would have returned already!) open the connection.
        $fp = @fsockopen($ftp->pasv['ip'], $ftp->pasv['port'], $err, $err, 5);
        if (!$fp) {
            return false;
        }
        // The server should now say something in acknowledgement.
        $ftp->check_response(150);
        $data = '';
        while (!feof($fp)) {
            $data .= fread($fp, 4096);
        }
        fclose($fp);
        // All done, right?  Good.
        $ftp->check_response(226);
        $ftp->close();
    } elseif (isset($match[1]) && $match[1] === 'http' && function_exists('curl_init')) {
        // Include the file containing the Curl_Fetch_Webdata class.
        require_once SOURCEDIR . '/CurlFetchWebdata.class.php';
        $fetch_data = new Curl_Fetch_Webdata(array(), $redirection_level);
        $fetch_data->get_url_data($url, $post_data);
        // no errors and a 200 result, then we have a good dataset, well we at least have data ;)
        if ($fetch_data->result('code') == 200 && !$fetch_data->result('error')) {
            $data = $fetch_data->result('body');
        } else {
            return false;
        }
    } elseif (isset($match[1]) && $match[1] == 'http') {
        if ($keep_alive && $match[3] == $keep_alive_dom) {
            $fp = $keep_alive_fp;
        }
        if (empty($fp)) {
            // Open the socket on the port we want...
            $fp = @fsockopen(($match[2] ? 'ssl://' : '') . $match[3], empty($match[5]) ? $match[2] ? 443 : 80 : $match[5], $err, $err, 5);
            if (!$fp) {
                return false;
            }
        }
        if ($keep_alive) {
            $keep_alive_dom = $match[3];
            $keep_alive_fp = $fp;
        }
        // I want this, from there, and I'm not going to be bothering you for more (probably.)
        if (empty($post_data)) {
            fwrite($fp, 'GET ' . ($match[6] !== '/' ? str_replace(' ', '%20', $match[6]) : '') . ' HTTP/1.0' . "\r\n");
            fwrite($fp, 'Host: ' . $match[3] . (empty($match[5]) ? $match[2] ? ':443' : '' : ':' . $match[5]) . "\r\n");
            fwrite($fp, 'User-Agent: PHP/ELK' . "\r\n");
            if ($keep_alive) {
                fwrite($fp, 'Connection: Keep-Alive' . "\r\n\r\n");
            } else {
                fwrite($fp, 'Connection: close' . "\r\n\r\n");
            }
        } else {
            fwrite($fp, 'POST ' . ($match[6] !== '/' ? $match[6] : '') . ' HTTP/1.0' . "\r\n");
            fwrite($fp, 'Host: ' . $match[3] . (empty($match[5]) ? $match[2] ? ':443' : '' : ':' . $match[5]) . "\r\n");
            fwrite($fp, 'User-Agent: PHP/ELK' . "\r\n");
            if ($keep_alive) {
                fwrite($fp, 'Connection: Keep-Alive' . "\r\n");
            } else {
                fwrite($fp, 'Connection: close' . "\r\n");
            }
            fwrite($fp, 'Content-Type: application/x-www-form-urlencoded' . "\r\n");
            fwrite($fp, 'Content-Length: ' . strlen($post_data) . "\r\n\r\n");
            fwrite($fp, $post_data);
        }
        $response = fgets($fp, 768);
        // Redirect in case this location is permanently or temporarily moved.
        if ($redirection_level < 3 && preg_match('~^HTTP/\\S+\\s+30[127]~i', $response) === 1) {
            $header = '';
            $location = '';
            while (!feof($fp) && trim($header = fgets($fp, 4096)) != '') {
                if (strpos($header, 'Location:') !== false) {
                    $location = trim(substr($header, strpos($header, ':') + 1));
                }
            }
            if (empty($location)) {
                return false;
            } else {
                if (!$keep_alive) {
                    fclose($fp);
                }
                return fetch_web_data($location, $post_data, $keep_alive, $redirection_level + 1);
            }
        } elseif (preg_match('~^HTTP/\\S+\\s+20[01]~i', $response) === 0) {
            return false;
        }
        // Skip the headers...
        while (!feof($fp) && trim($header = fgets($fp, 4096)) != '') {
            if (preg_match('~content-length:\\s*(\\d+)~i', $header, $match) != 0) {
                $content_length = $match[1];
            } elseif (preg_match('~connection:\\s*close~i', $header) != 0) {
                $keep_alive_dom = null;
                $keep_alive = false;
            }
            continue;
        }
        $data = '';
        if (isset($content_length)) {
            while (!feof($fp) && strlen($data) < $content_length) {
                $data .= fread($fp, $content_length - strlen($data));
            }
        } else {
            while (!feof($fp)) {
                $data .= fread($fp, 4096);
            }
        }
        if (!$keep_alive) {
            fclose($fp);
        }
    } else {
        // Umm, this shouldn't happen?
        trigger_error('fetch_web_data(): Bad URL', E_USER_NOTICE);
        $data = false;
    }
    return $data;
}
 /**
  * Handling function for the backup stuff.
  *
  * - It requires an administrator and the session hash by post.
  * - This method simply forwards to DumpDatabase2().
  */
 public function action_backup_display()
 {
     global $context, $txt, $user_info;
     validateToken('admin-maint');
     // Administrators only!
     if (!allowedTo('admin_forum')) {
         fatal_lang_error('no_dump_database', 'critical');
     }
     checkSession('post');
     if (empty($iknowitmaybeunsafe)) {
         require_once SUBSDIR . '/FtpConnection.class.php';
         $ftp = new Ftp_Connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']);
         if ($ftp->error === false) {
             // I know, I know... but a lot of people want to type /home/xyz/... which is wrong, but logical.
             if (!$ftp->chdir($_POST['ftp_path'])) {
                 $ftp_error = $ftp->error;
                 $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path']));
             }
         }
         // If we had an error...
         if ($ftp->error !== false) {
             loadLanguage('Packages');
             $ftp_error = $ftp->last_message === null ? isset($txt['package_ftp_' . $ftp->error]) ? $txt['package_ftp_' . $ftp->error] : '' : $ftp->last_message;
             // Fill the boxes for a FTP connection with data from the previous attempt
             $context['package_ftp'] = array('form_elements_only' => 1, 'server' => $_POST['ftp_server'], 'port' => $_POST['ftp_port'], 'username' => $_POST['ftp_username'], 'path' => $_POST['ftp_path'], 'error' => empty($ftp_error) ? null : $ftp_error);
             return $this->action_database();
         }
     }
     require_once SUBSDIR . '/Admin.subs.php';
     emailAdmins('admin_backup_database', array('BAK_REALNAME' => $user_info['name']));
     logAction('database_backup', array('member' => $user_info['id']), 'admin');
     require_once SOURCEDIR . '/DumpDatabase.php';
     DumpDatabase2();
 }
 /**
  * This method attempts to chmod packages and installed.list
  *
  * - uses FTP if necessary.
  * - It sets the $context['package_download_broken'] status for the template.
  * - Used by package servers pages.
  */
 public function ftp_connect()
 {
     global $context, $modSettings;
     // Try to chmod from PHP first
     @chmod(BOARDDIR . '/packages', 0777);
     @chmod(BOARDDIR . '/packages/installed.list', 0777);
     $unwritable = !is_writable(BOARDDIR . '/packages') || !is_writable(BOARDDIR . '/packages/installed.list');
     // Let's initialize $context
     $context['package_ftp'] = array('server' => '', 'port' => '', 'username' => '', 'path' => '', 'error' => '');
     if ($unwritable) {
         // Are they connecting to their FTP account already?
         if (isset($_POST['ftp_username'])) {
             require_once SUBSDIR . '/FtpConnection.class.php';
             $ftp = new Ftp_Connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']);
             if ($ftp->error === false) {
                 // I know, I know... but a lot of people want to type /home/xyz/... which is wrong, but logical.
                 if (!$ftp->chdir($_POST['ftp_path'])) {
                     $ftp_error = $ftp->error;
                     $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path']));
                 }
             }
         }
         // No attempt yet, or we had an error last time
         if (!isset($ftp) || $ftp->error !== false) {
             // Maybe we didn't even try yet
             if (!isset($ftp)) {
                 require_once SUBSDIR . '/FtpConnection.class.php';
                 $ftp = new Ftp_Connection(null);
             } elseif ($ftp->error !== false && !isset($ftp_error)) {
                 $ftp_error = $ftp->last_message === null ? '' : $ftp->last_message;
             }
             list($username, $detect_path, $found_path) = $ftp->detect_path(BOARDDIR);
             if ($found_path || !isset($_POST['ftp_path'])) {
                 $_POST['ftp_path'] = $detect_path;
             }
             if (!isset($_POST['ftp_username'])) {
                 $_POST['ftp_username'] = $username;
             }
             // Fill the boxes for a FTP connection with data from the previous attempt too, if any
             $context['package_ftp'] = array('server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : (isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost'), 'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : (isset($modSettings['package_port']) ? $modSettings['package_port'] : '21'), 'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : (isset($modSettings['package_username']) ? $modSettings['package_username'] : ''), 'path' => $_POST['ftp_path'], 'error' => empty($ftp_error) ? null : $ftp_error);
             // Announce the template it's time to display the ftp connection box.
             $context['package_download_broken'] = true;
         } else {
             // FTP connection has succeeded
             $context['package_download_broken'] = false;
             // Try to chmod packages folder and our list file.
             $ftp->chmod('packages', 0777);
             $ftp->chmod('packages/installed.list', 0777);
             $ftp->close();
         }
     }
 }