芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/public_html/sommatv/lib/Helper/Install.php
. */ namespace Xibo\Helper; use Xibo\Exception\InstallationError; use Xibo\Service\ConfigService; use Xibo\Service\SanitizerServiceInterface; use Xibo\Service\SanitizeService; use Xibo\Storage\StorageServiceInterface; /** * Class Install * @package Xibo\Helper */ class Install { // DB Details public $db_create; public $db_admin_user; public $db_admin_pass; public $new_db_host; public $new_db_user; public $new_db_pass; public $new_db_name; public $existing_db_host; public $existing_db_user; public $existing_db_pass; public $existing_db_name; /** @var SanitizerServiceInterface */ private $sanitizer; /** * Install constructor. * @param SanitizeService $sanitizer */ public function __construct($sanitizer) { $this->sanitizer = $sanitizer; } /** * @return array */ public function Step1() { return [ 'config' => new ConfigService() ]; } /** * @return array */ public function Step2() { return []; } /** * @param StorageServiceInterface $store * @throws InstallationError */ public function Step3($store) { // Have we been told to create a new database $this->db_create = $this->sanitizer->getInt('db_create'); // Check all parameters have been specified $this->db_admin_user = $this->sanitizer->getString('admin_username'); $this->db_admin_pass = $this->sanitizer->getString('admin_password'); $this->new_db_host = $this->sanitizer->getString('host'); $this->new_db_user = $this->sanitizer->getString('db_username'); $this->new_db_pass = $this->sanitizer->getString('db_password'); $this->new_db_name = $this->sanitizer->getString('db_name'); $this->existing_db_host = $this->sanitizer->getString('existing_host'); $this->existing_db_user = $this->sanitizer->getString('existing_db_username'); $this->existing_db_pass = $this->sanitizer->getString('existing_db_password'); $this->existing_db_name = $this->sanitizer->getString('existing_db_name'); // If an administrator user name / password has been specified then we should create a new DB if ($this->db_create == 1) { // Check details for a new database if ($this->new_db_host == '') throw new InstallationError(__('Please provide a database host. This is usually localhost.')); if ($this->new_db_user == '') throw new InstallationError(__('Please provide a user for the new database.')); if ($this->new_db_pass == '') throw new InstallationError(__('Please provide a password for the new database.')); if ($this->new_db_name == '') throw new InstallationError(__('Please provide a name for the new database.')); if ($this->db_admin_user == '') throw new InstallationError(__('Please provide an admin user name.')); // Try to create the new database // Try and connect using these details and create the new database try { $store->connect($this->new_db_host, $this->db_admin_user, $this->db_admin_pass); } catch (\PDOException $e) { throw new InstallationError(sprintf(__('Could not connect to MySQL with the administrator details. Please check and try again. Error Message = [%s]'), $e->getMessage())); } // Try to create the new database try { $dbh = $store->getConnection(); $dbh->exec(sprintf('CREATE DATABASE `%s` CHARACTER SET utf8 COLLATE utf8_general_ci', $this->new_db_name)); } catch (\PDOException $e) { throw new InstallationError(sprintf(__('Could not create a new database with the administrator details [%s]. Please check and try again. Error Message = [%s]'), $this->db_admin_user, $e->getMessage())); } // Try to create the new user try { $dbh = $store->getConnection(); // Create the user and grant privileges if ($this->new_db_host == 'localhost') { $sql = sprintf('GRANT ALL PRIVILEGES ON `%s`.* to %s@%s IDENTIFIED BY %s', $this->new_db_name, $dbh->quote($this->new_db_user), $dbh->quote($this->new_db_host), $dbh->quote($this->new_db_pass) ); $dbh->exec($sql); } else { $sql = sprintf('GRANT ALL PRIVILEGES ON `%s`.* to %s@\'%%\' IDENTIFIED BY %s', $this->new_db_name, $dbh->quote($this->new_db_user), $dbh->quote($this->new_db_pass) ); $dbh->exec($sql); } // Flush $dbh->exec('FLUSH PRIVILEGES'); } catch (\PDOException $e) { throw new InstallationError(sprintf(__('Could not create a new user with the administrator details. Please check and try again. Error Message = [%s]. SQL = [%s].'), $e->getMessage(), $sql)); } // Set our DB details $this->existing_db_host = $this->new_db_host; $this->existing_db_user = $this->new_db_user; $this->existing_db_pass = $this->new_db_pass; $this->existing_db_name = $this->new_db_name; // Close the connection $store->close(); } else { // Check details for a new database if ($this->existing_db_host == '') throw new InstallationError(__('Please provide a database host. This is usually localhost.')); if ($this->existing_db_user == '') throw new InstallationError(__('Please provide a user for the existing database.')); if ($this->existing_db_pass == '') throw new InstallationError(__('Please provide a password for the existing database.')); if ($this->existing_db_name == '') throw new InstallationError(__('Please provide a name for the existing database.')); } // Try and make a connection with this database try { $store->connect($this->existing_db_host, $this->existing_db_user, $this->existing_db_pass, $this->existing_db_name); } catch (\PDOException $e) { throw new InstallationError(sprintf(__('Could not connect to MySQL with the administrator details. Please check and try again. Error Message = [%s]'), $e->getMessage())); } // We should have a database that we can access and populate with our tables. $sql_files = array('structure.sql', 'data.sql', 'constraints.sql'); $sqlStatementCount = 0; $sql_file = ''; $sql = ''; try { $dbh = $store->getConnection(); foreach ($sql_files as $filename) { $delimiter = ';'; $sql_file = @file_get_contents(PROJECT_ROOT . '/install/master/' . $filename); $sql_file = Install::remove_remarks($sql_file); $sql_file = Install::split_sql_file($sql_file, $delimiter); foreach ($sql_file as $sql) { $sqlStatementCount++; $dbh->exec($sql); } } } catch (\PDOException $e) { throw new InstallationError(sprintf(__('An error occurred populating the database. Statement number: %d. Error Message = [%s]. File = [%s]. SQL = [%s].'), $sqlStatementCount, $e->getMessage(), $filename, $sql)); } // Write out a new settings.php $fh = fopen(PROJECT_ROOT . '/web/settings.php', 'wt'); if (!$fh) throw new InstallationError(__('Unable to write to settings.php. We already checked this was possible earlier, so something changed.')); // Generate a secret key for various reasons $secretKey = Install::generateSecret(); // Escape the password before we write it to disk $dbh = $store->getConnection(); $existing_db_pass = addslashes($this->existing_db_pass); $settings = <<
" . __("Please press the back button in your browser.")); global \$dbhost; global \$dbuser; global \$dbpass; global \$dbname; \$dbhost = '$this->existing_db_host'; \$dbuser = '$this->existing_db_user'; \$dbpass = '$existing_db_pass'; \$dbname = '$this->existing_db_name'; define('SECRET_KEY', '$secretKey'); // Additional Monolog handlers/processors to be registered // \$logHandlers = []; // \$logProcessors = []; // Additional Middleware // \$middleware = []; // \$authentication = ; END; if (!fwrite($fh, $settings)) throw new InstallationError(__('Unable to write to settings.php. We already checked this was possible earlier, so something changed.')); fclose($fh); // If we get here, we want to move on to the next step. // This is handled by the calling function (i.e. there is no output from this call, we just reload and move on) } /** * @return array */ public function Step4() { return []; } /** * @param StorageServiceInterface $store * @throws InstallationError */ public function Step5($store) { // Configure the user account $username = $this->sanitizer->getString('admin_username'); $password = $this->sanitizer->getString('admin_password'); if ($username == '') throw new InstallationError(__('Missing the admin username.')); if ($password == '') throw new InstallationError(__('Missing the admin password.')); // Update user id 1 with these details. try { $dbh = $store->getConnection(); $sth = $dbh->prepare('UPDATE `user` SET UserName = :username, UserPassword = :password WHERE UserID = 1 LIMIT 1'); $sth->execute(array( 'username' => $username, 'password' => md5($password) )); // Update group ID 3 with the user name $sth = $dbh->prepare('UPDATE `group` SET `group` = :username WHERE groupId = 3 LIMIT 1'); $sth->execute(array( 'username' => $username )); } catch (InstallationError $e) { throw new InstallationError(sprintf(__('Unable to set the user details. This is an unexpected error, please contact support. Error Message = [%s]'), $e->getMessage())); } } /** * @return array */ public function Step6() { return [ 'serverKey' => Install::generateSecret(6) ]; } /** * @param StorageServiceInterface $store * @throws InstallationError */ public function Step7($store) { $server_key = $this->sanitizer->getString('server_key'); $library_location = $this->sanitizer->getString('library_location'); $stats = $this->sanitizer->getCheckbox('stats'); if ($server_key == '') throw new InstallationError(__('Missing the server key.')); if ($library_location == '') throw new InstallationError(__('Missing the library location.')); // Remove trailing white space from the path given. $library_location = trim($library_location); if (!is_dir($library_location)) { // Make sure they haven't given a file as the library location if (is_file($library_location)) throw new InstallationError(__('A file exists with the name you gave for the Library Location. Please choose another location')); // Directory does not exist. Attempt to make it // Using mkdir recursively, so it will attempt to make any // intermediate folders required. if (!mkdir($library_location, 0755, true)) { throw new InstallationError(__('Could not create the Library Location directory for you. Please ensure the webserver has permission to create a folder in this location, or create the folder manually and grant permission for the webserver to write to the folder.')); } } // Is library_location writable? if (!is_writable($library_location)) throw new InstallationError(__('The Library Location you gave is not writable by the webserver. Please fix the permissions and try again.')); // Is library_location empty? if (count(Install::ls("*", $library_location, true)) > 0) throw new InstallationError(__('The Library Location you gave is not empty. Please give the location of an empty folder')); // Check if the user has added a trailing slash. If not, add one. if (!((substr($library_location, -1) == '/') || (substr($library_location, -1) == '\\'))) { $library_location = $library_location . '/'; } try { $dbh = $store->getConnection(); // Library Location $sth = $dbh->prepare('UPDATE `setting` SET `value` = :value WHERE `setting`.`setting` = \'LIBRARY_LOCATION\' LIMIT 1'); $sth->execute(array('value' => $library_location)); // Server Key $sth = $dbh->prepare('UPDATE `setting` SET `value` = :value WHERE `setting`.`setting` = \'SERVER_KEY\' LIMIT 1'); $sth->execute(array('value' => $server_key)); // Default Time zone $sth = $dbh->prepare('UPDATE `setting` SET `value` = :value WHERE `setting`.`setting` = \'defaultTimezone\' LIMIT 1'); $sth->execute(array('value' => date_default_timezone_get())); // Phone Home $sth = $dbh->prepare('UPDATE `setting` SET `value` = :value WHERE `setting`.`setting` = \'PHONE_HOME\' LIMIT 1'); $sth->execute(array('value' => (($stats == 1) ? 'On' : 'Off'))); // Phone Home Key $sth = $dbh->prepare('UPDATE `setting` SET `value` = :value WHERE `setting`.`setting` = \'PHONE_HOME_KEY\' LIMIT 1'); $sth->execute(array('value' => md5(uniqid(rand(), true)))); } catch (\PDOException $e) { throw new InstallationError(sprintf(__('An error occurred updating these settings. This is an unexpected error, please contact support. Error Message = [%s]'), $e->getMessage())); } // Delete install if (!@unlink('index.php')) throw new InstallationError(__("Unable to delete install/index.php. Please ensure the web server has permission to unlink this file and retry")); } /* * Third party classes */ // Taken from http://forums.devshed.com/php-development-5/php-wont-load-sql-from-file-515902.html // By Crackster /** * remove_remarks will strip the sql comment lines out of an uploaded sql file */ public static function remove_remarks($sql) { $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^[-].*$/m', "\n", $sql)); $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql)); return $sql; } // Taken from http://forums.devshed.com/php-development-5/php-wont-load-sql-from-file-515902.html // By Crackster /** * split_sql_file will split an uploaded sql file into single sql statements. * Note: expects trim() to have already been run on $sql. */ public static function split_sql_file($sql, $delimiter) { $sql = str_replace("\r", '', $sql); $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); $data = array_map('trim', $data); // The empty case $end_data = end($data); if (empty($end_data)) { unset($data[key($data)]); } return $data; } /** * This function will take a pattern and a folder as the argument and go thru it(recursively if needed)and return the list of * all files in that folder. * Link : http://www.bin-co.com/php/scripts/filesystem/ls/ * License : BSD * Arguments : $pattern - The pattern to look out for [OPTIONAL] * $folder - The path of the directory of which's directory list you want [OPTIONAL] * $recursivly - The funtion will traverse the folder tree recursivly if this is true. Defaults to false. [OPTIONAL] * $options - An array of values 'return_files' or 'return_folders' or both * Returns : A flat list with the path of all the files(no folders) that matches the condition given. */ public static function ls($pattern = "*", $folder = "", $recursivly = false, $options = array('return_files', 'return_folders')) { if ($folder) { $current_folder = realpath('.'); if (in_array('quiet', $options)) { // If quiet is on, we will suppress the 'no such folder' error if (!file_exists($folder)) return array(); } if (!chdir($folder)) return array(); } $get_files = in_array('return_files', $options); $get_folders = in_array('return_folders', $options); $both = array(); $folders = array(); // Get the all files and folders in the given directory. if ($get_files) $both = glob($pattern, GLOB_BRACE + GLOB_MARK); if ($recursivly or $get_folders) $folders = glob("*", GLOB_ONLYDIR + GLOB_MARK); //If a pattern is specified, make sure even the folders match that pattern. $matching_folders = array(); if ($pattern !== '*') $matching_folders = glob($pattern, GLOB_ONLYDIR + GLOB_MARK); //Get just the files by removing the folders from the list of all files. $all = array_values(array_diff($both, $folders)); if ($recursivly or $get_folders) { foreach ($folders as $this_folder) { if ($get_folders) { //If a pattern is specified, make sure even the folders match that pattern. if ($pattern !== '*') { if (in_array($this_folder, $matching_folders)) array_push($all, $this_folder); } else array_push($all, $this_folder); } if ($recursivly) { // Continue calling this function for all the folders $deep_items = Install::ls($pattern, $this_folder, $recursivly, $options); # :RECURSION: foreach ($deep_items as $item) { array_push($all, $this_folder . $item); } } } } if ($folder) chdir($current_folder); return $all; } /** * @param int $length * @return string */ public static function generateSecret($length = 12) { # Generates a random 12 character alphanumeric string to use as a salt mt_srand((double)microtime() * 1000000); $key = ""; for ($i = 0; $i < $length; $i++) { $c = mt_rand(0, 2); if ($c == 0) { $key .= chr(mt_rand(65, 90)); } elseif ($c == 1) { $key .= chr(mt_rand(97, 122)); } else { $key .= chr(mt_rand(48, 57)); } } return $key; } }