From 9b50e98927e7374f65bd2b1debc413c0d4fe3a93 Mon Sep 17 00:00:00 2001 From: Shish Date: Mon, 27 Jan 2020 17:47:28 +0000 Subject: [PATCH] move some installer bits to util.php --- core/_install.php | 244 ++++---------------------------------------- core/exceptions.php | 20 ++++ core/util.php | 187 +++++++++++++++++++++++++++++++++ tests/bootstrap.php | 13 +-- 4 files changed, 232 insertions(+), 232 deletions(-) diff --git a/core/_install.php b/core/_install.php index d4a623d4..b3529efd 100644 --- a/core/_install.php +++ b/core/_install.php @@ -67,6 +67,7 @@ require_once "core/exceptions.php"; require_once "core/cacheengine.php"; require_once "core/dbengine.php"; require_once "core/database.php"; +require_once "core/util.php"; if (is_readable("data/config/shimmie.conf.php")) { die("Shimmie is already installed."); @@ -76,29 +77,6 @@ do_install(); // TODO: Can some of these be pushed into "core/???.inc.php" ? -function check_gd_version(): int -{ - $gdversion = 0; - - if (function_exists('gd_info')) { - $gd_info = gd_info(); - if (substr_count($gd_info['GD Version'], '2.')) { - $gdversion = 2; - } elseif (substr_count($gd_info['GD Version'], '1.')) { - $gdversion = 1; - } - } - - return $gdversion; -} - -function check_im_version(): int -{ - $convert_check = exec("convert"); - - return (empty($convert_check) ? 0 : 1); -} - function do_install() { if (file_exists("data/config/auto_install.conf.php")) { @@ -115,7 +93,23 @@ function do_install() define("CACHE_DSN", null); define("DATABASE_KA", true); - install_process(); + try { + create_dirs(); + create_tables(new Database()); + write_config(); + } catch (InstallerException $e) { + print << +

Shimmie Installer

+

{$e->title}

+
+ {$e->body} +

+
+ +EOD; + exit($e->code); + } } function ask_questions() @@ -231,208 +225,6 @@ function ask_questions() EOD; } - -/** - * This is where the install really takes place. - */ -function install_process() -{ - build_dirs(); - create_tables(); - insert_defaults(); - write_config(); -} - -function create_tables() -{ - try { - $db = new Database(); - - if ($db->count_tables() > 0) { - print << -

Shimmie Installer

-

Warning: The Database schema is not empty!

-
-

Please ensure that the database you are installing Shimmie with is empty before continuing.

-

Once you have emptied the database of any tables, please hit 'refresh' to continue.

-

-
- -EOD; - exit(2); - } - - $db->create_table("aliases", " - oldtag VARCHAR(128) NOT NULL, - newtag VARCHAR(128) NOT NULL, - PRIMARY KEY (oldtag) - "); - $db->execute("CREATE INDEX aliases_newtag_idx ON aliases(newtag)", []); - - $db->create_table("config", " - name VARCHAR(128) NOT NULL, - value TEXT, - PRIMARY KEY (name) - "); - $db->create_table("users", " - id SCORE_AIPK, - name VARCHAR(32) UNIQUE NOT NULL, - pass VARCHAR(250), - joindate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - class VARCHAR(32) NOT NULL DEFAULT 'user', - email VARCHAR(128) - "); - $db->execute("CREATE INDEX users_name_idx ON users(name)", []); - - $db->create_table("images", " - id SCORE_AIPK, - owner_id INTEGER NOT NULL, - owner_ip SCORE_INET NOT NULL, - filename VARCHAR(64) NOT NULL, - filesize INTEGER NOT NULL, - hash CHAR(32) UNIQUE NOT NULL, - ext CHAR(4) NOT NULL, - source VARCHAR(255), - width INTEGER NOT NULL, - height INTEGER NOT NULL, - posted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, - FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT - "); - $db->execute("CREATE INDEX images_owner_id_idx ON images(owner_id)", []); - $db->execute("CREATE INDEX images_width_idx ON images(width)", []); - $db->execute("CREATE INDEX images_height_idx ON images(height)", []); - $db->execute("CREATE INDEX images_hash_idx ON images(hash)", []); - - $db->create_table("tags", " - id SCORE_AIPK, - tag VARCHAR(64) UNIQUE NOT NULL, - count INTEGER NOT NULL DEFAULT 0 - "); - $db->execute("CREATE INDEX tags_tag_idx ON tags(tag)", []); - - $db->create_table("image_tags", " - image_id INTEGER NOT NULL, - tag_id INTEGER NOT NULL, - UNIQUE(image_id, tag_id), - FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE - "); - $db->execute("CREATE INDEX images_tags_image_id_idx ON image_tags(image_id)", []); - $db->execute("CREATE INDEX images_tags_tag_id_idx ON image_tags(tag_id)", []); - - $db->execute("INSERT INTO config(name, value) VALUES('db_version', 11)"); - $db->commit(); - } catch (PDOException $e) { - handle_db_errors(true, "An error occurred while trying to create the database tables necessary for Shimmie.", $e->getMessage(), 3); - } catch (Exception $e) { - handle_db_errors(false, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 4); - } -} - -function insert_defaults() -{ - try { - $db = new Database(); - - $db->execute("INSERT INTO users(name, pass, joindate, class) VALUES(:name, :pass, now(), :class)", ["name" => 'Anonymous', "pass" => null, "class" => 'anonymous']); - $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'anon_id', "value" => $db->get_last_insert_id('users_id_seq')]); - - if (check_im_version() > 0) { - $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'thumb_engine', "value" => 'convert']); - } - $db->commit(); - } catch (PDOException $e) { - handle_db_errors(true, "An error occurred while trying to insert data into the database.", $e->getMessage(), 5); - } catch (Exception $e) { - handle_db_errors(false, "An unknown error occurred while trying to insert data into the database.", $e->getMessage(), 6); - } -} - -function build_dirs() -{ - $data_exists = file_exists("data") || mkdir("data"); - $data_writable = is_writable("data") || chmod("data", 0755); - - if (!$data_exists || !$data_writable) { - print " -
-

Shimmie Installer

-

Directory Permissions Error:

-
-

Shimmie needs to have a 'data' folder in its directory, writable by the PHP user.

-

If you see this error, if probably means the folder is owned by you, and it needs to be writable by the web server.

-

PHP reports that it is currently running as user: ".$_ENV["USER"]." (". $_SERVER["USER"] .")

-

Once you have created this folder and / or changed the ownership of the shimmie folder, hit 'refresh' to continue.

-

-
-
- "; - exit(7); - } -} - -function write_config() -{ - $file_content = '<' . '?php' . "\n" . - "define('DATABASE_DSN', '".DATABASE_DSN."');\n" . - '?' . '>'; - - if (!file_exists("data/config")) { - mkdir("data/config", 0755, true); - } - - if (file_put_contents("data/config/shimmie.conf.php", $file_content, LOCK_EX)) { - header("Location: index.php"); - print << -

Shimmie Installer

-

Things are OK \o/

-
-

If you aren't redirected, click here to Continue. -

- -EOD; - } else { - $h_file_content = htmlentities($file_content); - print << -

Shimmie Installer

-

File Permissions Error:

-
- The web server isn't allowed to write to the config file; please copy - the text below, save it as 'data/config/shimmie.conf.php', and upload it into the shimmie - folder manually. Make sure that when you save it, there is no whitespace - before the "<?php" or after the "?>" - -

- -

Once done, click here to Continue. -

-

- -EOD; - } - echo "\n"; -} - -function handle_db_errors(bool $isPDO, string $errorMessage1, string $errorMessage2, int $exitCode) -{ - $errorMessage1Extra = ($isPDO ? "Please check and ensure that the database configuration options are all correct." : "Please check the server log files for more information."); - print << -

Shimmie Installer

-

Unknown Error:

-
-

{$errorMessage1}

-

{$errorMessage1Extra}

-

{$errorMessage2}

-
- -EOD; - exit($exitCode); -} ?> diff --git a/core/exceptions.php b/core/exceptions.php index bc975d5c..1c6c8ac7 100644 --- a/core/exceptions.php +++ b/core/exceptions.php @@ -21,6 +21,26 @@ class SCoreException extends RuntimeException } } +class InstallerException extends RuntimeException +{ + /** @var string */ + public $title; + + /** @var string */ + public $body; + + /** @var int */ + public $code; + + public function __construct(string $title, string $body, int $code) + { + parent::construct($title); + $this->title = $title; + $this->body = $body; + $this->code = $code; + } +} + /** * Class PermissionDeniedException * diff --git a/core/util.php b/core/util.php index b3c78264..65f7241d 100644 --- a/core/util.php +++ b/core/util.php @@ -130,6 +130,36 @@ function get_memory_limit(): int } } +/** + * Check if PHP has the GD library installed + */ +function check_gd_version(): int +{ + $gdversion = 0; + + if (function_exists('gd_info')) { + $gd_info = gd_info(); + if (substr_count($gd_info['GD Version'], '2.')) { + $gdversion = 2; + } elseif (substr_count($gd_info['GD Version'], '1.')) { + $gdversion = 1; + } + } + + return $gdversion; +} + +/** + * Check whether ImageMagick's `convert` command + * is installed and working + */ +function check_im_version(): int +{ + $convert_check = exec("convert"); + + return (empty($convert_check) ? 0 : 1); +} + /** * Get the currently active IP, masked to make it not change when the last * octet or two change, for use in session cookies and such @@ -605,6 +635,163 @@ function _get_query(): string } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ +* Things used in the installer + unit tests * +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +function create_dirs() +{ + $data_exists = file_exists("data") || mkdir("data"); + $data_writable = is_writable("data") || chmod("data", 0755); + + if (!$data_exists || !$data_writable) { + throw new InstallerException( + "Directory Permissions Error:", + "

Shimmie needs to have a 'data' folder in its directory, writable by the PHP user.

+

If you see this error, if probably means the folder is owned by you, and it needs to be writable by the web server.

+

PHP reports that it is currently running as user: ".$_ENV["USER"]." (". $_SERVER["USER"] .")

+

Once you have created this folder and / or changed the ownership of the shimmie folder, hit 'refresh' to continue.

", + 7 + ); + } +} + +function create_tables(Database $db) +{ + try { + if ($db->count_tables() > 0) { + throw new InstallerException( + "Warning: The Database schema is not empty!", + "

Please ensure that the database you are installing Shimmie with is empty before continuing.

+

Once you have emptied the database of any tables, please hit 'refresh' to continue.

", + 2 + ); + } + + $db->create_table("aliases", " + oldtag VARCHAR(128) NOT NULL, + newtag VARCHAR(128) NOT NULL, + PRIMARY KEY (oldtag) + "); + $db->execute("CREATE INDEX aliases_newtag_idx ON aliases(newtag)", []); + + $db->create_table("config", " + name VARCHAR(128) NOT NULL, + value TEXT, + PRIMARY KEY (name) + "); + $db->create_table("users", " + id SCORE_AIPK, + name VARCHAR(32) UNIQUE NOT NULL, + pass VARCHAR(250), + joindate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + class VARCHAR(32) NOT NULL DEFAULT 'user', + email VARCHAR(128) + "); + $db->execute("CREATE INDEX users_name_idx ON users(name)", []); + + $db->execute("INSERT INTO users(name, pass, joindate, class) VALUES(:name, :pass, now(), :class)", ["name" => 'Anonymous', "pass" => null, "class" => 'anonymous']); + $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'anon_id', "value" => $db->get_last_insert_id('users_id_seq')]); + + if (check_im_version() > 0) { + $db->execute("INSERT INTO config(name, value) VALUES(:name, :value)", ["name" => 'thumb_engine', "value" => 'convert']); + } + + $db->create_table("images", " + id SCORE_AIPK, + owner_id INTEGER NOT NULL, + owner_ip SCORE_INET NOT NULL, + filename VARCHAR(64) NOT NULL, + filesize INTEGER NOT NULL, + hash CHAR(32) UNIQUE NOT NULL, + ext CHAR(4) NOT NULL, + source VARCHAR(255), + width INTEGER NOT NULL, + height INTEGER NOT NULL, + posted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + locked SCORE_BOOL NOT NULL DEFAULT SCORE_BOOL_N, + FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT + "); + $db->execute("CREATE INDEX images_owner_id_idx ON images(owner_id)", []); + $db->execute("CREATE INDEX images_width_idx ON images(width)", []); + $db->execute("CREATE INDEX images_height_idx ON images(height)", []); + $db->execute("CREATE INDEX images_hash_idx ON images(hash)", []); + + $db->create_table("tags", " + id SCORE_AIPK, + tag VARCHAR(64) UNIQUE NOT NULL, + count INTEGER NOT NULL DEFAULT 0 + "); + $db->execute("CREATE INDEX tags_tag_idx ON tags(tag)", []); + + $db->create_table("image_tags", " + image_id INTEGER NOT NULL, + tag_id INTEGER NOT NULL, + UNIQUE(image_id, tag_id), + FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE, + FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE + "); + $db->execute("CREATE INDEX images_tags_image_id_idx ON image_tags(image_id)", []); + $db->execute("CREATE INDEX images_tags_tag_id_idx ON image_tags(tag_id)", []); + + $db->execute("INSERT INTO config(name, value) VALUES('db_version', 11)"); + $db->commit(); + } catch (PDOException $e) { + throw new InstallerException( + "PDO Error:", + "

An error occurred while trying to create the database tables necessary for Shimmie.

+

Please check and ensure that the database configuration options are all correct.

+

{$e->getMessage()}

", + 3 + ); + } catch (Exception $e) { + throw new InstallerException( + "Unknown Error:", + "

An unknown error occurred while trying to insert data into the database.

+

Please check the server log files for more information.

+

{$e->getMessage()}

", + 4 + ); + } +} + +function write_config() +{ + $file_content = "<" . "?php\ndefine('DATABASE_DSN', '".DATABASE_DSN."');\n"; + + if (!file_exists("data/config")) { + mkdir("data/config", 0755, true); + } + + if (file_put_contents("data/config/shimmie.conf.php", $file_content, LOCK_EX)) { + header("Location: index.php"); + print << +

Shimmie Installer

+

Things are OK \o/

+
+

If you aren't redirected, click here to Continue. +

+ +EOD; + } else { + $h_file_content = htmlentities($file_content); + throw new InstallerException( + "File Permissions Error:", + "The web server isn't allowed to write to the config file; please copy + the text below, save it as 'data/config/shimmie.conf.php', and upload it into the shimmie + folder manually. Make sure that when you save it, there is no whitespace + before the \"<?php\" or after the \"?>\" + +

+ +

Once done, click here to Continue.", + 0 + ); + } +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Code coverage * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 428383ec..d05d7818 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -10,12 +10,13 @@ $_SERVER['QUERY_STRING'] = '/'; chdir(dirname(dirname(__FILE__))); require_once "core/_bootstrap.php"; -function create_user(string $name) { - if (is_null(User::by_name($name))) { - $userPage = new UserPage(); - $userPage->onUserCreation(new UserCreationEvent($name, $name, "")); - assert(!is_null(User::by_name($name)), "Creation of user $name failed"); - } +function create_user(string $name) +{ + if (is_null(User::by_name($name))) { + $userPage = new UserPage(); + $userPage->onUserCreation(new UserCreationEvent($name, $name, "")); + assert(!is_null(User::by_name($name)), "Creation of user $name failed"); + } } create_user("demo");