From a0f7b7258966434d2e9fd8c287db5c0010b66d2d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 10 Jan 2016 17:17:06 +0100 Subject: [PATCH 001/183] Moved GD check in front of the configuration check --- plugins/check/index.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/check/index.php b/plugins/check/index.php index b44519e..07c7701 100644 --- a/plugins/check/index.php +++ b/plugins/check/index.php @@ -45,6 +45,12 @@ if (hasPermissions(LYCHEE_UPLOADS_IMPORT)===false) $error .= ('Error: \'uploads if (hasPermissions(LYCHEE_UPLOADS)===false) $error .= ('Error: \'uploads/\' is missing or has insufficient read/write privileges' . PHP_EOL); if (hasPermissions(LYCHEE_DATA)===false) $error .= ('Error: \'data/\' is missing or has insufficient read/write privileges' . PHP_EOL); +# About GD +$gdVersion = gd_info(); +if (!$gdVersion['JPEG Support']) $error .= ('Error: PHP gd extension without jpeg support' . PHP_EOL); +if (!$gdVersion['PNG Support']) $error .= ('Error: PHP gd extension without png support' . PHP_EOL); +if (!$gdVersion['GIF Read Support'] || !$gdVersion['GIF Create Support']) $error .= ('Error: PHP gd extension without full gif support' . PHP_EOL); + # Load config if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error: Configuration not found. Please install Lychee for additional tests'); else require(LYCHEE_CONFIG_FILE); @@ -89,12 +95,6 @@ if (!ini_get('allow_url_fopen')) echo('Warning: You may experience problems with # Check mysql version if ($database->server_version<50500) echo('Warning: Lychee uses the GBK charset to avoid sql injections on your MySQL version. Please update to MySQL 5.5 or higher to enable UTF-8 support.' . PHP_EOL); -# About GD -$gdVersion = gd_info(); -if (!$gdVersion['JPEG Support']) $error .= ('Error: PHP gd extension without jpeg support' . PHP_EOL); -if (!$gdVersion['PNG Support']) $error .= ('Error: PHP gd extension without png support' . PHP_EOL); -if (!$gdVersion['GIF Read Support'] || !$gdVersion['GIF Create Support']) $error .= ('Error: PHP gd extension without full gif support' . PHP_EOL); - # Output if ($error==='') echo('No critical problems found. Lychee should work without problems!' . PHP_EOL); else echo $error; From 978caa90b3c51092d993e4a2e8b6506acb782519 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:02:47 +0100 Subject: [PATCH 002/183] Code style adjustment --- src/scripts/lychee.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 03d1c1f..21be02a 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -7,9 +7,9 @@ lychee = { title : document.title, version : '3.0.9', - version_code : '030009', + versionCode : '030009', - update_path : '//update.electerious.com/index.json', + updatePath : '//update.electerious.com/index.json', updateURL : 'https://github.com/electerious/Lychee', website : 'http://lychee.electerious.com', @@ -232,8 +232,8 @@ lychee.load = function() { lychee.getUpdate = function() { $.ajax({ - url : lychee.update_path, - success : function(data) { if (data.lychee.version>parseInt(lychee.version_code)) $('.version span').show() }, + url : lychee.updatePath, + success : function(data) { if (data.lychee.version>parseInt(lychee.versionCode)) $('.version span').show() }, }) } From 9e76acd9a80325647bed52a33c541d41b9cf3faf Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:03:28 +0100 Subject: [PATCH 003/183] PHP code style adjustments --- php/modules/Photo.php | 5 +++-- php/modules/Session.php | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/php/modules/Photo.php b/php/modules/Photo.php index bc745dd..5f34ccb 100755 --- a/php/modules/Photo.php +++ b/php/modules/Photo.php @@ -18,6 +18,7 @@ class Photo extends Module { IMAGETYPE_GIF, IMAGETYPE_PNG ); + public static $validExtensions = array( '.jpg', '.jpeg', @@ -125,7 +126,7 @@ class Photo extends Module { # Verify extension $extension = getExtension($file['name']); - if (!in_array(strtolower($extension), Photo::$validExtensions, true)) { + if (!in_array(strtolower($extension), self::$validExtensions, true)) { Log::error($this->database, __METHOD__, __LINE__, 'Photo format not supported'); if ($returnOnError===true) return false; exit('Error: Photo format not supported!'); @@ -133,7 +134,7 @@ class Photo extends Module { # Verify image $type = @exif_imagetype($file['tmp_name']); - if (!in_array($type, Photo::$validTypes, true)) { + if (!in_array($type, self::$validTypes, true)) { Log::error($this->database, __METHOD__, __LINE__, 'Photo type not supported'); if ($returnOnError===true) return false; exit('Error: Photo type not supported!'); diff --git a/php/modules/Session.php b/php/modules/Session.php index 16916c9..461110e 100755 --- a/php/modules/Session.php +++ b/php/modules/Session.php @@ -40,6 +40,9 @@ class Session extends Module { # Return settings $return['config'] = $this->settings; + # Path to Lychee for the server-import dialog + $return['config']['location'] = LYCHEE; + # Remove username and password from response unset($return['config']['username']); unset($return['config']['password']); @@ -47,9 +50,6 @@ class Session extends Module { # Remove identifier from response unset($return['config']['identifier']); - # Path to Lychee for the server-import dialog - $return['config']['location'] = LYCHEE; - # Check if login credentials exist and login if they don't if ($this->noLogin()===true) { $public = false; From 634c3621db40ae3478d051231b264190a45f6843 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:06:54 +0100 Subject: [PATCH 004/183] Update database connect function and update mechanism Database::connect now takes care of the update-mechanism and uses the current database version instead of the version from the client. --- php/access/Admin.php | 3 +- php/access/Guest.php | 2 +- php/modules/Database.php | 106 ++++++++++++++++++++------------------- php/modules/Session.php | 12 +---- src/scripts/lychee.js | 6 +-- 5 files changed, 60 insertions(+), 69 deletions(-) diff --git a/php/access/Admin.php b/php/access/Admin.php index e70aa07..251328e 100644 --- a/php/access/Admin.php +++ b/php/access/Admin.php @@ -247,9 +247,8 @@ class Admin extends Access { global $dbName; - Module::dependencies(isset($_POST['version'])); $session = new Session($this->plugins, $this->settings); - echo json_encode($session->init($this->database, $dbName, false, $_POST['version'])); + echo json_encode($session->init($this->database, $dbName, false)); } diff --git a/php/access/Guest.php b/php/access/Guest.php index 611d310..2cfab14 100644 --- a/php/access/Guest.php +++ b/php/access/Guest.php @@ -112,7 +112,7 @@ class Guest extends Access { global $dbName; $session = new Session($this->plugins, $this->settings); - echo json_encode($session->init($this->database, $dbName, true, $_POST['version'])); + echo json_encode($session->init($this->database, $dbName, true)); } diff --git a/php/modules/Database.php b/php/modules/Database.php index d7764e4..9b25860 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -9,6 +9,20 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); class Database extends Module { + private static $versions = array( + '020100', #2.1 + '020101', #2.1.1 + '020200', #2.2 + '020500', #2.5 + '020505', #2.5.5 + '020601', #2.6.1 + '020602', #2.6.2 + '020700', #2.7.0 + '030000', #3.0.0 + '030001', #3.0.1 + '030003' #3.0.3 + ); + static function connect($host = 'localhost', $user, $password, $name = 'lychee') { # Check dependencies @@ -26,44 +40,34 @@ class Database extends Module { # Set unicode $database->query('SET NAMES utf8;'); - # Check database - if (!$database->select_db($name)) - if (!Database::createDatabase($database, $name)) exit('Error: Could not create database!'); + # Create database + if (!self::createDatabase($database, $name)) exit('Error: Could not create database!'); - # Check tables - $query = Database::prepare($database, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); - if (!$database->query($query)) - if (!Database::createTables($database)) exit('Error: Could not create tables!'); + # Create tables + if (!self::createTables($database)) exit('Error: Could not create tables!'); + + # Update database + if (!self::update($database, $name)) exit('Error: Could not update database and tables!'); return $database; } - static function update($database, $dbName, $version = 0) { + private static function update($database, $dbName) { # Check dependencies Module::dependencies(isset($database, $dbName)); - if (!isset($version)) return true; - # List of updates - $updates = array( - '020100', #2.1 - '020101', #2.1.1 - '020200', #2.2 - '020500', #2.5 - '020505', #2.5.5 - '020601', #2.6.1 - '020602', #2.6.2 - '020700', #2.7.0 - '030000', #3.0.0 - '030001', #3.0.1 - '030003' #3.0.3 - ); + # Get current version + $query = self::prepare($database, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); + $results = $database->query($query); + $current = $results->fetch_object()->value; # For each update - foreach ($updates as $update) { + foreach (self::$versions as $version) { - if ($update<=$version) continue; + # Only update when newer version available + if ($version<=$current) continue; # Load update include(__DIR__ . '/../database/update_' . $update . '.php'); @@ -74,7 +78,7 @@ class Database extends Module { } - static function createConfig($host = 'localhost', $user, $password, $name = 'lychee', $prefix = '') { + public static function createConfig($host = 'localhost', $user, $password, $name = 'lychee', $prefix = '') { # Check dependencies Module::dependencies(isset($host, $user, $password, $name)); @@ -83,15 +87,8 @@ class Database extends Module { if ($database->connect_errno) return 'Warning: Connection failed!'; - # Check if database exists - if (!$database->select_db($name)) { - - # Database doesn't exist - # Check if user can create the database - $result = Database::createDatabase($database, $name); - if ($result===false) return 'Warning: Creation failed!'; - - } + # Check if user can create the database before saving the configuration + if (!self::createDatabase($database, $name)) return 'Warning: Creation failed!'; # Escape data $host = mysqli_real_escape_string($database, $host); @@ -127,13 +124,16 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } - static function createDatabase($database, $name = 'lychee') { + private static function createDatabase($database, $name = 'lychee') { # Check dependencies Module::dependencies(isset($database, $name)); + # Check if database exists + if ($database->select_db($name)) return true; + # Create database - $query = Database::prepare($database, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); + $query = self::prepare($database, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); $result = $database->query($query); if (!$database->select_db($name)||!$result) return false; @@ -141,13 +141,17 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } - static function createTables($database) { + private static function createTables($database) { # Check dependencies Module::dependencies(isset($database)); + # Check if tables exist + $query = self::prepare($database, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); + if ($database->query($query)) return true; + # Create log - $exist = Database::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); + $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); if (!$database->query($exist)) { # Read file @@ -157,13 +161,13 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); if (!isset($query)||$query===false) return false; # Create table - $query = Database::prepare($database, $query, array(LYCHEE_TABLE_LOG)); + $query = self::prepare($database, $query, array(LYCHEE_TABLE_LOG)); if (!$database->query($query)) return false; } # Create settings - $exist = Database::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); + $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); if (!$database->query($exist)) { # Read file @@ -176,7 +180,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Create table - $query = Database::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); + $query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); if (!$database->query($query)) { Log::error($database, __METHOD__, __LINE__, $database->error); return false; @@ -192,7 +196,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Add content - $query = Database::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); + $query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); if (!$database->query($query)) { Log::error($database, __METHOD__, __LINE__, $database->error); return false; @@ -200,7 +204,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Generate identifier $identifier = md5(microtime(true)); - $query = Database::prepare($database, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); + $query = self::prepare($database, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); if (!$database->query($query)) { Log::error($database, __METHOD__, __LINE__, $database->error); return false; @@ -209,7 +213,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Create albums - $exist = Database::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); + $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); if (!$database->query($exist)) { # Read file @@ -222,7 +226,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Create table - $query = Database::prepare($database, $query, array(LYCHEE_TABLE_ALBUMS)); + $query = self::prepare($database, $query, array(LYCHEE_TABLE_ALBUMS)); if (!$database->query($query)) { Log::error($database, __METHOD__, __LINE__, $database->error); return false; @@ -231,7 +235,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Create photos - $exist = Database::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); + $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); if (!$database->query($exist)) { # Read file @@ -244,7 +248,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } # Create table - $query = Database::prepare($database, $query, array(LYCHEE_TABLE_PHOTOS)); + $query = self::prepare($database, $query, array(LYCHEE_TABLE_PHOTOS)); if (!$database->query($query)) { Log::error($database, __METHOD__, __LINE__, $database->error); return false; @@ -256,9 +260,9 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } - static function setVersion($database, $version) { + public static function setVersion($database, $version) { - $query = Database::prepare($database, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); + $query = self::prepare($database, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); $result = $database->query($query); if (!$result) { Log::error($database, __METHOD__, __LINE__, 'Could not update database (' . $database->error . ')'); @@ -267,7 +271,7 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } - static function prepare($database, $query, $data) { + public static function prepare($database, $query, $data) { # Check dependencies Module::dependencies(isset($database, $query, $data)); diff --git a/php/modules/Session.php b/php/modules/Session.php index 461110e..524877b 100755 --- a/php/modules/Session.php +++ b/php/modules/Session.php @@ -21,22 +21,14 @@ class Session extends Module { } - public function init($database, $dbName, $public, $version) { + public function init($database, $dbName, $public) { # Check dependencies - self::dependencies(isset($this->settings, $public, $version)); + self::dependencies(isset($this->settings, $public)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); - # Update - if (!isset($this->settings['version'])||$this->settings['version']!==$version) { - if (!Database::update($database, $dbName, @$this->settings['version'])) { - Log::error($database, __METHOD__, __LINE__, 'Updating the database failed'); - exit('Error: Updating the database failed!'); - } - } - # Return settings $return['config'] = $this->settings; diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 21be02a..c326cef 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -32,11 +32,7 @@ lychee = { lychee.init = function() { - let params = { - version: lychee.version_code - } - - api.post('Session::init', params, function(data) { + api.post('Session::init', {}, function(data) { // Check status // 0 = No configuration From 9cb6dc19b79a305c59150a6f60e9099d96fad628 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:45:41 +0100 Subject: [PATCH 005/183] Added abstract/final to classes to be more strict --- php/modules/Album.php | 2 +- php/modules/Database.php | 2 +- php/modules/Import.php | 2 +- php/modules/Log.php | 2 +- php/modules/Module.php | 4 ++-- php/modules/Photo.php | 2 +- php/modules/Plugins.php | 2 +- php/modules/Session.php | 2 +- php/modules/Settings.php | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/php/modules/Album.php b/php/modules/Album.php index 1b8d1c5..f4ed7f7 100644 --- a/php/modules/Album.php +++ b/php/modules/Album.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Album extends Module { +final class Album extends Module { private $database = null; private $settings = null; diff --git a/php/modules/Database.php b/php/modules/Database.php index 9b25860..131e5e2 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Database extends Module { +final class Database extends Module { private static $versions = array( '020100', #2.1 diff --git a/php/modules/Import.php b/php/modules/Import.php index 621c562..5c42dd1 100644 --- a/php/modules/Import.php +++ b/php/modules/Import.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Import extends Module { +final class Import extends Module { private $database = null; private $settings = null; diff --git a/php/modules/Log.php b/php/modules/Log.php index 1725020..5befb0a 100644 --- a/php/modules/Log.php +++ b/php/modules/Log.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Log extends Module { +final class Log extends Module { public static function notice($database, $function, $line, $text = '') { diff --git a/php/modules/Module.php b/php/modules/Module.php index 3e8b672..ab9fb0a 100644 --- a/php/modules/Module.php +++ b/php/modules/Module.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Module { +abstract class Module { protected $plugins = null; @@ -25,7 +25,7 @@ class Module { } - public static function dependencies($available = false) { + final public static function dependencies($available = false) { if ($available===false) exit('Error: Can not execute function. Missing parameters or variables.'); diff --git a/php/modules/Photo.php b/php/modules/Photo.php index 5f34ccb..ce99dd7 100755 --- a/php/modules/Photo.php +++ b/php/modules/Photo.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Photo extends Module { +final class Photo extends Module { private $database = null; private $settings = null; diff --git a/php/modules/Plugins.php b/php/modules/Plugins.php index 9663814..d58cbaf 100644 --- a/php/modules/Plugins.php +++ b/php/modules/Plugins.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Plugins implements \SplSubject { +final class Plugins implements \SplSubject { private $files = array(); private $observers = array(); diff --git a/php/modules/Session.php b/php/modules/Session.php index 524877b..3e27d98 100755 --- a/php/modules/Session.php +++ b/php/modules/Session.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Session extends Module { +final class Session extends Module { private $settings = null; diff --git a/php/modules/Settings.php b/php/modules/Settings.php index f0f57f4..689fd1c 100755 --- a/php/modules/Settings.php +++ b/php/modules/Settings.php @@ -7,7 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Settings extends Module { +final class Settings extends Module { private $database = null; From 1019b0fef1d89c99293691041839ac5352fee367 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:45:59 +0100 Subject: [PATCH 006/183] Added 'public' to database connect function --- php/modules/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/modules/Database.php b/php/modules/Database.php index 131e5e2..07d4035 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -23,7 +23,7 @@ final class Database extends Module { '030003' #3.0.3 ); - static function connect($host = 'localhost', $user, $password, $name = 'lychee') { + public static function connect($host = 'localhost', $user, $password, $name = 'lychee') { # Check dependencies Module::dependencies(isset($host, $user, $password, $name)); From 33e16041af0fa8762db9f880bdcc2ce8ecb824b0 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 11:57:16 +0100 Subject: [PATCH 007/183] Removed $dbTablePrefix definition as defineTablePrefix() will do the same --- php/api.php | 3 +-- php/define.php | 2 +- plugins/check/index.php | 3 +-- plugins/displaylog/index.php | 3 +-- view.php | 3 +-- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/php/api.php b/php/api.php index d043a4d..4c259cb 100755 --- a/php/api.php +++ b/php/api.php @@ -33,8 +33,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { } # Define the table prefix - if (!isset($dbTablePrefix)) $dbTablePrefix = ''; - defineTablePrefix($dbTablePrefix); + defineTablePrefix(@$dbTablePrefix); # Connect to database $database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName); diff --git a/php/define.php b/php/define.php index fb045f2..65b99d6 100644 --- a/php/define.php +++ b/php/define.php @@ -34,7 +34,7 @@ define('LYCHEE_URL_UPLOADS_THUMB', 'uploads/thumb/'); function defineTablePrefix($dbTablePrefix) { # This part is wrapped into a function, because it needs to be called - # after the config-file has been loaded. Other defines are also available + # after the config-file has been loaded. Other defines are available # before the config-file has been loaded. # Parse table prefix diff --git a/plugins/check/index.php b/plugins/check/index.php index 07c7701..dfcbd12 100644 --- a/plugins/check/index.php +++ b/plugins/check/index.php @@ -56,8 +56,7 @@ if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error: Configuration not found. Plea else require(LYCHEE_CONFIG_FILE); # Define the table prefix -if (!isset($dbTablePrefix)) $dbTablePrefix = ''; -defineTablePrefix($dbTablePrefix); +defineTablePrefix(@$dbTablePrefix); # Database $database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName); diff --git a/plugins/displaylog/index.php b/plugins/displaylog/index.php index e6e690b..a9ac561 100644 --- a/plugins/displaylog/index.php +++ b/plugins/displaylog/index.php @@ -23,8 +23,7 @@ if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error 001: Configuration not found. require(LYCHEE_CONFIG_FILE); # Define the table prefix -if (!isset($dbTablePrefix)) $dbTablePrefix = ''; -defineTablePrefix($dbTablePrefix); +defineTablePrefix(@$dbTablePrefix); # Declare $result = ''; diff --git a/view.php b/view.php index f051f21..c1b1160 100644 --- a/view.php +++ b/view.php @@ -29,8 +29,7 @@ require(LYCHEE_CONFIG_FILE); # Define the table prefix - if (!isset($dbTablePrefix)) $dbTablePrefix = ''; - defineTablePrefix($dbTablePrefix); + defineTablePrefix(@$dbTablePrefix); $database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName); From 0a9b0d0078e3c1d581d0295c140afb744540e6b1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 14:58:08 +0100 Subject: [PATCH 008/183] Simplified autoloader --- php/autoload.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/php/autoload.php b/php/autoload.php index 91df00c..6dad8c0 100644 --- a/php/autoload.php +++ b/php/autoload.php @@ -7,23 +7,19 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -function lycheeAutoloaderModules($class_name) { +function lycheeAutoloaderModules($class) { - $modules = array('Album', 'Database', 'Import', 'Log', 'Module', 'Photo', 'Plugins', 'Session', 'Settings'); - if (!in_array($class_name, $modules)) return false; + $file = LYCHEE . 'php/modules/' . $class . '.php'; - $file = LYCHEE . 'php/modules/' . $class_name . '.php'; - if (file_exists($file)!==false) require $file; + if (file_exists($file)===true) require $file; } -function lycheeAutoloaderAccess($class_name) { +function lycheeAutoloaderAccess($class) { - $access = array('Access', 'Admin', 'Guest', 'Installation'); - if (!in_array($class_name, $access)) return false; + $file = LYCHEE . 'php/access/' . $class . '.php'; - $file = LYCHEE . 'php/access/' . $class_name . '.php'; - if (file_exists($file)!==false) require $file; + if (file_exists($file)===true) require $file; } From 7bce954c8d3ac3f99d512742214ed1c4a283776e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 15:03:50 +0100 Subject: [PATCH 009/183] Register autoloader functions as anonymous functions Requires PHP 5.3 --- php/autoload.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/php/autoload.php b/php/autoload.php index 6dad8c0..e7bede4 100644 --- a/php/autoload.php +++ b/php/autoload.php @@ -7,23 +7,20 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -function lycheeAutoloaderModules($class) { +spl_autoload_register(function($class) { $file = LYCHEE . 'php/modules/' . $class . '.php'; if (file_exists($file)===true) require $file; -} +}); -function lycheeAutoloaderAccess($class) { +spl_autoload_register(function($class) { $file = LYCHEE . 'php/access/' . $class . '.php'; if (file_exists($file)===true) require $file; -} - -spl_autoload_register('lycheeAutoloaderModules'); -spl_autoload_register('lycheeAutoloaderAccess'); +}); ?> \ No newline at end of file From 3d88300df18250c298f92442a7ee001f70a2b754 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 16:08:43 +0100 Subject: [PATCH 010/183] Code style adjustment --- php/modules/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/modules/Plugins.php b/php/modules/Plugins.php index d58cbaf..283223d 100644 --- a/php/modules/Plugins.php +++ b/php/modules/Plugins.php @@ -20,7 +20,7 @@ final class Plugins implements \SplSubject { if (!isset($files)) return false; # Init vars - $this->files = $files; + $this->files = $files; # Load plugins foreach ($this->files as $file) { From a5cab35e34eb6407afa96d9cb3436e937084dc6c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 16:08:50 +0100 Subject: [PATCH 011/183] Added type hints --- php/modules/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/modules/Plugins.php b/php/modules/Plugins.php index 283223d..94aa1bd 100644 --- a/php/modules/Plugins.php +++ b/php/modules/Plugins.php @@ -15,7 +15,7 @@ final class Plugins implements \SplSubject { public $action = null; public $args = null; - public function __construct($files, $database, $settings) { + public function __construct(array $files, $database, array $settings) { if (!isset($files)) return false; From 70d7e1e6f249993a11171293366caef55ceebc7c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 19 Jan 2016 16:09:06 +0100 Subject: [PATCH 012/183] API cleanup and code style changes --- php/api.php | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/php/api.php b/php/api.php index 4c259cb..d9e8381 100755 --- a/php/api.php +++ b/php/api.php @@ -5,8 +5,15 @@ # @copyright 2015 by Tobias Reich ### -if (!empty($_POST['function'])||!empty($_GET['function'])) { +# Define the called function +if (isset($_POST['function'])) $fn = $_POST['function']; +else if (isset($_GET['function'])) $fn = $_GET['function']; +else $fn = null; +# Check if a function has been specified +if (!empty($fn)) { + + # Start the session and set the default timezone session_start(); date_default_timezone_set('UTC'); @@ -15,6 +22,13 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { require(__DIR__ . '/autoload.php'); require(__DIR__ . '/modules/misc.php'); + # Validate parameters + if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); + if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); + if (isset($_POST['albumID'])&&preg_match('/^[0-9sfr]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); + if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + + # Check if a configuration exists if (file_exists(LYCHEE_CONFIG_FILE)) require(LYCHEE_CONFIG_FILE); else { @@ -46,16 +60,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { $plugins = explode(';', $settings['plugins']); $plugins = new Plugins($plugins, $database, $settings); - # Validate parameters - if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); - if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); - if (isset($_POST['albumID'])&&preg_match('/^[0-9sfr]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); - if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); - - # Function for switch statement - if (isset($_POST['function'])) $fn = $_POST['function']; - else $fn = $_GET['function']; - + # Check if user is logged if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& (isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) { @@ -85,8 +90,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { } else { - exit('Error: Called function not found!'); + exit('Error: No API function specified!'); } -?> +?> \ No newline at end of file From d5a03a31f8411d57a39cb2debccb477d0fb683b9 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 13:07:25 +0100 Subject: [PATCH 013/183] Fix for session_start() after sending headers #433 --- plugins/check/index.php | 5 +++-- plugins/displaylog/index.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/check/index.php b/plugins/check/index.php index dfcbd12..7340573 100644 --- a/plugins/check/index.php +++ b/plugins/check/index.php @@ -15,6 +15,9 @@ require($lychee . 'php/define.php'); require($lychee . 'php/autoload.php'); require($lychee . 'php/modules/misc.php'); +# Start the session +session_start(); + # Set content header('content-type: text/plain'); @@ -103,8 +106,6 @@ echo(PHP_EOL . PHP_EOL . 'System Information' . PHP_EOL); echo('------------------' . PHP_EOL); # Ensure that user is logged in -session_start(); - if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& (isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) { diff --git a/plugins/displaylog/index.php b/plugins/displaylog/index.php index a9ac561..52aa698 100644 --- a/plugins/displaylog/index.php +++ b/plugins/displaylog/index.php @@ -10,6 +10,9 @@ # Location $lychee = __DIR__ . '/../../'; +# Start the session +session_start(); + # Load requirements require($lychee . 'php/define.php'); require($lychee . 'php/autoload.php'); @@ -41,8 +44,6 @@ $settings = new Settings($database); $settings = $settings->get(); # Ensure that user is logged in -session_start(); - if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& (isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) { From 1a856eeb4f8b10d27d6ed7cbefe9dd4aedff0965 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 14:21:06 +0100 Subject: [PATCH 014/183] Updated jquery --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 2de6f1e..fa9ea25 100644 --- a/src/package.json +++ b/src/package.json @@ -23,7 +23,7 @@ "gulp-rimraf": "^0.2.0", "gulp-sass": "^2.1.1", "gulp-uglify": "^1.5.1", - "jquery": "^2.1.4", + "jquery": "^2.2.0", "mousetrap": "^1.5.3" } } From eb887c7ca83314cf30337e7bcf0b3f1c79158258 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 14:57:22 +0100 Subject: [PATCH 015/183] Added scripts to package.json and removed gulp from the global dependencies --- docs/Build.md | 12 ++++-------- src/package.json | 4 ++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/Build.md b/docs/Build.md index 6d9af87..acb0a09 100644 --- a/docs/Build.md +++ b/docs/Build.md @@ -4,22 +4,18 @@ First you have to install the following dependencies: - `node` [Node.js](http://nodejs.org) v0.10 or later - `npm` [Node Packaged Modules](https://www.npmjs.org) -- `gulp` [Gulp.js](http://gulpjs.com) -After [installing Node.js](http://nodejs.org) you can use the included `npm` package manager to install the global requirements and Lychee-dependencies with the following command: +After [installing Node.js](http://nodejs.org) you can use the included `npm` package manager to download all dependencies: cd src/ - npm install -g gulp npm install ### Build -The Gulpfile is located in `src/` and can be easily executed using the `gulp` command. +The Gulpfile is located in `src/` and can be executed using the `npm start` command. ### Watch for changes -While developing, you might want to use the following command to watch for changes: +While developing, you might want to use the following command to automatically build Lychee everytime you save a file: - gulp watch - -`gulp watch` will automatically build Lychee everytime you save a file. + npm run watch diff --git a/src/package.json b/src/package.json index fa9ea25..fecdb82 100644 --- a/src/package.json +++ b/src/package.json @@ -9,6 +9,10 @@ "type": "git", "url": "https://github.com/electerious/Lychee.git" }, + "scripts": { + "start": "gulp", + "watch": "gulp watch" + }, "devDependencies": { "babel-preset-es2015": "^6.3.13", "basiccontext": "^3.5.1", From 606968f349cdfa695d386f9788436c78637c8a8e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 15:16:03 +0100 Subject: [PATCH 016/183] Updated code style --- src/scripts/_gup.js | 6 ++-- src/scripts/album.js | 36 ++++++++++++------------ src/scripts/albums.js | 2 +- src/scripts/api.js | 8 +++--- src/scripts/build.js | 6 ++-- src/scripts/contextMenu.js | 28 +++++++++---------- src/scripts/header.js | 14 +++++----- src/scripts/init.js | 22 +++++++-------- src/scripts/lychee.js | 57 +++++++++++++++++++++----------------- src/scripts/multiselect.js | 36 ++++++++++++------------ src/scripts/photo.js | 54 ++++++++++++++++++------------------ src/scripts/search.js | 6 ++-- src/scripts/settings.js | 24 ++++++++-------- src/scripts/sidebar.js | 32 ++++++++++----------- src/scripts/upload.js | 36 ++++++++++++------------ src/scripts/view.js | 44 ++++++++++++++++------------- src/scripts/view/main.js | 14 +++++----- 17 files changed, 218 insertions(+), 207 deletions(-) diff --git a/src/scripts/_gup.js b/src/scripts/_gup.js index 8757da7..c71c790 100644 --- a/src/scripts/_gup.js +++ b/src/scripts/_gup.js @@ -2,9 +2,9 @@ function gup(b) { b = b.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]") - let a = "[\\?&]" + b + "=([^&#]*)", - d = new RegExp(a), - c = d.exec(window.location.href) + let a = "[\\?&]" + b + "=([^&#]*)" + let d = new RegExp(a) + let c = d.exec(window.location.href) if (c === null) return '' else return c[1] diff --git a/src/scripts/album.js b/src/scripts/album.js index b552fd6..6f3a9b7 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -146,12 +146,12 @@ album.add = function() { album.delete = function(albumIDs) { - let action = {}, - cancel = {}, - msg = '' + let action = {} + let cancel = {} + let msg = '' if (!albumIDs) return false - if (albumIDs instanceof Array===false) albumIDs = [albumIDs] + if (albumIDs instanceof Array===false) albumIDs = [ albumIDs ] action.fn = function() { @@ -234,11 +234,11 @@ album.delete = function(albumIDs) { album.setTitle = function(albumIDs) { - let oldTitle = '', - msg = '' + let oldTitle = '' + let msg = '' if (!albumIDs) return false - if (albumIDs instanceof Array===false) albumIDs = [albumIDs] + if (albumIDs instanceof Array===false) albumIDs = [ albumIDs ] if (albumIDs.length===1) { @@ -365,12 +365,12 @@ album.setPublic = function(albumID, modal, e) { if (modal===true) { - let text = '', - action = {} + let text = '' + let action = {} action.fn = () => { - // setPublic function without showing the modal + // Call setPublic function without showing the modal album.setPublic(album.getID(), false, e) } @@ -515,8 +515,8 @@ album.setPublic = function(albumID, modal, e) { album.share = function(service) { - let link = '', - url = location.href + let link = '' + let url = location.href switch (service) { case 'twitter': @@ -539,8 +539,8 @@ album.share = function(service) { album.getArchive = function(albumID) { - let link, - url = `${ api.path }?function=Album::getArchive&albumID=${ albumID }` + let link = '' + let url = `${ api.path }?function=Album::getArchive&albumID=${ albumID }` if (location.href.indexOf('index.html')>0) link = location.href.replace(location.hash, '').replace('index.html', url) else link = location.href.replace(location.hash, '') + url @@ -553,12 +553,12 @@ album.getArchive = function(albumID) { album.merge = function(albumIDs) { - let title = '', - sTitle = '', - msg = '' + let title = '' + let sTitle = '' + let msg = '' if (!albumIDs) return false - if (albumIDs instanceof Array===false) albumIDs = [albumIDs] + if (albumIDs instanceof Array===false) albumIDs = [ albumIDs ] // Get title of first album if (albums.json) title = albums.getByID(albumIDs[0]).title diff --git a/src/scripts/albums.js b/src/scripts/albums.js index ef6b6d1..846046c 100644 --- a/src/scripts/albums.js +++ b/src/scripts/albums.js @@ -134,7 +134,7 @@ albums.deleteByID = function(albumID) { if (!albums.json) return false if (!albums.json.albums) return false - var deleted = false + let deleted = false $.each(albums.json.albums, function(i) { diff --git a/src/scripts/api.js b/src/scripts/api.js index 3301dbd..264a7e6 100644 --- a/src/scripts/api.js +++ b/src/scripts/api.js @@ -14,7 +14,7 @@ api.post = function(fn, params, callback) { loadingBar.show() - params = $.extend({function: fn}, params) + params = $.extend({ function: fn }, params) const success = (data) => { @@ -31,9 +31,9 @@ api.post = function(fn, params, callback) { else if (data==='') data = false // Convert to JSON if string start with '{' and ends with '}' - if (typeof data==='string' && - data.substring(0, 1)==='{' && - data.substring(data.length-1, data.length)==='}') data = $.parseJSON(data) + if (typeof data==='string' && data.substring(0, 1)==='{' && data.substring(data.length - 1, data.length)==='}') { + data = $.parseJSON(data) + } // Output response when debug mode is enabled if (lychee.debugMode) console.log(data) diff --git a/src/scripts/build.js b/src/scripts/build.js index 75cc311..4b1f020 100644 --- a/src/scripts/build.js +++ b/src/scripts/build.js @@ -115,8 +115,8 @@ build.photo = function(data) { build.imageview = function(data, visibleControls) { - let html = '', - hasMedium = data.medium!=='' + let html = '' + let hasMedium = data.medium!=='' if (hasMedium===false) { @@ -182,7 +182,7 @@ build.uploadModal = function(title, files) { let file = files[i] - if (file.name.length>40) file.name = file.name.substr(0, 17) + '...' + file.name.substr(file.name.length-20, 20) + if (file.name.length>40) file.name = file.name.substr(0, 17) + '...' + file.name.substr(file.name.length - 20, 20) html += lychee.html`
diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index 2d6b6b5..cc036fd 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -53,9 +53,9 @@ contextMenu.album = function(albumID, e) { let showMerge = (albums.json && albums.json.albums && Object.keys(albums.json.albums).length>1) let items = [ - { title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([albumID]) }, + { title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([ albumID ]) }, { title: build.iconic('collapse-left') + 'Merge', visible: showMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumID, e) } }, - { title: build.iconic('trash') + 'Delete', fn: () => album.delete([albumID]) } + { title: build.iconic('trash') + 'Delete', fn: () => album.delete([ albumID ]) } ] $('.album[data-id="' + albumID + '"]').addClass('active') @@ -111,7 +111,7 @@ contextMenu.albumTitle = function(albumID, e) { } - items.unshift({ title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([albumID]) }) + items.unshift({ title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([ albumID ]) }) basicContext.show(items, e.originalEvent, contextMenu.close) @@ -133,7 +133,7 @@ contextMenu.mergeAlbum = function(albumID, e) { let title = lychee.html`
$${ this.title }
` - if (this.id!=albumID) items.push({ title, fn: () => album.merge([albumID, this.id]) }) + if (this.id!=albumID) items.push({ title, fn: () => album.merge([ albumID, this.id ]) }) }) @@ -154,13 +154,13 @@ contextMenu.photo = function(photoID, e) { // in order to keep the selection let items = [ - { title: build.iconic('star') + 'Star', fn: () => photo.setStar([photoID]) }, - { title: build.iconic('tag') + 'Tags', fn: () => photo.editTags([photoID]) }, + { title: build.iconic('star') + 'Star', fn: () => photo.setStar([ photoID ]) }, + { title: build.iconic('tag') + 'Tags', fn: () => photo.editTags([ photoID ]) }, { }, - { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([photoID]) }, - { title: build.iconic('layers') + 'Duplicate', fn: () => photo.duplicate([photoID]) }, - { title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.move([photoID], e) } }, - { title: build.iconic('trash') + 'Delete', fn: () => photo.delete([photoID]) } + { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([ photoID ]) }, + { title: build.iconic('layers') + 'Duplicate', fn: () => photo.duplicate([ photoID ]) }, + { title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.move([ photoID ], e) } }, + { title: build.iconic('trash') + 'Delete', fn: () => photo.delete([ photoID ]) } ] $('.photo[data-id="' + photoID + '"]').addClass('active') @@ -194,7 +194,7 @@ contextMenu.photoMulti = function(photoIDs, e) { contextMenu.photoTitle = function(albumID, photoID, e) { let items = [ - { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([photoID]) } + { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([ photoID ]) } ] let data = album.json @@ -236,7 +236,7 @@ contextMenu.photoMore = function(photoID, e) { contextMenu.move = function(photoIDs, e) { - var items = [] + let items = [] api.post('Album::getAll', {}, function(data) { @@ -278,8 +278,8 @@ contextMenu.move = function(photoIDs, e) { contextMenu.sharePhoto = function(photoID, e) { - let link = photo.getViewLink(photoID), - iconClass = 'ionicons' + let link = photo.getViewLink(photoID) + let iconClass = 'ionicons' let items = [ { title: ``, fn: () => {}, class: 'basicContext__item--noHover' }, diff --git a/src/scripts/header.js b/src/scripts/header.js index bced47a..c8a9672 100644 --- a/src/scripts/header.js +++ b/src/scripts/header.js @@ -46,17 +46,17 @@ header.bind = function() { header.dom('#button_info') .on(eventName, sidebar.toggle) header.dom('.button_add') .on(eventName, contextMenu.add) header.dom('#button_more') .on(eventName, function(e) { contextMenu.photoMore(photo.getID(), e) }) - header.dom('#button_move') .on(eventName, function(e) { contextMenu.move([photo.getID()], e) }) + header.dom('#button_move') .on(eventName, function(e) { contextMenu.move([ photo.getID() ], e) }) header.dom('.header__hostedwith') .on(eventName, function() { window.open(lychee.website) }) - header.dom('#button_trash_album') .on(eventName, function() { album.delete([album.getID()]) }) - header.dom('#button_trash') .on(eventName, function() { photo.delete([photo.getID()]) }) + header.dom('#button_trash_album') .on(eventName, function() { album.delete([ album.getID() ]) }) + header.dom('#button_trash') .on(eventName, function() { photo.delete([ photo.getID() ]) }) header.dom('#button_archive') .on(eventName, function() { album.getArchive(album.getID()) }) - header.dom('#button_star') .on(eventName, function() { photo.setStar([photo.getID()]) }) + header.dom('#button_star') .on(eventName, function() { photo.setStar([ photo.getID() ]) }) header.dom('#button_back_home') .on(eventName, function() { lychee.goto('') }) header.dom('#button_back') .on(eventName, function() { lychee.goto(album.getID()) }) header.dom('.header__search').on('keyup click', function() { search.find($(this).val()) }) - header.dom('.header__clear').on(eventName, function () { + header.dom('.header__clear').on(eventName, function() { header.dom('.header__search').focus() search.reset() }) @@ -99,8 +99,8 @@ header.hide = function(e, delay = 500) { header.setTitle = function(title = 'Untitled') { - let $title = header.dom('.header__title'), - html = lychee.html`$${ title }${ build.iconic('caret-bottom') }` + let $title = header.dom('.header__title') + let html = lychee.html`$${ title }${ build.iconic('caret-bottom') }` $title.html(html) diff --git a/src/scripts/init.js b/src/scripts/init.js index 474064d..612eeff 100755 --- a/src/scripts/init.js +++ b/src/scripts/init.js @@ -24,38 +24,38 @@ $(document).ready(function() { // Keyboard Mousetrap - .bind('left', function() { + .bind([ 'left' ], function() { if (visible.photo()) { $('#imageview a#previous').click(); return false } }) - .bind('right', function() { + .bind([ 'right' ], function() { if (visible.photo()) { $('#imageview a#next').click(); return false } }) - .bind('u', function() { + .bind([ 'u' ], function() { if (!visible.photo()) { $('#upload_files').click(); return false } }) - .bind(['s', 'f'], function() { + .bind([ 's', 'f' ], function() { if (visible.photo()) { header.dom('#button_star').click(); return false } else if (visible.albums()) { header.dom('.header__search').focus(); return false } }) - .bind('r', function() { + .bind([ 'r' ], function() { if (visible.album()) { album.setTitle(album.getID()); return false } else if (visible.photo()) { photo.setTitle([photo.getID()]); return false } }) - .bind('d', function() { + .bind([ 'd' ], function() { if (visible.photo()) { photo.setDescription(photo.getID()); return false } else if (visible.album()) { album.setDescription(album.getID()); return false } }) - .bind('t', function() { + .bind([ 't' ], function() { if (visible.photo()) { photo.editTags([photo.getID()]); return false } }) - .bind('i', function() { + .bind([ 'i' ], function() { if (!visible.multiselect()) { sidebar.toggle(); return false } }) - .bind(['command+backspace', 'ctrl+backspace'], function() { + .bind([ 'command+backspace', 'ctrl+backspace' ], function() { if (visible.photo() && basicModal.visible()===false) { photo.delete([photo.getID()]); return false } else if (visible.album() && basicModal.visible()===false) { album.delete([album.getID()]); return false } }) - .bind(['command+a', 'ctrl+a'], function() { + .bind([ 'command+a', 'ctrl+a' ], function() { if (visible.album() && basicModal.visible()===false) { multiselect.selectAll(); return false } else if (visible.albums() && basicModal.visible()===false) { multiselect.selectAll(); return false } }) @@ -64,7 +64,7 @@ $(document).ready(function() { if (basicModal.visible()===true) basicModal.action() }) - Mousetrap.bindGlobal(['esc', 'command+up'], function() { + Mousetrap.bindGlobal([ 'esc', 'command+up' ], function() { if (basicModal.visible()===true) basicModal.cancel() else if (visible.contextMenu()) contextMenu.close() else if (visible.photo()) lychee.goto(album.getID()) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index c326cef..1efc4eb 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -84,8 +84,8 @@ lychee.init = function() { lychee.login = function(data) { - let user = data.username, - password = data.password + let user = data.username + let password = data.password let params = { user, @@ -169,9 +169,9 @@ lychee.goto = function(url) { lychee.load = function() { - let albumID = '', - photoID = '', - hash = document.location.hash.replace('#', '').split('/') + let albumID = '' + let photoID = '' + let hash = document.location.hash.replace('#', '').split('/') $('.no_content').remove() contextMenu.close() @@ -227,9 +227,13 @@ lychee.load = function() { lychee.getUpdate = function() { + const success = function(data) { + if (data.lychee.version>parseInt(lychee.versionCode)) $('.version span').show() + } + $.ajax({ url : lychee.updatePath, - success : function(data) { if (data.lychee.version>parseInt(lychee.versionCode)) $('.version span').show() }, + success : success }) } @@ -256,14 +260,14 @@ lychee.setMode = function(mode) { .off('drop') Mousetrap - .unbind('u') - .unbind('s') - .unbind('f') - .unbind('r') - .unbind('d') - .unbind('t') - .unbind(['command+backspace', 'ctrl+backspace']) - .unbind(['command+a', 'ctrl+a']) + .unbind([ 'u' ]) + .unbind([ 's' ]) + .unbind([ 'f' ]) + .unbind([ 'r' ]) + .unbind([ 'd' ]) + .unbind([ 't' ]) + .unbind([ 'command+backspace', 'ctrl+backspace' ]) + .unbind([ 'command+a', 'ctrl+a' ]) if (mode==='public') { @@ -271,7 +275,8 @@ lychee.setMode = function(mode) { } else if (mode==='view') { - Mousetrap.unbind(['esc', 'command+up']) + Mousetrap.unbind([ 'esc', 'command+up' ]) + $('#button_back, a#next, a#previous').remove() $('.no_content').remove() @@ -285,8 +290,8 @@ lychee.setMode = function(mode) { lychee.animate = function(obj, animation) { let animations = [ - ['fadeIn', 'fadeOut'], - ['contentZoomIn', 'contentZoomOut'] + [ 'fadeIn', 'fadeOut' ], + [ 'contentZoomIn', 'contentZoomOut' ] ] if (!obj.jQuery) obj = $(obj) @@ -306,8 +311,8 @@ lychee.animate = function(obj, animation) { lychee.retinize = function(path = '') { - let extention = path.split('.').pop(), - isPhoto = extention!=='svg' + let extention = path.split('.').pop() + let isPhoto = extention!=='svg' if (isPhoto===true) { @@ -329,8 +334,8 @@ lychee.loadDropbox = function(callback) { loadingBar.show() - let g = document.createElement('script'), - s = document.getElementsByTagName('script')[0] + let g = document.createElement('script') + let s = document.getElementsByTagName('script')[0] g.src = 'https://www.dropbox.com/static/api/1/dropins.js' g.id = 'dropboxjs' @@ -360,8 +365,8 @@ lychee.loadDropbox = function(callback) { lychee.getEventName = function() { - let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement), - eventName = (touchendSupport===true ? 'touchend' : 'click') + let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement) + let eventName = (touchendSupport===true ? 'touchend' : 'click') return eventName @@ -388,8 +393,8 @@ lychee.html = function(literalSections, ...substs) { // Use raw literal sections: we don’t want // backslashes (\n etc.) to be interpreted - let raw = literalSections.raw, - result = '' + let raw = literalSections.raw + let result = '' substs.forEach((subst, i) => { @@ -412,7 +417,7 @@ lychee.html = function(literalSections, ...substs) { // Take care of last literal section // (Never fails, because an empty template string // produces one literal section, an empty string) - result += raw[raw.length-1] + result += raw[raw.length - 1] return result diff --git a/src/scripts/multiselect.js b/src/scripts/multiselect.js index b9318fe..e9c60e2 100644 --- a/src/scripts/multiselect.js +++ b/src/scripts/multiselect.js @@ -89,8 +89,8 @@ multiselect.resize = function(e) { multiselect.position.bottom === null || multiselect.position.left === null) return false - let newSize = {}, - documentSize = {} + let newSize = {} + let documentSize = {} // Get the position of the mouse let mousePos = { @@ -114,7 +114,7 @@ multiselect.resize = function(e) { // Do not leave the screen newSize.height = mousePos.y - multiselect.position.top - if ((multiselect.position.top+newSize.height)>=documentSize.height) { + if ((multiselect.position.top + newSize.height)>=documentSize.height) { newSize.height -= (multiselect.position.top + newSize.height) - documentSize.height + 2 } @@ -136,7 +136,7 @@ multiselect.resize = function(e) { // Do not leave the screen newSize.width = mousePos.x - multiselect.position.left - if ((multiselect.position.left+newSize.width)>=documentSize.width) { + if ((multiselect.position.left + newSize.width)>=documentSize.width) { newSize.width -= (multiselect.position.left + newSize.width) - documentSize.width + 2 } @@ -167,8 +167,8 @@ multiselect.getSize = function() { if (!visible.multiselect()) return false - let $elem = $('#multiselect'), - offset = $elem.offset() + let $elem = $('#multiselect') + let offset = $elem.offset() return { top : offset.top, @@ -181,9 +181,9 @@ multiselect.getSize = function() { multiselect.getSelection = function(e) { - let tolerance = 150, - ids = [], - size = multiselect.getSize() + let tolerance = 150 + let ids = [] + let size = multiselect.getSize() if (visible.contextMenu()) return false if (!visible.multiselect()) return false @@ -192,19 +192,19 @@ multiselect.getSelection = function(e) { let offset = $(this).offset() - if (offset.top>=(size.top-tolerance) && - offset.left>=(size.left-tolerance) && - (offset.top+206)<=(size.top+size.height+tolerance) && - (offset.left+206)<=(size.left+size.width+tolerance)) { + if (offset.top>=(size.top - tolerance) && + offset.left>=(size.left - tolerance) && + (offset.top + 206)<=(size.top + size.height + tolerance) && + (offset.left + 206)<=(size.left + size.width + tolerance)) { - let id = $(this).data('id') + let id = $(this).data('id') - if (id!=='0' && id!==0 && id!=='f' && id!=='s' && id!=='r' && id!=null) { + if (id!=='0' && id!==0 && id!=='f' && id!=='s' && id!=='r' && id!=null) { - ids.push(id) - $(this).addClass('active') + ids.push(id) + $(this).addClass('active') - } + } } diff --git a/src/scripts/photo.js b/src/scripts/photo.js index c486313..7c73d44 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -71,8 +71,8 @@ photo.preloadNext = function(photoID) { album.json.content[photoID] && album.json.content[photoID].nextPhoto!='') { - let nextPhoto = album.json.content[photoID].nextPhoto, - url = album.json.content[nextPhoto].url + let nextPhoto = album.json.content[photoID].nextPhoto + let url = album.json.content[nextPhoto].url $('head [data-prefetch]').remove() $('head').append(``) @@ -152,7 +152,7 @@ photo.next = function(animate) { photo.duplicate = function(photoIDs) { if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] albums.refresh() @@ -171,13 +171,13 @@ photo.duplicate = function(photoIDs) { photo.delete = function(photoIDs) { - let action = {}, - cancel = {}, - msg = '', - photoTitle = '' + let action = {} + let cancel = {} + let msg = '' + let photoTitle = '' if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] if (photoIDs.length===1) { @@ -192,8 +192,8 @@ photo.delete = function(photoIDs) { action.fn = function() { - let nextPhoto, - previousPhoto + let nextPhoto + let previousPhoto basicModal.close() @@ -269,11 +269,11 @@ photo.delete = function(photoIDs) { photo.setTitle = function(photoIDs) { - let oldTitle = '', - msg = '' + let oldTitle = '' + let msg = '' if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] if (photoIDs.length===1) { @@ -300,8 +300,8 @@ photo.setTitle = function(photoIDs) { }) let params = { - photoIDs: photoIDs.join(), - title: newTitle + photoIDs : photoIDs.join(), + title : newTitle } api.post('Photo::setTitle', params, function(data) { @@ -335,11 +335,11 @@ photo.setTitle = function(photoIDs) { photo.setAlbum = function(photoIDs, albumID) { - let nextPhoto, - previousPhoto + let nextPhoto + let previousPhoto if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] if (visible.photo) lychee.goto(album.getID()) @@ -416,7 +416,7 @@ photo.setPublic = function(photoID, e) { } basicModal.show({ - body: "

This photo is located in a public album. To make this photo private or public, edit the visibility of the associated album.

", + body: '

This photo is located in a public album. To make this photo private or public, edit the visibility of the associated album.

', buttons: { action: { title: 'Show Album', @@ -500,11 +500,11 @@ photo.setDescription = function(photoID) { photo.editTags = function(photoIDs) { - let oldTags = '', - msg = '' + let oldTags = '' + let msg = '' if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] // Get tags if (visible.photo()) oldTags = photo.json.tags @@ -591,14 +591,14 @@ photo.deleteTag = function(photoID, index) { // Save photo.json.tags = tags.toString() - photo.setTags([photoID], photo.json.tags) + photo.setTags([ photoID ], photo.json.tags) } photo.share = function(photoID, service) { - let link = '', - url = photo.getViewLink(photoID) + let link = '' + let url = photo.getViewLink(photoID) switch (service) { case 'twitter': @@ -627,8 +627,8 @@ photo.share = function(photoID, service) { photo.getArchive = function(photoID) { - let link, - url = `${ api.path }?function=Photo::getArchive&photoID=${ photoID }` + let link + let url = `${ api.path }?function=Photo::getArchive&photoID=${ photoID }` if (location.href.indexOf('index.html')>0) link = location.href.replace(location.hash, '').replace('index.html', url) else link = location.href.replace(location.hash, '') + url diff --git a/src/scripts/search.js b/src/scripts/search.js index af7e142..a723a1c 100755 --- a/src/scripts/search.js +++ b/src/scripts/search.js @@ -19,9 +19,9 @@ search.find = function(term) { api.post('search', { term }, function(data) { - let html = '', - albumsData = '', - photosData = '' + let html = '' + let albumsData = '' + let photosData = '' // Build albums if (data && data.albums) { diff --git a/src/scripts/settings.js b/src/scripts/settings.js index 876ef8b..db5810f 100644 --- a/src/scripts/settings.js +++ b/src/scripts/settings.js @@ -9,11 +9,11 @@ settings.createConfig = function() { const action = function(data) { - let dbName = data.dbName || '', - dbUser = data.dbUser || '', - dbPassword = data.dbPassword || '', - dbHost = data.dbHost || '', - dbTablePrefix = data.dbTablePrefix || '' + let dbName = data.dbName || '' + let dbUser = data.dbUser || '' + let dbPassword = data.dbPassword || '' + let dbHost = data.dbHost || '' + let dbTablePrefix = data.dbTablePrefix || '' if (dbUser.length<1) { basicModal.error('dbUser') @@ -140,8 +140,8 @@ settings.createLogin = function() { const action = function(data) { - let username = data.username, - password = data.password + let username = data.username + let password = data.password if (username.length<1) { basicModal.error('username') @@ -204,9 +204,9 @@ settings.setLogin = function() { const action = function(data) { - let oldPassword = data.oldPassword || '', - username = data.username || '', - password = data.password || '' + let oldPassword = data.oldPassword || '' + let username = data.username || '' + let password = data.password || '' if (oldPassword.length<1) { basicModal.error('oldPassword') @@ -269,8 +269,8 @@ settings.setLogin = function() { settings.setSorting = function() { - let sortingPhotos = [], - sortingAlbums = [] + let sortingPhotos = [] + let sortingAlbums = [] const action = function() { diff --git a/src/scripts/sidebar.js b/src/scripts/sidebar.js index f628506..8f1770b 100644 --- a/src/scripts/sidebar.js +++ b/src/scripts/sidebar.js @@ -30,14 +30,14 @@ sidebar.bind = function() { // event handlers should be removed before binding a new one. // Event Name - let eventName = lychee.getEventName(); + let eventName = lychee.getEventName() sidebar .dom('#edit_title') .off(eventName) .on(eventName, function() { - if (visible.photo()) photo.setTitle([photo.getID()]) - else if (visible.album()) album.setTitle([album.getID()]) + if (visible.photo()) photo.setTitle([ photo.getID() ]) + else if (visible.album()) album.setTitle([ album.getID() ]) }) sidebar @@ -52,7 +52,7 @@ sidebar.bind = function() { .dom('#edit_tags') .off(eventName) .on(eventName, function() { - photo.editTags([photo.getID()]) + photo.editTags([ photo.getID() ]) }) sidebar @@ -114,10 +114,10 @@ sidebar.createStructure.photo = function(data) { if (data==null || data==='') return false - let editable = false, - exifHash = data.takestamp + data.make + data.model + data.shutter + data.aperture + data.focal + data.iso, - structure = {}, - _public = '' + let editable = false + let exifHash = data.takestamp + data.make + data.model + data.shutter + data.aperture + data.focal + data.iso + let structure = {} + let _public = '' // Enable editable when user logged in if (lychee.publicMode===false) editable = true @@ -220,12 +220,12 @@ sidebar.createStructure.album = function(data) { if (data==null || data==='') return false - let editable = false, - structure = {}, - _public = '', - visible = '', - downloadable = '', - password = '' + let editable = false + let structure = {} + let _public = '' + let visible = '' + let downloadable = '' + let password = '' // Enable editable when user logged in if (lychee.publicMode===false) editable = true @@ -367,8 +367,8 @@ sidebar.render = function(structure) { let renderTags = function(section) { - let _html = '', - editable = '' + let _html = '' + let editable = '' // Add edit-icon to the value when editable if (section.editable===true) editable = build.editIcon('edit_tags') diff --git a/src/scripts/upload.js b/src/scripts/upload.js index 2d473af..9f546e7 100755 --- a/src/scripts/upload.js +++ b/src/scripts/upload.js @@ -40,16 +40,16 @@ upload.start = { local: function(files) { - let albumID = album.getID(), - error = false, - warning = false + let albumID = album.getID() + let error = false + let warning = false const process = function(files, file) { - let formData = new FormData(), - xhr = new XMLHttpRequest(), - pre_progress = 0, - progress = 0 + let formData = new FormData() + let xhr = new XMLHttpRequest() + let pre_progress = 0 + let progress = 0 const finish = function() { @@ -122,8 +122,8 @@ upload.start = { xhr.onload = function() { - let wait = false, - errorText = '' + let wait = false + let errorText = '' file.ready = true @@ -131,7 +131,7 @@ upload.start = { if (xhr.status===200 && xhr.responseText==='1') { // Success - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') .status') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status') .html('Finished') .addClass('success') @@ -143,7 +143,7 @@ upload.start = { error = true // Error Status - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') .status') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status') .html('Failed') .addClass('error') @@ -153,7 +153,7 @@ upload.start = { warning = true // Warning Status - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') .status') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status') .html('Skipped') .addClass('warning') @@ -163,13 +163,13 @@ upload.start = { error = true // Error Status - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') .status') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status') .html('Failed') .addClass('error') } - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') p.notice') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') p.notice') .html(errorText) .show() @@ -210,11 +210,11 @@ upload.start = { // Scroll to the uploading file let scrollPos = 0 - if ((file.num+1)>4) scrollPos = (file.num + 1 - 4) * 40 + if ((file.num + 1)>4) scrollPos = (file.num + 1 - 4) * 40 $('.basicModal .rows').scrollTop(scrollPos) // Set status to processing - $('.basicModal .rows .row:nth-child(' + (file.num+1) + ') .status').html('Processing') + $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status').html('Processing') // Upload next file if (file.next!=null) process(files, file.next) @@ -236,7 +236,7 @@ upload.start = { files[i].ready = false files[i].supported = true - if (i < files.length-1) files[i].next = files[i+1] + if (i < files.length-1) files[i].next = files[i + 1] else files[i].next = null // Check if file is supported @@ -480,7 +480,7 @@ upload.start = { } // Remove last comma - links = links.substr(0, links.length-1) + links = links.substr(0, links.length - 1) upload.show('Importing from Dropbox', files, function() { diff --git a/src/scripts/view.js b/src/scripts/view.js index 099295a..02cc498 100644 --- a/src/scripts/view.js +++ b/src/scripts/view.js @@ -26,8 +26,8 @@ view.albums = { init: function() { - let smartData = '', - albumsData = '' + let smartData = '' + let albumsData = '' // Smart Albums if (lychee.publicMode===false) { @@ -271,8 +271,8 @@ view.album = { if ((visible.album() || !album.json.init) && !visible.photo()) { - let structure = sidebar.createStructure.album(album.json), - html = sidebar.render(structure) + let structure = sidebar.createStructure.album(album.json) + let html = sidebar.render(structure) sidebar.dom('.sidebar__wrapper').html(html) sidebar.bind() @@ -408,27 +408,33 @@ view.photo = { lychee.imageview.html(build.imageview(photo.json, visible.header())) - let $nextArrow = lychee.imageview.find('a#next'), - $previousArrow = lychee.imageview.find('a#previous'), - photoID = photo.getID(), - hasNext = album.json && album.json.content && album.json.content[photoID] && album.json.content[photoID].nextPhoto!=='', - hasPrevious = album.json && album.json.content && album.json.content[photoID] && album.json.content[photoID].previousPhoto!=='' + let $nextArrow = lychee.imageview.find('a#next') + let $previousArrow = lychee.imageview.find('a#previous') + let photoID = photo.getID() + let hasNext = album.json && album.json.content && album.json.content[photoID] && album.json.content[photoID].nextPhoto!=='' + let hasPrevious = album.json && album.json.content && album.json.content[photoID] && album.json.content[photoID].previousPhoto!=='' - if (hasNext===false || lychee.viewMode===true) { $nextArrow.hide() } - else { + if (hasNext===false || lychee.viewMode===true) { - let nextPhotoID = album.json.content[photoID].nextPhoto, - nextPhoto = album.json.content[nextPhotoID] + $nextArrow.hide() + + } else { + + let nextPhotoID = album.json.content[photoID].nextPhoto + let nextPhoto = album.json.content[nextPhotoID] $nextArrow.css('background-image', lychee.html`linear-gradient(to bottom, rgba(0, 0, 0, .4), rgba(0, 0, 0, .4)), url("$${ nextPhoto.thumbUrl }")`) } - if (hasPrevious===false || lychee.viewMode===true) { $previousArrow.hide() } - else { + if (hasPrevious===false || lychee.viewMode===true) { - let previousPhotoID = album.json.content[photoID].previousPhoto, - previousPhoto = album.json.content[previousPhotoID] + $previousArrow.hide() + + } else { + + let previousPhotoID = album.json.content[photoID].previousPhoto + let previousPhoto = album.json.content[previousPhotoID] $previousArrow.css('background-image', lychee.html`linear-gradient(to bottom, rgba(0, 0, 0, .4), rgba(0, 0, 0, .4)), url("$${ previousPhoto.thumbUrl }")`) @@ -438,8 +444,8 @@ view.photo = { sidebar: function() { - let structure = sidebar.createStructure.photo(photo.json), - html = sidebar.render(structure) + let structure = sidebar.createStructure.photo(photo.json) + let html = sidebar.render(structure) sidebar.dom('.sidebar__wrapper').html(html) sidebar.bind() diff --git a/src/scripts/view/main.js b/src/scripts/view/main.js index 5f03cbe..e7a2725 100644 --- a/src/scripts/view/main.js +++ b/src/scripts/view/main.js @@ -11,8 +11,8 @@ lychee.content = $('.content') lychee.getEventName = function() { - let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement), - eventName = (touchendSupport===true ? 'touchend' : 'click') + let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement) + let eventName = (touchendSupport===true ? 'touchend' : 'click') return eventName @@ -39,8 +39,8 @@ lychee.html = function(literalSections, ...substs) { // Use raw literal sections: we don’t want // backslashes (\n etc.) to be interpreted - let raw = literalSections.raw, - result = '' + let raw = literalSections.raw + let result = '' substs.forEach((subst, i) => { @@ -63,7 +63,7 @@ lychee.html = function(literalSections, ...substs) { // Take care of last literal section // (Never fails, because an empty template string // produces one literal section, an empty string) - result += raw[raw.length-1] + result += raw[raw.length - 1] return result @@ -127,8 +127,8 @@ const loadPhotoInfo = function(photoID) { imageview.addClass('fadeIn').show() // Render Sidebar - let structure = sidebar.createStructure.photo(data), - html = sidebar.render(structure) + let structure = sidebar.createStructure.photo(data) + let html = sidebar.render(structure) sidebar.dom('.sidebar__wrapper').html(html) sidebar.bind() From 454a503196d3f13067dc771782af3f4682c67c5e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 15:21:40 +0100 Subject: [PATCH 017/183] Rebuild --- dist/main.css | Bin 31994 -> 32020 bytes dist/main.js | Bin 190680 -> 192549 bytes dist/view.js | Bin 105146 -> 107024 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.css b/dist/main.css index 63c0582915a29247aa0cf0cd7c98eb4bf278166f..ffedd78f8afda0cf78a65f28e0c244ac7ee0f00b 100755 GIT binary patch delta 27 jcmezMlX1!~#tl-=Ji58Xy6HukDY`}Z<(qk&-&q0xrW6Y+ delta 14 WcmbR8i}BY_#tl-=n@yY_SONezJ_ghP diff --git a/dist/main.js b/dist/main.js index cb570890acad884cf55aa08c1a8e1ecaf10578bb..a813e60400c5aec0a6f623fc4dab3763c33d450a 100644 GIT binary patch delta 31629 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 Y7pw_c9WNgHY}qsD@M7yP%I;(T8>lu4L;wH) delta 30029 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 diff --git a/dist/view.js b/dist/view.js index 388f4a0a27aca4e07152ae58ff35b0476b1af4a3..825385ae2a3ccab785da8aa5f1f5cd1e85e3f538 100644 GIT binary patch delta 29808 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 delta 28206 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 t43`w?{8d4Q Date: Sun, 24 Jan 2016 15:39:12 +0100 Subject: [PATCH 018/183] Fixed the loading bar --- src/scripts/loadingBar.js | 6 +++--- src/styles/_header.scss | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripts/loadingBar.js b/src/scripts/loadingBar.js index f656511..732d0e5 100755 --- a/src/scripts/loadingBar.js +++ b/src/scripts/loadingBar.js @@ -29,7 +29,7 @@ loadingBar.show = function(status, errorText) { if (!errorText) errorText = 'Whoops, it looks like something went wrong. Please reload the site and try again!' // Move header down - if (visible.header()) header.dom().addClass('header__error') + if (visible.header()) header.dom().addClass('header--error') // Modify loading loadingBar.dom() @@ -56,7 +56,7 @@ loadingBar.show = function(status, errorText) { loadingBar._timeout = setTimeout(() => { // Move header down - if (visible.header()) header.dom().addClass('header__loading') + if (visible.header()) header.dom().addClass('header--loading') // Modify loading loadingBar.dom() @@ -81,7 +81,7 @@ loadingBar.hide = function(force) { loadingBar.status = null // Move header up - header.dom().removeClass('header__error header__loading') + header.dom().removeClass('header--error header--loading') // Set timeout clearTimeout(loadingBar._timeout) diff --git a/src/styles/_header.scss b/src/styles/_header.scss index 96f29fe..f727063 100644 --- a/src/styles/_header.scss +++ b/src/styles/_header.scss @@ -19,7 +19,7 @@ background: none; border-bottom: none; - .header__error { background-color: rgba(10, 10, 10, .99); } + &.header--error { background-color: rgba(10, 10, 10, .99); } } // Toolbars -------------------------------------------------------------- // From 61c13e36a0829b2d836730272bab1ecdf7b85195 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 15:39:22 +0100 Subject: [PATCH 019/183] Rebuild --- dist/main.css | Bin 32020 -> 32019 bytes dist/main.js | Bin 192549 -> 192549 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dist/main.js diff --git a/dist/main.css b/dist/main.css index ffedd78f8afda0cf78a65f28e0c244ac7ee0f00b..7edc009c68d977ae6e352ed9e987e1b4388a9587 100755 GIT binary patch delta 24 gcmbR8i*fQV#tqY*IQ2486H`))bagi`bSkz20EH$A?#tqY*xD@mk}6M From 9e52f93a59d83099c799e02331c182eb19ded32f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 16:51:09 +0100 Subject: [PATCH 020/183] Removed database updates for versions <= 2.5.0 --- php/database/update_020100.php | 44 ---------------------------------- php/database/update_020101.php | 20 ---------------- php/database/update_020200.php | 23 ------------------ php/modules/Database.php | 3 --- 4 files changed, 90 deletions(-) delete mode 100644 php/database/update_020100.php delete mode 100644 php/database/update_020101.php delete mode 100644 php/database/update_020200.php diff --git a/php/database/update_020100.php b/php/database/update_020100.php deleted file mode 100644 index a9c9c9b..0000000 --- a/php/database/update_020100.php +++ /dev/null @@ -1,44 +0,0 @@ -query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `tags` VARCHAR( 1000 ) NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'dropboxKey' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); -if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('dropboxKey', '')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'version' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); -if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('version', '020100')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} else { - if (Database::setVersion($database, '020100')===false) return false; -} - -?> \ No newline at end of file diff --git a/php/database/update_020101.php b/php/database/update_020101.php deleted file mode 100644 index 435477e..0000000 --- a/php/database/update_020101.php +++ /dev/null @@ -1,20 +0,0 @@ -query($query); -if (!$result) { - Log::error($database, 'update_020101', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set version -if (Database::setVersion($database, '020101')===false) return false; - -?> \ No newline at end of file diff --git a/php/database/update_020200.php b/php/database/update_020200.php deleted file mode 100644 index 161ccc2..0000000 --- a/php/database/update_020200.php +++ /dev/null @@ -1,23 +0,0 @@ -query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `visible` TINYINT(1) NOT NULL DEFAULT 1", array(LYCHEE_TABLE_ALBUMS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020200', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Set version -if (Database::setVersion($database, '020200')===false) return false; - -?> \ No newline at end of file diff --git a/php/modules/Database.php b/php/modules/Database.php index 07d4035..3b088ed 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -10,9 +10,6 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Database extends Module { private static $versions = array( - '020100', #2.1 - '020101', #2.1.1 - '020200', #2.2 '020500', #2.5 '020505', #2.5.5 '020601', #2.6.1 From f7e624ca8b10d2e9e0fc07f24ef3a14fcc8e8b3d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 17:09:49 +0100 Subject: [PATCH 021/183] Fixed 'Full Photo' in view.php --- src/scripts/view/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/view/main.js b/src/scripts/view/main.js index e7a2725..329892e 100644 --- a/src/scripts/view/main.js +++ b/src/scripts/view/main.js @@ -88,7 +88,7 @@ $(document).ready(function() { // Direct Link header.dom('#button_direct').on(eventName, function() { - let link = $('#imageview #image').css('background-image').replace(/"/g,'').replace(/url\(|\)$/ig, '') + let link = $('#imageview img').attr('src').replace(/"/g,'').replace(/url\(|\)$/ig, '') window.open(link, '_newtab') }) From 24c883a661b7a617e146b1036118c94bd2564430 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 17:10:23 +0100 Subject: [PATCH 022/183] Use default value to define defineTablePrefix --- php/define.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/php/define.php b/php/define.php index 65b99d6..01b59fd 100644 --- a/php/define.php +++ b/php/define.php @@ -31,7 +31,7 @@ define('LYCHEE_URL_UPLOADS_BIG', 'uploads/big/'); define('LYCHEE_URL_UPLOADS_MEDIUM', 'uploads/medium/'); define('LYCHEE_URL_UPLOADS_THUMB', 'uploads/thumb/'); -function defineTablePrefix($dbTablePrefix) { +function defineTablePrefix($dbTablePrefix = '') { # This part is wrapped into a function, because it needs to be called # after the config-file has been loaded. Other defines are available @@ -39,8 +39,7 @@ function defineTablePrefix($dbTablePrefix) { # Parse table prefix # Old users do not have the table prefix stored in their config-file - if (!isset($dbTablePrefix)||$dbTablePrefix==='') $dbTablePrefix = ''; - else $dbTablePrefix .= '_'; + if ($dbTablePrefix!=='') $dbTablePrefix .= '_'; # Define tables define('LYCHEE_TABLE_ALBUMS', $dbTablePrefix . 'lychee_albums'); From 36b1b403259b00d3e4d81ffbbac89b5d3107b773 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 17:10:54 +0100 Subject: [PATCH 023/183] Added 'final' to access classes --- php/access/Admin.php | 2 +- php/access/Guest.php | 2 +- php/access/Installation.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/php/access/Admin.php b/php/access/Admin.php index 251328e..8d02c74 100644 --- a/php/access/Admin.php +++ b/php/access/Admin.php @@ -8,7 +8,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); if (!defined('LYCHEE_ACCESS_ADMIN')) exit('Error: You are not allowed to access this area!'); -class Admin extends Access { +final class Admin extends Access { public function check($fn) { diff --git a/php/access/Guest.php b/php/access/Guest.php index 2cfab14..94d9e31 100644 --- a/php/access/Guest.php +++ b/php/access/Guest.php @@ -8,7 +8,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); if (!defined('LYCHEE_ACCESS_GUEST')) exit('Error: You are not allowed to access this area!'); -class Guest extends Access { +final class Guest extends Access { public function check($fn) { diff --git a/php/access/Installation.php b/php/access/Installation.php index ef1b21f..67c8811 100644 --- a/php/access/Installation.php +++ b/php/access/Installation.php @@ -8,7 +8,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to access this area!'); -class Installation extends Access { +final class Installation extends Access { public function check($fn) { From c8a3a92c3f10e19fdcd3ee57b2cb83d863cf05ce Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 17:11:05 +0100 Subject: [PATCH 024/183] Rebuild --- dist/view.js | Bin 107024 -> 107009 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/view.js b/dist/view.js index 825385ae2a3ccab785da8aa5f1f5cd1e85e3f538..084bab82048e3368096d073e4663f0a2df545500 100644 GIT binary patch delta 33 pcmbPmgst%iTf-K{CG+?*bJLYH^%6@;iZqmpi;}k=n#btJ3;^LW4441_ delta 48 zcmZoX!ZzUuTf-K{CG+HzGjkKuQ56!Q$ID&tvps1^~ob B5*Gjf From 0dffa5c765647ef8fb506b0c7a5599834e3bea32 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 18:38:26 +0100 Subject: [PATCH 025/183] Dropped update support for versions < 2.7 --- docs/Update.md | 13 ++- php/database/update_020500.php | 156 --------------------------------- php/database/update_020505.php | 24 ----- php/database/update_020601.php | 24 ----- php/database/update_020602.php | 47 ---------- php/modules/Database.php | 4 - 6 files changed, 9 insertions(+), 259 deletions(-) delete mode 100644 php/database/update_020500.php delete mode 100644 php/database/update_020505.php delete mode 100644 php/database/update_020601.php delete mode 100644 php/database/update_020602.php diff --git a/docs/Update.md b/docs/Update.md index 4fbec1d..ad8529c 100644 --- a/docs/Update.md +++ b/docs/Update.md @@ -1,15 +1,20 @@ +### Update requirements + +- Your system must comply with the latest [system requirements](https://github.com/electerious/Lychee/blob/master/docs/Installation.md) of Lychee. +- Ensure that your current version is greater than 2.7.0. Updates from older Lychee versions aren't supported. + ### Update with `git` -The easiest way to update Lychee is with `git`: +Updating Lychee with `git` is the easiest way: git pull - + ### Update manually -1. Download the [newest Version](https://github.com/electerious/Lychee/archive/master.zip) +1. Download the [newest Version](https://github.com/electerious/Lychee/release) 2. Replace all existing files, excluding `uploads/` and `data/` 3. Open Lychee (and enter your database details) ### Changelog -Take a look at the [Changelog](Changelog.md) to see what's new. +Take a look at the [Changelog](Changelog.md) to see what's new. \ No newline at end of file diff --git a/php/database/update_020500.php b/php/database/update_020500.php deleted file mode 100644 index 9892961..0000000 --- a/php/database/update_020500.php +++ /dev/null @@ -1,156 +0,0 @@ -query($query); -if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('plugins', '')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Add `takestamp` -$query = Database::prepare($database, "SELECT `takestamp` FROM `?` LIMIT 1;", array(LYCHEE_TABLE_PHOTOS)); -if (!$database->query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `takestamp` INT(11) DEFAULT NULL", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Convert to `takestamp` -$query = Database::prepare($database, "SELECT `takedate`, `taketime` FROM `?` LIMIT 1;", array(LYCHEE_TABLE_PHOTOS)); -if ($database->query($query)) { - $query = Database::prepare($database, "SELECT `id`, `takedate`, `taketime` FROM `?` WHERE `takedate` <> '' AND `taketime` <> ''", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } - while ($photo = $result->fetch_object()) { - $takestamp = strtotime($photo->takedate . $photo->taketime); - $query = Database::prepare($database, "UPDATE `?` SET `takestamp` = '?' WHERE `id` = '?'", array(LYCHEE_TABLE_PHOTOS, $takestamp, $photo->id)); - $database->query($query); - } - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `takedate`;", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `taketime`", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); -} - -# Remove `import_name` -$query = Database::prepare($database, "SELECT `import_name` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); -if ($database->query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `import_name`", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); -} - -# Remove `sysdate` and `systime` -$query = Database::prepare($database, "SELECT `sysdate`, `systime` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); -if ($database->query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `sysdate`", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `systime`", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); -} - -# Add `sysstamp` -$query = Database::prepare($database, "SELECT `sysstamp` FROM `?` LIMIT 1", array(LYCHEE_TABLE_ALBUMS)); -if (!$database->query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `sysstamp` INT(11) DEFAULT NULL", array(LYCHEE_TABLE_ALBUMS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Convert to `sysstamp` -$query = Database::prepare($database, "SELECT `sysdate` FROM `?` LIMIT 1", array(LYCHEE_TABLE_ALBUMS)); -if ($database->query($query)) { - $query = Database::prepare($database, "SELECT `id`, `sysdate` FROM `?`", array(LYCHEE_TABLE_ALBUMS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } - while ($album = $result->fetch_object()) { - $sysstamp = strtotime($album->sysdate); - $query = Database::prepare($database, "UPDATE `?` SET `sysstamp` = '?' WHERE `id` = '?'", array(LYCHEE_TABLE_ALBUMS, $sysstamp, $album->id)); - $database->query($query); - } - $query = Database::prepare($database, "ALTER TABLE `?` DROP COLUMN `sysdate`", array(LYCHEE_TABLE_ALBUMS)); - $result = $database->query($query); -} - -# Set character of database -$result = $database->query("ALTER DATABASE $dbName CHARACTER SET utf8 COLLATE utf8_general_ci;"); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set character -$query = Database::prepare($database, "ALTER TABLE `?` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci", array(LYCHEE_TABLE_ALBUMS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set character -$query = Database::prepare($database, "ALTER TABLE `?` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci", array(LYCHEE_TABLE_PHOTOS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set character -$query = Database::prepare($database, "ALTER TABLE `?` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set album password length to 100 (for longer hashes) -$query = Database::prepare($database, "ALTER TABLE `?` CHANGE `password` `password` VARCHAR(100)", array(LYCHEE_TABLE_ALBUMS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set make length to 50 -$query = Database::prepare($database, "ALTER TABLE `?` CHANGE `make` `make` VARCHAR(50)", array(LYCHEE_TABLE_PHOTOS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Reset sorting -$query = Database::prepare($database, "UPDATE ? SET value = 'ORDER BY takestamp DESC' WHERE `key` = 'sorting' AND `value` LIKE '%UNIX_TIMESTAMP%'", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); -if (!$result) { - Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; -} - -# Set version -if (Database::setVersion($database, '020500')===false) return false; - -?> \ No newline at end of file diff --git a/php/database/update_020505.php b/php/database/update_020505.php deleted file mode 100644 index 6c25fa0..0000000 --- a/php/database/update_020505.php +++ /dev/null @@ -1,24 +0,0 @@ -query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `checksum` VARCHAR(100) DEFAULT NULL", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020505', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Set version -if (Database::setVersion($database, '020505')===false) return false; - -?> \ No newline at end of file diff --git a/php/database/update_020601.php b/php/database/update_020601.php deleted file mode 100644 index 453114b..0000000 --- a/php/database/update_020601.php +++ /dev/null @@ -1,24 +0,0 @@ -query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `downloadable` TINYINT(1) NOT NULL DEFAULT 1", array(LYCHEE_TABLE_ALBUMS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020601', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Set version -if (Database::setVersion($database, '020601')===false) return false; - -?> \ No newline at end of file diff --git a/php/database/update_020602.php b/php/database/update_020602.php deleted file mode 100644 index a97f263..0000000 --- a/php/database/update_020602.php +++ /dev/null @@ -1,47 +0,0 @@ -query($query); -if (!$result) { - Log::error($database, 'update_020602', __LINE__, 'Could not find photos without checksum (' . $database->error . ')'); - return false; -} -while ($photo = $result->fetch_object()) { - $checksum = sha1_file(LYCHEE_UPLOADS_BIG . $photo->url); - if ($checksum!==false) { - $query = Database::prepare($database, "UPDATE `?` SET `checksum` = '?' WHERE `id` = '?'", array(LYCHEE_TABLE_PHOTOS, $checksum, $photo->id)); - $setChecksum = $database->query($query); - if (!$setChecksum) { - Log::error($database, 'update_020602', __LINE__, 'Could not update checksum (' . $database->error . ')'); - return false; - } - } else { - Log::error($database, 'update_020602', __LINE__, 'Could not calculate checksum for photo with id ' . $photo->id); - return false; - } -} - -# Add Imagick -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'imagick' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); -if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('imagick', '1')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); - if (!$result) { - Log::error($database, 'update_020602', __LINE__, 'Could not update database (' . $database->error . ')'); - return false; - } -} - -# Set version -if (Database::setVersion($database, '020602')===false) return false; - -?> \ No newline at end of file diff --git a/php/modules/Database.php b/php/modules/Database.php index 3b088ed..aa56c56 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -10,10 +10,6 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Database extends Module { private static $versions = array( - '020500', #2.5 - '020505', #2.5.5 - '020601', #2.6.1 - '020602', #2.6.2 '020700', #2.7.0 '030000', #3.0.0 '030001', #3.0.1 From 17e5dba9793f2e240410f66ea7f7b551c8d0c24b Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:14:20 +0100 Subject: [PATCH 026/183] Singleton pattern for Settings::get(), Database::get() and Plugins::get() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What could properly go wrong? ¯\_(ツ)_/¯ --- dist/main.js | Bin 192549 -> 192541 bytes docs/Plugins.md | 36 +-- php/access/Access.php | 17 +- php/access/Admin.php | 66 +++-- php/access/Guest.php | 21 +- php/access/Installation.php | 9 +- php/api.php | 33 +-- php/autoload.php | 8 + php/database/update_020700.php | 24 +- php/database/update_030000.php | 20 +- php/database/update_030001.php | 40 ++-- php/database/update_030003.php | 12 +- php/modules/Album.php | 187 +++++++-------- php/modules/Config.php | 79 ++++++ php/modules/Database.php | 423 +++++++++++++++++---------------- php/modules/Import.php | 45 ++-- php/modules/Log.php | 20 +- php/modules/Module.php | 6 +- php/modules/Photo.php | 205 ++++++++-------- php/modules/Plugins.php | 47 ++-- php/modules/Session.php | 39 +-- php/modules/Settings.php | 91 ++++--- php/modules/misc.php | 26 +- plugins/check/index.php | 8 +- plugins/displaylog/index.php | 9 +- src/scripts/settings.js | 2 +- view.php | 8 +- 27 files changed, 726 insertions(+), 755 deletions(-) mode change 100755 => 100644 dist/main.js create mode 100644 php/modules/Config.php diff --git a/dist/main.js b/dist/main.js old mode 100755 new mode 100644 index e6e9190a58c6284c2014aff798cb8606707054e2..7fc8c459c694ab4108d722023329b69ec9d13a2e GIT binary patch delta 60 zcmZ4bfP3x(?uHh|EleUEg3kGQX_@I(R>?)Fi6yB@Iz`hP+ZaW+J9RMGq)o4X$0W_j QHJx!8lkoPn@0cnW0k7{BqyPW_ delta 78 zcmbRHfP3i!?uHh|EleUEk}ioQiAjmYsa96WMX8A;sm}R%X_@ItIz`hP+ZaW+TXitm iqzQ19Wfo^9<)rErXQrekB^FID6lD_LKJy(@3nKu2!yI$~ diff --git a/docs/Plugins.md b/docs/Plugins.md index deef245..e47a7ce 100644 --- a/docs/Plugins.md +++ b/docs/Plugins.md @@ -11,33 +11,19 @@ The plugin-system of Lychee allows you to execute scripts, when a certain action ### How to create a plugin -1. Create a folder in `plugins/` -2. Create an `index.php` within the new folder and with the following content: +1. Create a folder in `plugins/` (e.g. `plugins/ExamplePlugin/`) +2. Create an `ExamplePlugin.php` file within the new folder and add the following content: ```php database = $database; - $this->settings = $settings; - - # Add more code here if wanted + # Add code here if wanted # __construct() will be called every time Lychee gets called # Make sure this part is performant @@ -52,8 +38,9 @@ class ExamplePlugin implements SplObserver { if ($subject->action!=='Photo::add:before') return false; # Do something when Photo::add:before gets called - # $this->database => The database of Lychee - # $this->settings => The settings of Lychee + # Database::get() => Database connection of Lychee + # Settings::get() => Settings of Lychee + # $subject->action => Called hook # $subject->args => Params passed to the original function return true; @@ -62,15 +49,14 @@ class ExamplePlugin implements SplObserver { } -# Register your plugin -$plugins->attach(new ExamplePlugin($database, $settings)); +?> ``` -3. Add the plugin-path to the database of Lychee +3. Add the class name to the database of Lychee -Select the table `lychee_settings` and edit the value of `plugins` to the path of your plugin. The path must be relative from the `plugins/`-folder: `ExamplePlugin/index.php`. +Select the table `lychee_settings` and add the name of the class to the value of `plugins` (e.g. `ExamplePlugin`). Please ensure that the folder has the same name as the class and as the file. -Divide multiple plugins with semicolons: `Plugin01/index.php;Plugin02/index.php`. +Divide multiple plugins with semicolons: `ExamplePlugin;ExampleTwoPlugin`. ### Available hooks diff --git a/php/access/Access.php b/php/access/Access.php index 8a145c8..cf515c4 100644 --- a/php/access/Access.php +++ b/php/access/Access.php @@ -7,22 +7,9 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -class Access { +abstract class Access { - protected $database = null; - protected $plugins = null; - protected $settings = null; - - public function __construct($database, $plugins, $settings) { - - # Init vars - $this->database = $database; - $this->plugins = $plugins; - $this->settings = $settings; - - return true; - - } + abstract protected function check($fn); } diff --git a/php/access/Admin.php b/php/access/Admin.php index 8d02c74..59917cf 100644 --- a/php/access/Admin.php +++ b/php/access/Admin.php @@ -6,7 +6,6 @@ ### if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -if (!defined('LYCHEE_ACCESS_ADMIN')) exit('Error: You are not allowed to access this area!'); final class Admin extends Access { @@ -71,7 +70,7 @@ final class Admin extends Access { private function getAlbums() { - $album = new Album($this->database, $this->plugins, $this->settings, null); + $album = new Album(null); echo json_encode($album->getAll(false)); } @@ -79,7 +78,7 @@ final class Admin extends Access { private function getAlbum() { Module::dependencies(isset($_POST['albumID'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']); + $album = new Album($_POST['albumID']); echo json_encode($album->get()); } @@ -87,7 +86,7 @@ final class Admin extends Access { private function addAlbum() { Module::dependencies(isset($_POST['title'])); - $album = new Album($this->database, $this->plugins, $this->settings, null); + $album = new Album(null); echo $album->add($_POST['title']); } @@ -95,7 +94,7 @@ final class Admin extends Access { private function setAlbumTitle() { Module::dependencies(isset($_POST['albumIDs'], $_POST['title'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']); + $album = new Album($_POST['albumIDs']); echo $album->setTitle($_POST['title']); } @@ -103,7 +102,7 @@ final class Admin extends Access { private function setAlbumDescription() { Module::dependencies(isset($_POST['albumID'], $_POST['description'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']); + $album = new Album($_POST['albumID']); echo $album->setDescription($_POST['description']); } @@ -111,7 +110,7 @@ final class Admin extends Access { private function setAlbumPublic() { Module::dependencies(isset($_POST['albumID'], $_POST['password'], $_POST['visible'], $_POST['downloadable'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']); + $album = new Album($_POST['albumID']); echo $album->setPublic($_POST['public'], $_POST['password'], $_POST['visible'], $_POST['downloadable']); } @@ -119,7 +118,7 @@ final class Admin extends Access { private function deleteAlbum() { Module::dependencies(isset($_POST['albumIDs'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']); + $album = new Album($_POST['albumIDs']); echo $album->delete(); } @@ -127,7 +126,7 @@ final class Admin extends Access { private function mergeAlbums() { Module::dependencies(isset($_POST['albumIDs'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']); + $album = new Album($_POST['albumIDs']); echo $album->merge(); } @@ -137,7 +136,7 @@ final class Admin extends Access { private function getPhoto() { Module::dependencies(isset($_POST['photoID'], $_POST['albumID'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']); + $photo = new Photo($_POST['photoID']); echo json_encode($photo->get($_POST['albumID'])); } @@ -145,7 +144,7 @@ final class Admin extends Access { private function setPhotoTitle() { Module::dependencies(isset($_POST['photoIDs'], $_POST['title'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->setTitle($_POST['title']); } @@ -153,7 +152,7 @@ final class Admin extends Access { private function setPhotoDescription() { Module::dependencies(isset($_POST['photoID'], $_POST['description'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']); + $photo = new Photo($_POST['photoID']); echo $photo->setDescription($_POST['description']); } @@ -161,7 +160,7 @@ final class Admin extends Access { private function setPhotoStar() { Module::dependencies(isset($_POST['photoIDs'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->setStar(); } @@ -169,7 +168,7 @@ final class Admin extends Access { private function setPhotoPublic() { Module::dependencies(isset($_POST['photoID'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']); + $photo = new Photo($_POST['photoID']); echo $photo->setPublic(); } @@ -177,7 +176,7 @@ final class Admin extends Access { private function setPhotoAlbum() { Module::dependencies(isset($_POST['photoIDs'], $_POST['albumID'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->setAlbum($_POST['albumID']); } @@ -185,7 +184,7 @@ final class Admin extends Access { private function setPhotoTags() { Module::dependencies(isset($_POST['photoIDs'], $_POST['tags'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->setTags($_POST['tags']); } @@ -193,7 +192,7 @@ final class Admin extends Access { private function duplicatePhoto() { Module::dependencies(isset($_POST['photoIDs'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->duplicate(); } @@ -201,7 +200,7 @@ final class Admin extends Access { private function deletePhoto() { Module::dependencies(isset($_POST['photoIDs'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']); + $photo = new Photo($_POST['photoIDs']); echo $photo->delete(); } @@ -211,7 +210,7 @@ final class Admin extends Access { private function upload() { Module::dependencies(isset($_FILES, $_POST['albumID'], $_POST['tags'])); - $photo = new Photo($this->database, $this->plugins, $this->settings, null); + $photo = new Photo(null); echo $photo->add($_FILES, $_POST['albumID'], '', $_POST['tags']); } @@ -219,7 +218,7 @@ final class Admin extends Access { private function importUrl() { Module::dependencies(isset($_POST['url'], $_POST['albumID'])); - $import = new Import($this->database, $this->plugins, $this->settings); + $import = new Import(); echo $import->url($_POST['url'], $_POST['albumID']); } @@ -227,7 +226,7 @@ final class Admin extends Access { private function importServer() { Module::dependencies(isset($_POST['albumID'], $_POST['path'])); - $import = new Import($this->database, $this->plugins, $this->settings); + $import = new Import(); echo $import->server($_POST['path'], $_POST['albumID']); } @@ -237,7 +236,7 @@ final class Admin extends Access { private function search() { Module::dependencies(isset($_POST['term'])); - echo json_encode(search($this->database, $this->settings, $_POST['term'])); + echo json_encode(search($_POST['term'])); } @@ -247,22 +246,22 @@ final class Admin extends Access { global $dbName; - $session = new Session($this->plugins, $this->settings); - echo json_encode($session->init($this->database, $dbName, false)); + $session = new Session(); + echo json_encode($session->init(false)); } private function login() { Module::dependencies(isset($_POST['user'], $_POST['password'])); - $session = new Session($this->plugins, $this->settings); + $session = new Session(); echo $session->login($_POST['user'], $_POST['password']); } private function logout() { - $session = new Session($this->plugins, $this->settings); + $session = new Session(); echo $session->logout(); } @@ -273,18 +272,16 @@ final class Admin extends Access { Module::dependencies(isset($_POST['username'], $_POST['password'])); if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = ''; - $this->settings = new Settings($this->database); - echo $this->settings->setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); + echo Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); } private function setSorting() { Module::dependencies(isset($_POST['typeAlbums'], $_POST['orderAlbums'], $_POST['typePhotos'], $_POST['orderPhotos'])); - $this->settings = new Settings($this->database); - $sA = $this->settings->setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']); - $sP = $this->settings->setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']); + $sA = Settings::setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']); + $sP = Settings::setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']); if ($sA===true&&$sP===true) echo true; else echo false; @@ -294,8 +291,7 @@ final class Admin extends Access { private function setDropboxKey() { Module::dependencies(isset($_POST['key'])); - $this->settings = new Settings($this->database); - echo $this->settings->setDropboxKey($_POST['key']); + echo Settings::setDropboxKey($_POST['key']); } @@ -304,7 +300,7 @@ final class Admin extends Access { private function getAlbumArchive() { Module::dependencies(isset($_GET['albumID'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']); + $album = new Album($_GET['albumID']); $album->getArchive(); } @@ -312,7 +308,7 @@ final class Admin extends Access { private function getPhotoArchive() { Module::dependencies(isset($_GET['photoID'])); - $photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']); + $photo = new Photo($_GET['photoID']); $photo->getArchive(); } diff --git a/php/access/Guest.php b/php/access/Guest.php index 94d9e31..e153f78 100644 --- a/php/access/Guest.php +++ b/php/access/Guest.php @@ -6,7 +6,6 @@ ### if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -if (!defined('LYCHEE_ACCESS_GUEST')) exit('Error: You are not allowed to access this area!'); final class Guest extends Access { @@ -45,7 +44,7 @@ final class Guest extends Access { private function getAlbums() { - $album = new Album($this->database, $this->plugins, $this->settings, null); + $album = new Album(null); echo json_encode($album->getAll(true)); } @@ -53,7 +52,7 @@ final class Guest extends Access { private function getAlbum() { Module::dependencies(isset($_POST['albumID'], $_POST['password'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']); + $album = new Album($_POST['albumID']); if ($album->getPublic()) { @@ -73,7 +72,7 @@ final class Guest extends Access { private function checkAlbumAccess() { Module::dependencies(isset($_POST['albumID'], $_POST['password'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']); + $album = new Album($_POST['albumID']); if ($album->getPublic()) { @@ -95,7 +94,7 @@ final class Guest extends Access { private function getPhoto() { Module::dependencies(isset($_POST['photoID'], $_POST['albumID'], $_POST['password'])); - $photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']); + $photo = new Photo($_POST['photoID']); $pgP = $photo->getPublic($_POST['password']); @@ -111,22 +110,22 @@ final class Guest extends Access { global $dbName; - $session = new Session($this->plugins, $this->settings); - echo json_encode($session->init($this->database, $dbName, true)); + $session = new Session(); + echo json_encode($session->init(true)); } private function login() { Module::dependencies(isset($_POST['user'], $_POST['password'])); - $session = new Session($this->plugins, $this->settings); + $session = new Session(); echo $session->login($_POST['user'], $_POST['password']); } private function logout() { - $session = new Session($this->plugins, $this->settings); + $session = new Session(); echo $session->logout(); } @@ -136,7 +135,7 @@ final class Guest extends Access { private function getAlbumArchive() { Module::dependencies(isset($_GET['albumID'], $_GET['password'])); - $album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']); + $album = new Album($_GET['albumID']); if ($album->getPublic()&&$album->getDownloadable()) { @@ -156,7 +155,7 @@ final class Guest extends Access { private function getPhotoArchive() { Module::dependencies(isset($_GET['photoID'], $_GET['password'])); - $photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']); + $photo = new Photo($_GET['photoID']); $pgP = $photo->getPublic($_GET['password']); diff --git a/php/access/Installation.php b/php/access/Installation.php index 67c8811..c0c0ef7 100644 --- a/php/access/Installation.php +++ b/php/access/Installation.php @@ -6,7 +6,6 @@ ### if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to access this area!'); final class Installation extends Access { @@ -14,10 +13,10 @@ final class Installation extends Access { switch ($fn) { - case 'Database::createConfig': $this->dbCreateConfig(); break; + case 'Config::create': $this->configCreate(); break; # Error - default: $this->init(); break; + default: $this->init(); break; } @@ -25,10 +24,10 @@ final class Installation extends Access { } - private function dbCreateConfig() { + private function configCreate() { Module::dependencies(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix'])); - echo Database::createConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']); + echo Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']); } diff --git a/php/api.php b/php/api.php index d9e8381..d64e4fe 100755 --- a/php/api.php +++ b/php/api.php @@ -29,49 +29,30 @@ if (!empty($fn)) { if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); # Check if a configuration exists - if (file_exists(LYCHEE_CONFIG_FILE)) require(LYCHEE_CONFIG_FILE); - else { + if (Config::exists()===false) { ### # Installation Access # Limited access to configure Lychee. Only available when the config.php file is missing. ### - define('LYCHEE_ACCESS_INSTALLATION', true); - - $installation = new Installation(null, null, null); - $installation->check($_POST['function']); + $installation = new Installation(); + $installation->check($fn); exit(); } - # Define the table prefix - defineTablePrefix(@$dbTablePrefix); - - # Connect to database - $database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName); - - # Load settings - $settings = new Settings($database); - $settings = $settings->get(); - - # Init plugins - $plugins = explode(';', $settings['plugins']); - $plugins = new Plugins($plugins, $database, $settings); - # Check if user is logged if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& - (isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) { + (isset($_SESSION['identifier'])&&$_SESSION['identifier']===Settings::get()['identifier'])) { ### # Admin Access # Full access to Lychee. Only with correct password/session. ### - define('LYCHEE_ACCESS_ADMIN', true); - - $admin = new Admin($database, $plugins, $settings); + $admin = new Admin(); $admin->check($fn); } else { @@ -81,9 +62,7 @@ if (!empty($fn)) { # Access to view all public folders and photos in Lychee. ### - define('LYCHEE_ACCESS_GUEST', true); - - $guest = new Guest($database, $plugins, $settings); + $guest = new Guest(); $guest->check($fn); } diff --git a/php/autoload.php b/php/autoload.php index e7bede4..bd5aca4 100644 --- a/php/autoload.php +++ b/php/autoload.php @@ -23,4 +23,12 @@ spl_autoload_register(function($class) { }); +spl_autoload_register(function($class) { + + $file = LYCHEE . 'plugins/' . $class . '/' . $class . '.php'; + + if (file_exists($file)===true) require $file; + +}); + ?> \ No newline at end of file diff --git a/php/database/update_020700.php b/php/database/update_020700.php index e6e594e..c610054 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -8,12 +8,12 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Add medium to photos -$query = Database::prepare($database, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); -if (!$database->query($query)) { - $query = Database::prepare($database, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); - $result = $database->query($query); +$query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); +if (!$connection->query($query)) { + $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); + $result = $connection->query($query); if (!$result) { - Log::error($database, 'update_020700', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } @@ -22,22 +22,22 @@ if (!$database->query($query)) { if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) { # Only create the folder when it is missing if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false) - Log::error($database, 'update_020700', __LINE__, 'Could not create medium-folder'); + Log::error('update_020700', __LINE__, 'Could not create medium-folder'); } # Add medium to settings -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { - Log::error($database, 'update_020700', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } # Set version -if (Database::setVersion($database, '020700')===false) return false; +if (Database::setVersion($connection, '020700')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030000.php b/php/database/update_030000.php index 632277d..937f1d4 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -9,29 +9,29 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Remove login # Login now saved as crypt without md5. Legacy code has been removed. -$query = Database::prepare($database, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$resetUsername = $database->query($query); +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$resetUsername = $connection->query($query); if (!$resetUsername) { - Log::error($database, 'update_030000', __LINE__, 'Could not reset username (' . $database->error . ')'); + Log::error('update_030000', __LINE__, 'Could not reset username (' . $connection->error . ')'); return false; } -$query = Database::prepare($database, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$resetPassword = $database->query($query); +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$resetPassword = $connection->query($query); if (!$resetPassword) { - Log::error($database, 'update_030000', __LINE__, 'Could not reset password (' . $database->error . ')'); + Log::error('update_030000', __LINE__, 'Could not reset password (' . $connection->error . ')'); return false; } # Make public albums private and reset password # Password now saved as crypt without md5. Legacy code has been removed. -$query = Database::prepare($database, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); -$resetPublic = $database->query($query); +$query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); +$resetPublic = $connection->query($query); if (!$resetPublic) { - Log::error($database, 'update_030000', __LINE__, 'Could not reset public albums (' . $database->error . ')'); + Log::error('update_030000', __LINE__, 'Could not reset public albums (' . $connection->error . ')'); return false; } # Set version -if (Database::setVersion($database, '030000')===false) return false; +if (Database::setVersion($connection, '030000')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 3147255..c13505c 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -8,55 +8,55 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Change length of photo title -$query = Database::prepare($database, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); -$result = $database->query($query); +$query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); +$result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } # Change length of album title -$query = Database::prepare($database, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); -$result = $database->query($query); +$query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); +$result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } # Add album sorting to settings -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } # Rename sorting to sortingPhotos -$query = Database::prepare($database, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); +$query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } # Add identifier to settings -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { $identifier = md5(microtime(true)); - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); - $result = $database->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); + $result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } # Set version -if (Database::setVersion($database, '030001')===false) return false; +if (Database::setVersion($connection, '030001')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030003.php b/php/database/update_030003.php index c658bc0..dd09fe7 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -8,18 +8,18 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); # Add skipDuplicates to settings -$query = Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $database->query($query); +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); - $result = $database->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { - Log::error($database, 'update_030003', __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error('update_030003', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } # Set version -if (Database::setVersion($database, '030003')===false) return false; +if (Database::setVersion($connection, '030003')===false) return false; ?> \ No newline at end of file diff --git a/php/modules/Album.php b/php/modules/Album.php index f4ed7f7..e74997e 100644 --- a/php/modules/Album.php +++ b/php/modules/Album.php @@ -9,26 +9,18 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Album extends Module { - private $database = null; - private $settings = null; private $albumIDs = null; - public function __construct($database, $plugins, $settings, $albumIDs) { + public function __construct($albumIDs) { # Init vars - $this->database = $database; - $this->plugins = $plugins; - $this->settings = $settings; $this->albumIDs = $albumIDs; return true; } - public function add($title = 'Untitled', $public = 0, $visible = 1) { - - # Check dependencies - self::dependencies(isset($this->database)); + public function add($title = 'Untitled') { # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -36,19 +28,23 @@ final class Album extends Module { # Parse if (strlen($title)>50) $title = substr($title, 0, 50); + # Properties + $public = 0; + $visible = 1; + # Database $sysstamp = time(); - $query = Database::prepare($this->database, "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - return $this->database->insert_id; + return Database::get()->insert_id; } @@ -91,7 +87,7 @@ final class Album extends Module { public function get() { # Check dependencies - self::dependencies(isset($this->database, $this->settings, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -100,32 +96,32 @@ final class Album extends Module { switch ($this->albumIDs) { case 'f': $return['public'] = '0'; - $query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); break; case 's': $return['public'] = '0'; - $query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); break; case 'r': $return['public'] = '0'; - $query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); break; case '0': $return['public'] = '0'; - $query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); break; - default: $query = Database::prepare($this->database, "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = $this->database->query($query); + default: $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); $return = $albums->fetch_assoc(); $return = Album::prepareData($return); - $query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); break; } # Get photos - $photos = $this->database->query($query); + $photos = Database::get()->query($query); $previousPhotoID = ''; while ($photo = $photos->fetch_assoc()) { @@ -178,7 +174,7 @@ final class Album extends Module { public function getAll($public) { # Check dependencies - self::dependencies(isset($this->database, $this->settings, $public)); + self::dependencies(isset($public)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -194,14 +190,14 @@ final class Album extends Module { if ($public===false) $return['smartalbums'] = $this->getSmartInfo(); # Albums query - if ($public===false) $query = Database::prepare($this->database, 'SELECT id, title, public, sysstamp, password FROM ? ' . $this->settings['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); - else $query = Database::prepare($this->database, 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . $this->settings['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); # Execute query - $albums = $this->database->query($query); + $albums = Database::get()->query($query); if (!$albums) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not get all albums (' . $this->database->error . ')'); - exit('Error: ' . $this->database->error); + Log::error(__METHOD__, __LINE__, 'Could not get all albums (' . Database::get()->error . ')'); + exit('Error: ' . Database::get()->error); } # For each album @@ -215,8 +211,8 @@ final class Album extends Module { ($public===false)) { # Execute query - $query = Database::prepare($this->database, "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr($this->settings['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::get()->query($query); # For each thumb $k = 0; @@ -244,9 +240,6 @@ final class Album extends Module { private function getSmartInfo() { - # Check dependencies - self::dependencies(isset($this->database, $this->settings)); - # Initialize return var $return = array( 'unsorted' => null, @@ -259,8 +252,8 @@ final class Album extends Module { # Unsorted ### - $query = Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE album = 0 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $unsorted = $this->database->query($query); + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $unsorted = Database::get()->query($query); $i = 0; $return['unsorted'] = array( @@ -279,8 +272,8 @@ final class Album extends Module { # Starred ### - $query = Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE star = 1 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $starred = $this->database->query($query); + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $starred = Database::get()->query($query); $i = 0; $return['starred'] = array( @@ -299,8 +292,8 @@ final class Album extends Module { # Public ### - $query = Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE public = 1 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $public = $this->database->query($query); + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $public = Database::get()->query($query); $i = 0; $return['public'] = array( @@ -319,8 +312,8 @@ final class Album extends Module { # Recent ### - $query = Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $recent = $this->database->query($query); + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $recent = Database::get()->query($query); $i = 0; $return['recent'] = array( @@ -343,7 +336,7 @@ final class Album extends Module { public function getArchive() { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -357,31 +350,31 @@ final class Album extends Module { # Photos query switch($this->albumIDs) { case 's': - $photos = Database::prepare($this->database, 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS)); + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Public'; break; case 'f': - $photos = Database::prepare($this->database, 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS)); + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Starred'; break; case 'r': - $photos = Database::prepare($this->database, 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Recent'; break; default: - $photos = Database::prepare($this->database, "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $photos = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); $zipTitle = 'Unsorted'; } # Get title from database when album is not a SmartAlbum if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) { - $query = Database::prepare($this->database, "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $album = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $album = Database::get()->query($query); # Error in database query if (!$album) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -390,7 +383,7 @@ final class Album extends Module { # Photo not found if ($album===null) { - Log::error($this->database, __METHOD__, __LINE__, 'Album not found. Cannot start download.'); + Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); return false; } @@ -407,16 +400,16 @@ final class Album extends Module { # Create zip $zip = new ZipArchive(); if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive'); + Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive'); return false; } # Execute query - $photos = $this->database->query($photos); + $photos = Database::get()->query($photos); # Check if album empty if ($photos->num_rows==0) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive without images'); + Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive without images'); return false; } @@ -483,20 +476,20 @@ final class Album extends Module { public function setTitle($title = 'Untitled') { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Execute query - $query = Database::prepare($this->database, "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -506,20 +499,20 @@ final class Album extends Module { public function setDescription($description = '') { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Execute query - $query = Database::prepare($this->database, "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -529,7 +522,7 @@ final class Album extends Module { public function getPublic() { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -537,8 +530,8 @@ final class Album extends Module { if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f') return false; # Execute query - $query = Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); $album = $albums->fetch_object(); # Call plugins @@ -552,7 +545,7 @@ final class Album extends Module { public function getDownloadable() { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -560,8 +553,8 @@ final class Album extends Module { if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f'||$this->albumIDs==='r') return false; # Execute query - $query = Database::prepare($this->database, "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); $album = $albums->fetch_object(); # Call plugins @@ -575,7 +568,7 @@ final class Album extends Module { public function setPublic($public, $password, $visible, $downloadable) { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -586,19 +579,19 @@ final class Album extends Module { $downloadable = ($downloadable==='1' ? 1 : 0); # Set public - $query = Database::prepare($this->database, "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } # Reset permissions for photos if ($public===1) { - $query = Database::prepare($this->database, "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } } @@ -616,7 +609,7 @@ final class Album extends Module { private function setPassword($password) { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -629,23 +622,23 @@ final class Album extends Module { # Set hashed password # Do not prepare $password because it is hashed and save # Preparing (escaping) the password would destroy the hash - $query = Database::prepare($this->database, "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $query = Database::prepare(Database::get(), "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); } else { # Unset password - $query = Database::prepare($this->database, "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $query = Database::prepare(Database::get(), "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); } # Execute query - $result = $this->database->query($query); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -655,14 +648,14 @@ final class Album extends Module { public function checkPassword($password) { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Execute query - $query = Database::prepare($this->database, "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); $album = $albums->fetch_object(); # Call plugins @@ -677,7 +670,7 @@ final class Album extends Module { public function merge() { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -689,11 +682,11 @@ final class Album extends Module { $albumID = array_splice($albumIDs, 0, 1); $albumID = $albumID[0]; - $query = Database::prepare($this->database, "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -701,14 +694,14 @@ final class Album extends Module { # Convert to string $filteredIDs = implode(',', $albumIDs); - $query = Database::prepare($this->database, "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -718,7 +711,7 @@ final class Album extends Module { public function delete() { # Check dependencies - self::dependencies(isset($this->database, $this->albumIDs)); + self::dependencies(isset($this->albumIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -727,27 +720,27 @@ final class Album extends Module { $error = false; # Execute query - $query = Database::prepare($this->database, "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $photos = Database::get()->query($query); # For each album delete photo while ($row = $photos->fetch_object()) { - $photo = new Photo($this->database, $this->plugins, null, $row->id); + $photo = new Photo($row->id); if (!$photo->delete($row->id)) $error = true; } # Delete albums - $query = Database::prepare($this->database, "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if ($error) return false; if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; diff --git a/php/modules/Config.php b/php/modules/Config.php new file mode 100644 index 0000000..317571f --- /dev/null +++ b/php/modules/Config.php @@ -0,0 +1,79 @@ +"; + + # Save file + if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!'; + + return true; + + } + + public static function exists() { + + return file_exists(LYCHEE_CONFIG_FILE); + + } + + public static function get() { + + require(LYCHEE_CONFIG_FILE); + + return(array( + 'host' => $dbHost, + 'user' => $dbUser, + 'password' => $dbPassword, + 'name' => $dbName, + 'prefix' => $dbTablePrefix + )); + + } + +} + +?> diff --git a/php/modules/Database.php b/php/modules/Database.php index aa56c56..9662be2 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -9,6 +9,9 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Database extends Module { + private $connection = null; + private static $instance = null; + private static $versions = array( '020700', #2.7.0 '030000', #3.0.0 @@ -16,44 +19,230 @@ final class Database extends Module { '030003' #3.0.3 ); - public static function connect($host = 'localhost', $user, $password, $name = 'lychee') { + public static function get() { + + if (!self::$instance) { + + $credentials = Config::get(); + + self::$instance = new self( + $credentials['host'], + $credentials['user'], + $credentials['password'], + $credentials['name'], + $credentials['prefix'] + ); + + } + + return self::$instance->connection; + + } + + private function __construct($host, $user, $password, $name = 'lychee', $dbTablePrefix) { # Check dependencies Module::dependencies(isset($host, $user, $password, $name)); - $database = new mysqli($host, $user, $password); + # Define the table prefix + defineTablePrefix($dbTablePrefix); - # Check connection - if ($database->connect_errno) exit('Error: ' . $database->connect_error); + # Open a new connection to the MySQL server + $connection = self::connect($host, $user, $password); - # Avoid sql injection on older MySQL versions by using GBK - if ($database->server_version<50500) @$database->set_charset('GBK'); - else @$database->set_charset('utf8'); + # Check if the connection was successful + if ($connection===false) exit('Error: ' . $connection->connect_error); - # Set unicode - $database->query('SET NAMES utf8;'); + if (!self::setCharset($connection)) exit('Error: Could not set database charset!'); # Create database - if (!self::createDatabase($database, $name)) exit('Error: Could not create database!'); + if (!self::createDatabase($connection, $name)) exit('Error: Could not create database!'); # Create tables - if (!self::createTables($database)) exit('Error: Could not create tables!'); + if (!self::createTables($connection)) exit('Error: Could not create tables!'); # Update database - if (!self::update($database, $name)) exit('Error: Could not update database and tables!'); + if (!self::update($connection, $name)) exit('Error: Could not update database and tables!'); - return $database; + $this->connection = $connection; } - private static function update($database, $dbName) { + private function __clone() { + + # Magic method clone is empty to prevent duplication of connection + + } + + public static function connect($host = 'localhost', $user, $password) { + + # Open a new connection to the MySQL server + $connection = new mysqli($host, $user, $password); + + # Check if the connection was successful + if ($connection->connect_errno) return false; + + return $connection; + + } + + private static function setCharset($connection) { + + # Avoid sql injection on older MySQL versions by using GBK + if ($connection->server_version<50500) @$connection->set_charset('GBK'); + else @$connection->set_charset('utf8'); + + # Set unicode + $connection->query('SET NAMES utf8;'); + + return true; + + } + + public static function createDatabase($connection, $name = 'lychee') { # Check dependencies - Module::dependencies(isset($database, $dbName)); + Module::dependencies(isset($connection, $name)); + + # Check if database exists + if ($connection->select_db($name)) return true; + + # Create database + $query = self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); + $result = $connection->query($query); + + if (!$connection->select_db($name)) return false; + return true; + + } + + private static function createTables($connection) { + + # Check dependencies + Module::dependencies(isset($connection)); + + # Check if tables exist + $query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); + if ($connection->query($query)) return true; + + # Create log + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); + if (!$connection->query($exist)) { + + # Read file + $file = __DIR__ . '/../database/log_table.sql'; + $query = @file_get_contents($file); + + if (!isset($query)||$query===false) return false; + + # Create table + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG)); + if (!$connection->query($query)) return false; + + } + + # Create settings + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); + if (!$connection->query($exist)) { + + # Read file + $file = __DIR__ . '/../database/settings_table.sql'; + $query = @file_get_contents($file); + + if (!isset($query)||$query===false) { + Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_settings'); + return false; + } + + # Create table + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); + if (!$connection->query($query)) { + Log::error(__METHOD__, __LINE__, $connection->error); + return false; + } + + # Read file + $file = __DIR__ . '/../database/settings_content.sql'; + $query = @file_get_contents($file); + + if (!isset($query)||$query===false) { + Log::error(__METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); + return false; + } + + # Add content + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); + if (!$connection->query($query)) { + Log::error(__METHOD__, __LINE__, $connection->error); + return false; + } + + # Generate identifier + $identifier = md5(microtime(true)); + $query = self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); + if (!$connection->query($query)) { + Log::error(__METHOD__, __LINE__, $connection->error); + return false; + } + + } + + # Create albums + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); + if (!$connection->query($exist)) { + + # Read file + $file = __DIR__ . '/../database/albums_table.sql'; + $query = @file_get_contents($file); + + if (!isset($query)||$query===false) { + Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_albums'); + return false; + } + + # Create table + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS)); + if (!$connection->query($query)) { + Log::error(__METHOD__, __LINE__, $connection->error); + return false; + } + + } + + # Create photos + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); + if (!$connection->query($exist)) { + + # Read file + $file = __DIR__ . '/../database/photos_table.sql'; + $query = @file_get_contents($file); + + if (!isset($query)||$query===false) { + Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_photos'); + return false; + } + + # Create table + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS)); + if (!$connection->query($query)) { + Log::error(__METHOD__, __LINE__, $connection->error); + return false; + } + + } + + return true; + + } + + private static function update($connection, $dbName) { + + # Check dependencies + Module::dependencies(isset($connection)); # Get current version - $query = self::prepare($database, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); - $results = $database->query($query); + $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); + $results = $connection->query($query); $current = $results->fetch_object()->value; # For each update @@ -63,7 +252,7 @@ final class Database extends Module { if ($version<=$current) continue; # Load update - include(__DIR__ . '/../database/update_' . $update . '.php'); + include(__DIR__ . '/../database/update_' . $version . '.php'); } @@ -71,203 +260,21 @@ final class Database extends Module { } - public static function createConfig($host = 'localhost', $user, $password, $name = 'lychee', $prefix = '') { + public static function setVersion($connection, $version) { - # Check dependencies - Module::dependencies(isset($host, $user, $password, $name)); - - $database = new mysqli($host, $user, $password); - - if ($database->connect_errno) return 'Warning: Connection failed!'; - - # Check if user can create the database before saving the configuration - if (!self::createDatabase($database, $name)) return 'Warning: Creation failed!'; - - # Escape data - $host = mysqli_real_escape_string($database, $host); - $user = mysqli_real_escape_string($database, $user); - $password = mysqli_real_escape_string($database, $password); - $name = mysqli_real_escape_string($database, $name); - $prefix = mysqli_real_escape_string($database, $prefix); - - # Save config.php -$config = ""; - - # Save file - if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!'; - - return true; - - } - - private static function createDatabase($database, $name = 'lychee') { - - # Check dependencies - Module::dependencies(isset($database, $name)); - - # Check if database exists - if ($database->select_db($name)) return true; - - # Create database - $query = self::prepare($database, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); - $result = $database->query($query); - - if (!$database->select_db($name)||!$result) return false; - return true; - - } - - private static function createTables($database) { - - # Check dependencies - Module::dependencies(isset($database)); - - # Check if tables exist - $query = self::prepare($database, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); - if ($database->query($query)) return true; - - # Create log - $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); - if (!$database->query($exist)) { - - # Read file - $file = __DIR__ . '/../database/log_table.sql'; - $query = @file_get_contents($file); - - if (!isset($query)||$query===false) return false; - - # Create table - $query = self::prepare($database, $query, array(LYCHEE_TABLE_LOG)); - if (!$database->query($query)) return false; - - } - - # Create settings - $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); - if (!$database->query($exist)) { - - # Read file - $file = __DIR__ . '/../database/settings_table.sql'; - $query = @file_get_contents($file); - - if (!isset($query)||$query===false) { - Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_settings'); - return false; - } - - # Create table - $query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); - if (!$database->query($query)) { - Log::error($database, __METHOD__, __LINE__, $database->error); - return false; - } - - # Read file - $file = __DIR__ . '/../database/settings_content.sql'; - $query = @file_get_contents($file); - - if (!isset($query)||$query===false) { - Log::error($database, __METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); - return false; - } - - # Add content - $query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS)); - if (!$database->query($query)) { - Log::error($database, __METHOD__, __LINE__, $database->error); - return false; - } - - # Generate identifier - $identifier = md5(microtime(true)); - $query = self::prepare($database, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); - if (!$database->query($query)) { - Log::error($database, __METHOD__, __LINE__, $database->error); - return false; - } - - } - - # Create albums - $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); - if (!$database->query($exist)) { - - # Read file - $file = __DIR__ . '/../database/albums_table.sql'; - $query = @file_get_contents($file); - - if (!isset($query)||$query===false) { - Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_albums'); - return false; - } - - # Create table - $query = self::prepare($database, $query, array(LYCHEE_TABLE_ALBUMS)); - if (!$database->query($query)) { - Log::error($database, __METHOD__, __LINE__, $database->error); - return false; - } - - } - - # Create photos - $exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); - if (!$database->query($exist)) { - - # Read file - $file = __DIR__ . '/../database/photos_table.sql'; - $query = @file_get_contents($file); - - if (!isset($query)||$query===false) { - Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_photos'); - return false; - } - - # Create table - $query = self::prepare($database, $query, array(LYCHEE_TABLE_PHOTOS)); - if (!$database->query($query)) { - Log::error($database, __METHOD__, __LINE__, $database->error); - return false; - } - - } - - return true; - - } - - public static function setVersion($database, $version) { - - $query = self::prepare($database, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); - $result = $database->query($query); + $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); + $result = $connection->query($query); if (!$result) { - Log::error($database, __METHOD__, __LINE__, 'Could not update database (' . $database->error . ')'); + Log::error(__METHOD__, __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } - public static function prepare($database, $query, $data) { + public static function prepare($connection, $query, $data) { # Check dependencies - Module::dependencies(isset($database, $query, $data)); + Module::dependencies(isset($connection, $query, $data)); # Count the number of placeholders and compare it with the number of arguments # If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement @@ -280,12 +287,12 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); 'data' => count($data) ); - if (($num['data']-$num['placeholder'])<0) Log::notice($database, __METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); + if (($num['data']-$num['placeholder'])<0) Log::notice(__METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); foreach ($data as $value) { # Escape - $value = mysqli_real_escape_string($database, $value); + $value = mysqli_real_escape_string($connection, $value); # Recalculate number of placeholders $num['placeholder'] = substr_count($query, '?'); diff --git a/php/modules/Import.php b/php/modules/Import.php index 5c42dd1..93ceb54 100644 --- a/php/modules/Import.php +++ b/php/modules/Import.php @@ -9,31 +9,17 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Import extends Module { - private $database = null; - private $settings = null; - - public function __construct($database, $plugins, $settings) { - - # Init vars - $this->database = $database; - $this->plugins = $plugins; - $this->settings = $settings; - - return true; - - } - private function photo($path, $albumID = 0, $description = '', $tags = '') { # Check dependencies - self::dependencies(isset($this->database, $this->plugins, $this->settings, $path)); + self::dependencies(isset($path)); # No need to validate photo type and extension in this function. # $photo->add will take care of it. $info = getimagesize($path); $size = filesize($path); - $photo = new Photo($this->database, $this->plugins, $this->settings, null); + $photo = new Photo(null); $nameFile = array(array()); $nameFile[0]['name'] = $path; @@ -51,7 +37,7 @@ final class Import extends Module { public function url($urls, $albumID = 0) { # Check dependencies - self::dependencies(isset($this->database, $urls)); + self::dependencies(isset($urls)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -71,7 +57,7 @@ final class Import extends Module { $extension = getExtension($url); if (!in_array(strtolower($extension), Photo::$validExtensions, true)) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Photo format not supported (' . $url . ')'); + Log::error(__METHOD__, __LINE__, 'Photo format not supported (' . $url . ')'); continue; } @@ -79,7 +65,7 @@ final class Import extends Module { $type = @exif_imagetype($url); if (!in_array($type, Photo::$validTypes, true)) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Photo type not supported (' . $url . ')'); + Log::error(__METHOD__, __LINE__, 'Photo type not supported (' . $url . ')'); continue; } @@ -89,14 +75,14 @@ final class Import extends Module { if (@copy($url, $tmp_name)===false) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')'); + Log::error(__METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')'); continue; } # Import photo if (!$this->photo($tmp_name, $albumID)) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not import file: ' . $tmp_name); + Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $tmp_name); continue; } @@ -112,15 +98,12 @@ final class Import extends Module { public function server($path, $albumID = 0) { - # Check dependencies - self::dependencies(isset($this->database, $this->plugins, $this->settings)); - # Parse path if (!isset($path)) $path = LYCHEE_UPLOADS_IMPORT; if (substr($path, -1)==='/') $path = substr($path, 0, -1); if (is_dir($path)===false) { - Log::error($this->database, __METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); + Log::error(__METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); return 'Error: Given path is not a directory!'; } @@ -128,7 +111,7 @@ final class Import extends Module { if ($path===LYCHEE_UPLOADS_BIG||($path . '/')===LYCHEE_UPLOADS_BIG|| $path===LYCHEE_UPLOADS_MEDIUM||($path . '/')===LYCHEE_UPLOADS_MEDIUM|| $path===LYCHEE_UPLOADS_THUMB||($path . '/')===LYCHEE_UPLOADS_THUMB) { - Log::error($this->database, __METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')'); + Log::error(__METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')'); return 'Error: Given path is a reserved path of Lychee!'; } @@ -150,7 +133,7 @@ final class Import extends Module { # the file may still be unreadable by the user if (!is_readable($file)) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not read file or directory: ' . $file); + Log::error(__METHOD__, __LINE__, 'Could not read file or directory: ' . $file); continue; } @@ -162,7 +145,7 @@ final class Import extends Module { if (!$this->photo($file, $albumID)) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not import file: ' . $file); + Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $file); continue; } @@ -170,13 +153,13 @@ final class Import extends Module { # Folder - $album = new Album($this->database, $this->plugins, $this->settings, null); + $album = new Album(null); $newAlbumID = $album->add('[Import] ' . basename($file)); $contains['albums'] = true; if ($newAlbumID===false) { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')'); + Log::error(__METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')'); continue; } @@ -184,7 +167,7 @@ final class Import extends Module { if ($import!==true&&$import!=='Notice: Import only contains albums!') { $error = true; - Log::error($this->database, __METHOD__, __LINE__, 'Could not import folder. Function returned warning.'); + Log::error(__METHOD__, __LINE__, 'Could not import folder. Function returned warning.'); continue; } diff --git a/php/modules/Log.php b/php/modules/Log.php index 5befb0a..889de39 100644 --- a/php/modules/Log.php +++ b/php/modules/Log.php @@ -9,35 +9,35 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Log extends Module { - public static function notice($database, $function, $line, $text = '') { + public static function notice($function, $line, $text = '') { - return Log::text($database, 'notice', $function, $line, $text); + return Log::text('notice', $function, $line, $text); } - public static function warning($database, $function, $line, $text = '') { + public static function warning($function, $line, $text = '') { - return Log::text($database, 'warning', $function, $line, $text); + return Log::text('warning', $function, $line, $text); } - public static function error($database, $function, $line, $text = '') { + public static function error($function, $line, $text = '') { - return Log::text($database, 'error', $function, $line, $text); + return Log::text('error', $function, $line, $text); } - public static function text($database, $type, $function, $line, $text = '') { + private static function text($type, $function, $line, $text = '') { # Check dependencies - Module::dependencies(isset($database, $type, $function, $line, $text)); + Module::dependencies(isset($type, $function, $line, $text)); # Get time $sysstamp = time(); # Save in database - $query = Database::prepare($database, "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); - $result = $database->query($query); + $query = Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); + $result = Database::get()->query($query); if (!$result) return false; return true; diff --git a/php/modules/Module.php b/php/modules/Module.php index ab9fb0a..9a58de2 100644 --- a/php/modules/Module.php +++ b/php/modules/Module.php @@ -9,17 +9,15 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); abstract class Module { - protected $plugins = null; - protected function plugins($name, $location, $args) { - if (!isset($this->plugins, $name, $location, $args)) return false; + self::dependencies(isset($name, $location, $args)); # Parse $location = ($location===0 ? 'before' : 'after'); # Call plugins - $this->plugins->activate($name . ":" . $location, $args); + Plugins::get()->activate($name . ":" . $location, $args); return true; diff --git a/php/modules/Photo.php b/php/modules/Photo.php index ce99dd7..ddc14a1 100755 --- a/php/modules/Photo.php +++ b/php/modules/Photo.php @@ -9,9 +9,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Photo extends Module { - private $database = null; - private $settings = null; - private $photoIDs = null; + private $photoIDs = null; public static $validTypes = array( IMAGETYPE_JPEG, @@ -26,12 +24,9 @@ final class Photo extends Module { '.gif' ); - public function __construct($database, $plugins, $settings, $photoIDs) { + public function __construct($photoIDs) { # Init vars - $this->database = $database; - $this->plugins = $plugins; - $this->settings = $settings; $this->photoIDs = $photoIDs; return true; @@ -44,13 +39,13 @@ final class Photo extends Module { # e.g. when calling this functions inside an if-condition # Check dependencies - self::dependencies(isset($this->database, $this->settings, $files)); + self::dependencies(isset($files)); # Check permissions if (hasPermissions(LYCHEE_UPLOADS)===false|| hasPermissions(LYCHEE_UPLOADS_BIG)===false|| hasPermissions(LYCHEE_UPLOADS_THUMB)===false) { - Log::error($this->database, __METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); + Log::error(__METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); exit('Error: An upload-folder is missing or not readable and writable!'); } @@ -91,35 +86,35 @@ final class Photo extends Module { # Check if file exceeds the upload_max_filesize directive if ($file['error']===UPLOAD_ERR_INI_SIZE) { - Log::error($this->database, __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); + Log::error(__METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); if ($returnOnError===true) return false; exit('Error: The uploaded file exceeds the upload_max_filesize directive in php.ini!'); } # Check if file was only partially uploaded if ($file['error']===UPLOAD_ERR_PARTIAL) { - Log::error($this->database, __METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); + Log::error(__METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); if ($returnOnError===true) return false; exit('Error: The uploaded file was only partially uploaded!'); } # Check if writing file to disk failed if ($file['error']===UPLOAD_ERR_CANT_WRITE) { - Log::error($this->database, __METHOD__, __LINE__, 'Failed to write photo to disk'); + Log::error(__METHOD__, __LINE__, 'Failed to write photo to disk'); if ($returnOnError===true) return false; exit('Error: Failed to write photo to disk!'); } # Check if a extension stopped the file upload if ($file['error']===UPLOAD_ERR_EXTENSION) { - Log::error($this->database, __METHOD__, __LINE__, 'A PHP extension stopped the file upload'); + Log::error(__METHOD__, __LINE__, 'A PHP extension stopped the file upload'); if ($returnOnError===true) return false; exit('Error: A PHP extension stopped the file upload!'); } # Check if the upload was successful if ($file['error']!==UPLOAD_ERR_OK) { - Log::error($this->database, __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); + Log::error(__METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); if ($returnOnError===true) return false; exit('Error: Upload failed!'); } @@ -127,7 +122,7 @@ final class Photo extends Module { # Verify extension $extension = getExtension($file['name']); if (!in_array(strtolower($extension), self::$validExtensions, true)) { - Log::error($this->database, __METHOD__, __LINE__, 'Photo format not supported'); + Log::error(__METHOD__, __LINE__, 'Photo format not supported'); if ($returnOnError===true) return false; exit('Error: Photo format not supported!'); } @@ -135,7 +130,7 @@ final class Photo extends Module { # Verify image $type = @exif_imagetype($file['tmp_name']); if (!in_array($type, self::$validTypes, true)) { - Log::error($this->database, __METHOD__, __LINE__, 'Photo type not supported'); + Log::error(__METHOD__, __LINE__, 'Photo type not supported'); if ($returnOnError===true) return false; exit('Error: Photo type not supported!'); } @@ -152,7 +147,7 @@ final class Photo extends Module { # Calculate checksum $checksum = sha1_file($tmp_name); if ($checksum===false) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not calculate checksum for photo'); + Log::error(__METHOD__, __LINE__, 'Could not calculate checksum for photo'); if ($returnOnError===true) return false; exit('Error: Could not calculate checksum for photo!'); } @@ -182,13 +177,13 @@ final class Photo extends Module { # Import if not uploaded via web if (!is_uploaded_file($tmp_name)) { if (!@copy($tmp_name, $path)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not copy photo to uploads'); + Log::error(__METHOD__, __LINE__, 'Could not copy photo to uploads'); if ($returnOnError===true) return false; exit('Error: Could not copy photo to uploads!'); } else @unlink($tmp_name); } else { if (!@move_uploaded_file($tmp_name, $path)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not move photo to uploads'); + Log::error(__METHOD__, __LINE__, 'Could not move photo to uploads'); if ($returnOnError===true) return false; exit('Error: Could not move photo to uploads!'); } @@ -198,8 +193,8 @@ final class Photo extends Module { # Photo already exists # Check if the user wants to skip duplicates - if ($this->settings['skipDuplicates']==='1') { - Log::notice($this->database, __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); + if (Settings::get()['skipDuplicates']==='1') { + Log::notice(__METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); if ($returnOnError===true) return false; exit('Warning: This photo has been skipped because it\'s already in your library.'); } @@ -221,7 +216,7 @@ final class Photo extends Module { if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') { $adjustFile = $this->adjustFile($path, $info); if ($adjustFile!==false) $info = $adjustFile; - else Log::notice($this->database, __METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); + else Log::notice(__METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); } # Set original date @@ -229,7 +224,7 @@ final class Photo extends Module { # Create Thumb if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not create thumbnail for photo'); + Log::error(__METHOD__, __LINE__, 'Could not create thumbnail for photo'); if ($returnOnError===true) return false; exit('Error: Could not create thumbnail for photo!'); } @@ -245,11 +240,11 @@ final class Photo extends Module { # Save to DB $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); - $query = Database::prepare($this->database, "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); if ($returnOnError===true) return false; exit('Error: Could not save photo in database!'); } @@ -266,16 +261,16 @@ final class Photo extends Module { private function exists($checksum, $photoID = null) { # Check dependencies - self::dependencies(isset($this->database, $checksum)); + self::dependencies(isset($checksum)); # Exclude $photoID from select when $photoID is set - if (isset($photoID)) $query = Database::prepare($this->database, "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); - else $query = Database::prepare($this->database, "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); + if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); + else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); - $result = $this->database->query($query); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not check for existing photos with the same checksum'); + Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum'); return false; } @@ -301,7 +296,7 @@ final class Photo extends Module { private function createThumb($url, $filename, $type, $width, $height) { # Check dependencies - self::dependencies(isset($this->database, $this->settings, $url, $filename, $type, $width, $height)); + self::dependencies(isset($url, $filename, $type, $width, $height)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -315,12 +310,12 @@ final class Photo extends Module { $newUrl2x = LYCHEE_UPLOADS_THUMB . $photoName[0] . '@2x.jpeg'; # Create thumbnails with Imagick - if(extension_loaded('imagick')&&$this->settings['imagick']==='1') { + if(extension_loaded('imagick')&&Settings::get()['imagick']==='1') { # Read image $thumb = new Imagick(); $thumb->readImage($url); - $thumb->setImageCompressionQuality($this->settings['thumbQuality']); + $thumb->setImageCompressionQuality(Settings::get()['thumbQuality']); $thumb->setImageFormat('jpeg'); # Copy image for 2nd thumb version @@ -360,19 +355,19 @@ final class Photo extends Module { case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; case 'image/png': $sourceImg = imagecreatefrompng($url); break; case 'image/gif': $sourceImg = imagecreatefromgif($url); break; - default: Log::error($this->database, __METHOD__, __LINE__, 'Type of photo is not supported'); + default: Log::error(__METHOD__, __LINE__, 'Type of photo is not supported'); return false; break; } # Create thumb fastimagecopyresampled($thumb, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth, $newHeight, $newSize, $newSize); - imagejpeg($thumb, $newUrl, $this->settings['thumbQuality']); + imagejpeg($thumb, $newUrl, Settings::get()['thumbQuality']); imagedestroy($thumb); # Create retina thumb fastimagecopyresampled($thumb2x, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth*2, $newHeight*2, $newSize, $newSize); - imagejpeg($thumb2x, $newUrl2x, $this->settings['thumbQuality']); + imagejpeg($thumb2x, $newUrl2x, Settings::get()['thumbQuality']); imagedestroy($thumb2x); # Free memory @@ -400,7 +395,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->settings, $url, $filename, $width, $height)); + self::dependencies(isset($url, $filename, $width, $height)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -418,7 +413,7 @@ final class Photo extends Module { if (hasPermissions(LYCHEE_UPLOADS_MEDIUM)===false) { # Permissions are missing - Log::notice($this->database, __METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.'); + Log::notice(__METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.'); $error = true; } @@ -428,8 +423,8 @@ final class Photo extends Module { # Is Imagick installed and activated? if (($error===false)&& ($width>$newWidth||$height>$newHeight)&& - ($this->settings['medium']==='1')&& - (extension_loaded('imagick')&&$this->settings['imagick']==='1')) { + (Settings::get()['medium']==='1')&& + (extension_loaded('imagick')&&Settings::get()['imagick']==='1')) { $newUrl = LYCHEE_UPLOADS_MEDIUM . $filename; @@ -443,7 +438,7 @@ final class Photo extends Module { # Save image try { $medium->writeImage($newUrl); } catch (ImagickException $err) { - Log::notice($this->database, __METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); + Log::notice(__METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); $error = true; } @@ -485,7 +480,7 @@ final class Photo extends Module { $swapSize = false; - if (extension_loaded('imagick')&&$this->settings['imagick']==='1') { + if (extension_loaded('imagick')&&Settings::get()['imagick']==='1') { switch ($info['orientation']) { @@ -655,14 +650,14 @@ final class Photo extends Module { # (array) $photo # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get photo - $query = Database::prepare($this->database, "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); $photo = $photos->fetch_assoc(); # Parse photo @@ -684,8 +679,8 @@ final class Photo extends Module { if ($photo['album']!=='0') { # Get album - $query = Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); - $albums = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); + $albums = Database::get()->query($query); $album = $albums->fetch_assoc(); # Parse album @@ -714,7 +709,7 @@ final class Photo extends Module { # (array) $return # Check dependencies - self::dependencies(isset($this->database, $url)); + self::dependencies(isset($url)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -821,32 +816,32 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get photo - $query = Database::prepare($this->database, "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); $photo = $photos->fetch_object(); # Error in database query if (!$photos) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } # Photo not found if ($photo===null) { - Log::error($this->database, __METHOD__, __LINE__, 'Album not found. Cannot start download.'); + Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); return false; } # Get extension $extension = getExtension($photo->url); if ($extension===false) { - Log::error($this->database, __METHOD__, __LINE__, 'Invalid photo extension'); + Log::error(__METHOD__, __LINE__, 'Invalid photo extension'); return false; } @@ -887,20 +882,20 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Set title - $query = Database::prepare($this->database, "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -917,20 +912,20 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Set description - $query = Database::prepare($this->database, "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -945,7 +940,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -954,8 +949,8 @@ final class Photo extends Module { $error = false; # Get photos - $query = Database::prepare($this->database, "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); # For each photo while ($photo = $photos->fetch_object()) { @@ -964,8 +959,8 @@ final class Photo extends Module { $star = ($photo->star==0 ? 1 : 0); # Set star - $query = Database::prepare($this->database, "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); - $star = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); + $star = Database::get()->query($query); if (!$star) $error = true; } @@ -974,7 +969,7 @@ final class Photo extends Module { $this->plugins(__METHOD__, 1, func_get_args()); if ($error===true) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -990,14 +985,14 @@ final class Photo extends Module { # (int) 2 = Photo public or album public and password correct # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get photo - $query = Database::prepare($this->database, "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); $photo = $photos->fetch_object(); # Check if public @@ -1009,7 +1004,7 @@ final class Photo extends Module { } else { # Check if album public - $album = new Album($this->database, null, null, $photo->album); + $album = new Album($photo->album); $agP = $album->getPublic(); $acP = $album->checkPassword($password); @@ -1037,28 +1032,28 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get public - $query = Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); $photo = $photos->fetch_object(); # Invert public $public = ($photo->public==0 ? 1 : 0); # Set public - $query = Database::prepare($this->database, "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -1073,20 +1068,20 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Set album - $query = Database::prepare($this->database, "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -1103,7 +1098,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); @@ -1113,14 +1108,14 @@ final class Photo extends Module { $tags = preg_replace('/,$|^,|(\ ){0,}$/', '', $tags); # Set tags - $query = Database::prepare($this->database, "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs)); + $result = Database::get()->query($query); # Call plugins $this->plugins(__METHOD__, 1, func_get_args()); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; @@ -1135,16 +1130,16 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get photos - $query = Database::prepare($this->database, "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); if (!$photos) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1157,10 +1152,10 @@ final class Photo extends Module { # Duplicate entry $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); - $query = Database::prepare($this->database, "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); - $duplicate = $this->database->query($query); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); + $duplicate = Database::get()->query($query); if (!$duplicate) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1178,16 +1173,16 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->database, $this->photoIDs)); + self::dependencies(isset($this->photoIDs)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Get photos - $query = Database::prepare($this->database, "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); if (!$photos) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1204,35 +1199,35 @@ final class Photo extends Module { # Delete big if (file_exists(LYCHEE_UPLOADS_BIG . $photo->url)&&!unlink(LYCHEE_UPLOADS_BIG . $photo->url)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/big/'); + Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/big/'); return false; } # Delete medium if (file_exists(LYCHEE_UPLOADS_MEDIUM . $photo->url)&&!unlink(LYCHEE_UPLOADS_MEDIUM . $photo->url)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/medium/'); + Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/medium/'); return false; } # Delete thumb if (file_exists(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)&&!unlink(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/'); + Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/'); return false; } # Delete thumb@2x if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)) { - Log::error($this->database, __METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/'); + Log::error(__METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/'); return false; } } # Delete db entry - $query = Database::prepare($this->database, "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); - $delete = $this->database->query($query); + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); + $delete = Database::get()->query($query); if (!$delete) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } diff --git a/php/modules/Plugins.php b/php/modules/Plugins.php index 94aa1bd..6b83180 100644 --- a/php/modules/Plugins.php +++ b/php/modules/Plugins.php @@ -9,32 +9,35 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Plugins implements \SplSubject { - private $files = array(); - private $observers = array(); + private static $instance = null; - public $action = null; - public $args = null; + private $observers = array(); - public function __construct(array $files, $database, array $settings) { + public $action = null; + public $args = null; - if (!isset($files)) return false; + public static function get() { - # Init vars - $this->files = $files; + if (!self::$instance) { + + $files = Settings::get()['plugins']; + + self::$instance = new self($files); + + } + + return self::$instance; + + } + + private function __construct(array $plugins) { # Load plugins - foreach ($this->files as $file) { + foreach ($plugins as $plugin) { - if ($file==='') continue; + if ($plugin==='') continue; - $file = LYCHEE_PLUGINS . $file; - - if (file_exists($file)===false) { - Log::warning($database, __METHOD__, __LINE__, 'Could not include plugin. File does not exist (' . $file . ').'); - continue; - } - - include($file); + $this->attach(new $plugin); } @@ -42,6 +45,12 @@ final class Plugins implements \SplSubject { } + private function __clone() { + + # Magic method clone is empty to prevent duplication of plugins + + } + public function attach(\SplObserver $observer) { if (!isset($observer)) return false; @@ -91,4 +100,4 @@ final class Plugins implements \SplSubject { } -?> +?> \ No newline at end of file diff --git a/php/modules/Session.php b/php/modules/Session.php index 3e27d98..bd823ca 100755 --- a/php/modules/Session.php +++ b/php/modules/Session.php @@ -9,28 +9,16 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Session extends Module { - private $settings = null; - - public function __construct($plugins, $settings) { - - # Init vars - $this->plugins = $plugins; - $this->settings = $settings; - - return true; - - } - - public function init($database, $dbName, $public) { + public function init($public) { # Check dependencies - self::dependencies(isset($this->settings, $public)); + self::dependencies(isset($public)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); # Return settings - $return['config'] = $this->settings; + $return['config'] = Settings::get(); # Path to Lychee for the server-import dialog $return['config']['location'] = LYCHEE; @@ -83,19 +71,19 @@ final class Session extends Module { public function login($username, $password) { # Check dependencies - self::dependencies(isset($this->settings, $username, $password)); + self::dependencies(isset($username, $password)); # Call plugins $this->plugins(__METHOD__, 0, func_get_args()); - $username = crypt($username, $this->settings['username']); - $password = crypt($password, $this->settings['password']); + $username = crypt($username, Settings::get()['username']); + $password = crypt($password, Settings::get()['password']); # Check login with crypted hash - if ($this->settings['username']===$username&& - $this->settings['password']===$password) { + if (Settings::get()['username']===$username&& + Settings::get()['password']===$password) { $_SESSION['login'] = true; - $_SESSION['identifier'] = $this->settings['identifier']; + $_SESSION['identifier'] = Settings::get()['identifier']; return true; } @@ -111,14 +99,11 @@ final class Session extends Module { private function noLogin() { - # Check dependencies - self::dependencies(isset($this->settings)); - # Check if login credentials exist and login if they don't - if ($this->settings['username']===''&& - $this->settings['password']==='') { + if (Settings::get()['username']===''&& + Settings::get()['password']==='') { $_SESSION['login'] = true; - $_SESSION['identifier'] = $this->settings['identifier']; + $_SESSION['identifier'] = Settings::get()['identifier']; return true; } diff --git a/php/modules/Settings.php b/php/modules/Settings.php index 689fd1c..6c68373 100755 --- a/php/modules/Settings.php +++ b/php/modules/Settings.php @@ -9,51 +9,40 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); final class Settings extends Module { - private $database = null; + private static $cache = null; - public function __construct($database) { + public static function get() { - # Init vars - $this->database = $database; - - return true; - - } - - public function get() { - - # Check dependencies - self::dependencies(isset($this->database)); + if (self::$cache) return self::$cache; # Execute query - $query = Database::prepare($this->database, "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS)); - $settings = $this->database->query($query); + $query = Database::prepare(Database::get(), "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS)); + $settings = Database::get()->query($query); # Add each to return while ($setting = $settings->fetch_object()) $return[$setting->key] = $setting->value; - # Fallback for versions below v2.5 - if (!isset($return['plugins'])) $return['plugins'] = ''; + # Convert plugins to array + $return['plugins'] = explode(';', $return['plugins']); + + self::$cache = $return; return $return; } - public function setLogin($oldPassword = '', $username, $password) { + public static function setLogin($oldPassword = '', $username, $password) { # Check dependencies - self::dependencies(isset($this->database)); + self::dependencies(isset($oldPassword, $username, $password)); - # Load settings - $settings = $this->get(); - - if ($oldPassword===$settings['password']||$settings['password']===crypt($oldPassword, $settings['password'])) { + if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) { # Save username - if ($this->setUsername($username)!==true) exit('Error: Updating username failed!'); + if (self::setUsername($username)!==true) exit('Error: Updating username failed!'); # Save password - if ($this->setPassword($password)!==true) exit('Error: Updating password failed!'); + if (self::setPassword($password)!==true) exit('Error: Updating password failed!'); return true; @@ -63,10 +52,10 @@ final class Settings extends Module { } - private function setUsername($username) { + private static function setUsername($username) { # Check dependencies - self::dependencies(isset($this->database)); + self::dependencies(isset($username)); # Hash username $username = getHashedString($username); @@ -74,21 +63,21 @@ final class Settings extends Module { # Execute query # Do not prepare $username because it is hashed and save # Preparing (escaping) the username would destroy the hash - $query = Database::prepare($this->database, "UPDATE ? SET value = '$username' WHERE `key` = 'username'", array(LYCHEE_TABLE_SETTINGS)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$username' WHERE `key` = 'username'", array(LYCHEE_TABLE_SETTINGS)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; } - private function setPassword($password) { + private static function setPassword($password) { # Check dependencies - self::dependencies(isset($this->database)); + self::dependencies(isset($password)); # Hash password $password = getHashedString($password); @@ -96,43 +85,43 @@ final class Settings extends Module { # Execute query # Do not prepare $password because it is hashed and save # Preparing (escaping) the password would destroy the hash - $query = Database::prepare($this->database, "UPDATE ? SET value = '$password' WHERE `key` = 'password'", array(LYCHEE_TABLE_SETTINGS)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$password' WHERE `key` = 'password'", array(LYCHEE_TABLE_SETTINGS)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; } - public function setDropboxKey($key) { + public static function setDropboxKey($key) { # Check dependencies - self::dependencies(isset($this->database, $key)); + self::dependencies(isset($key)); if (strlen($key)<1||strlen($key)>50) { - Log::notice($this->database, __METHOD__, __LINE__, 'Dropbox key is either too short or too long'); + Log::notice(__METHOD__, __LINE__, 'Dropbox key is either too short or too long'); return false; } # Execute query - $query = Database::prepare($this->database, "UPDATE ? SET value = '?' WHERE `key` = 'dropboxKey'", array(LYCHEE_TABLE_SETTINGS, $key)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '?' WHERE `key` = 'dropboxKey'", array(LYCHEE_TABLE_SETTINGS, $key)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; } - public function setSortingPhotos($type, $order) { + public static function setSortingPhotos($type, $order) { # Check dependencies - self::dependencies(isset($this->database, $type, $order)); + self::dependencies(isset($type, $order)); $sorting = 'ORDER BY '; @@ -183,21 +172,21 @@ final class Settings extends Module { # Do not prepare $sorting because it is a true statement # Preparing (escaping) the sorting would destroy it # $sorting is save and can't contain user-input - $query = Database::prepare($this->database, "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingPhotos'", array(LYCHEE_TABLE_SETTINGS)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingPhotos'", array(LYCHEE_TABLE_SETTINGS)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; } - public function setSortingAlbums($type, $order) { + public static function setSortingAlbums($type, $order) { # Check dependencies - self::dependencies(isset($this->database, $type, $order)); + self::dependencies(isset($type, $order)); $sorting = 'ORDER BY '; @@ -239,11 +228,11 @@ final class Settings extends Module { # Do not prepare $sorting because it is a true statement # Preparing (escaping) the sorting would destroy it # $sorting is save and can't contain user-input - $query = Database::prepare($this->database, "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingAlbums'", array(LYCHEE_TABLE_SETTINGS)); - $result = $this->database->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingAlbums'", array(LYCHEE_TABLE_SETTINGS)); + $result = Database::get()->query($query); if (!$result) { - Log::error($this->database, __METHOD__, __LINE__, $this->database->error); + Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } return true; diff --git a/php/modules/misc.php b/php/modules/misc.php index 865d812..07dde6b 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -7,9 +7,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -function search($database, $settings, $term) { - - if (!isset($database, $settings, $term)) return false; +function search($term) { $return['albums'] = ''; @@ -24,8 +22,8 @@ function search($database, $settings, $term) { # Photos ### - $query = Database::prepare($database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); - $result = $database->query($query); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); + $result = Database::get()->query($query); while($photo = $result->fetch_assoc()) { @@ -38,8 +36,8 @@ function search($database, $settings, $term) { # Albums ### - $query = Database::prepare($database, "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); - $result = $database->query($query); + $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); + $result = Database::get()->query($query); while($album = $result->fetch_assoc()) { @@ -47,8 +45,8 @@ function search($database, $settings, $term) { $album = Album::prepareData($album); # Thumbs - $query = Database::prepare($database, "SELECT thumbUrl FROM ? WHERE album = '?' " . $settings['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = $database->query($query); + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::get()->query($query); # For each thumb $k = 0; @@ -69,15 +67,13 @@ function search($database, $settings, $term) { } -function getGraphHeader($database, $photoID) { +function getGraphHeader($photoID) { - if (!isset($database, $photoID)) return false; - - $photo = new Photo($database, null, null, $photoID); + $photo = new Photo($photoID); if ($photo->getPublic('')===false) return false; - $query = Database::prepare($database, "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); - $result = $database->query($query); + $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); + $result = Database::get()->query($query); $row = $result->fetch_object(); if (!$result||!$row) return false; diff --git a/plugins/check/index.php b/plugins/check/index.php index 7340573..d14dc0f 100644 --- a/plugins/check/index.php +++ b/plugins/check/index.php @@ -58,16 +58,12 @@ if (!$gdVersion['GIF Read Support'] || !$gdVersion['GIF Create Support']) $error if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error: Configuration not found. Please install Lychee for additional tests'); else require(LYCHEE_CONFIG_FILE); -# Define the table prefix -defineTablePrefix(@$dbTablePrefix); - # Database $database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName); if (mysqli_connect_errno()!=0) $error .= ('Error: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL); # Load settings -$settings = new Settings($database); -$settings = $settings->get(); +$settings = Settings::get(); # Config if (!isset($dbName)||$dbName==='') $error .= ('Error: No property for $dbName in config.php' . PHP_EOL); @@ -130,7 +126,7 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& echo('Imagick Active: ' . $settings['imagick'] . PHP_EOL); echo('Imagick Version: ' . $imagickVersion . PHP_EOL); echo('GD Version: ' . $gdVersion['GD Version'] . PHP_EOL); - echo('Plugins: ' . $settings['plugins'] . PHP_EOL); + echo('Plugins: ' . implode($settings['plugins'], ', ') . PHP_EOL); } else { diff --git a/plugins/displaylog/index.php b/plugins/displaylog/index.php index 52aa698..dda47a2 100644 --- a/plugins/displaylog/index.php +++ b/plugins/displaylog/index.php @@ -25,12 +25,6 @@ header('content-type: text/plain'); if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error 001: Configuration not found. Please install Lychee first.'); require(LYCHEE_CONFIG_FILE); -# Define the table prefix -defineTablePrefix(@$dbTablePrefix); - -# Declare -$result = ''; - # Database $database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName); @@ -40,8 +34,7 @@ if (mysqli_connect_errno()!=0) { } # Load settings -$settings = new Settings($database); -$settings = $settings->get(); +$settings = Settings::get(); # Ensure that user is logged in if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& diff --git a/src/scripts/settings.js b/src/scripts/settings.js index db5810f..8fd92d6 100644 --- a/src/scripts/settings.js +++ b/src/scripts/settings.js @@ -31,7 +31,7 @@ settings.createConfig = function() { dbTablePrefix } - api.post('Database::createConfig', params, function(data) { + api.post('Config::create', params, function(data) { if (data!==true) { diff --git a/view.php b/view.php index c1b1160..821b1f5 100644 --- a/view.php +++ b/view.php @@ -26,14 +26,8 @@ require(__DIR__ . '/php/define.php'); require(__DIR__ . '/php/autoload.php'); require(__DIR__ . '/php/modules/misc.php'); - require(LYCHEE_CONFIG_FILE); - # Define the table prefix - defineTablePrefix(@$dbTablePrefix); - - $database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName); - - echo getGraphHeader($database, $_GET['p']); + echo getGraphHeader($_GET['p']); } From 84c4a5b267b88d223d2090695aeaf4cdabd5893c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:15:04 +0100 Subject: [PATCH 027/183] Removed version from sql files --- php/database/albums_table.sql | 1 - php/database/log_table.sql | 1 - php/database/photos_table.sql | 1 - php/database/settings_content.sql | 1 - php/database/settings_table.sql | 1 - 5 files changed, 5 deletions(-) diff --git a/php/database/albums_table.sql b/php/database/albums_table.sql index b949e2e..8303b88 100644 --- a/php/database/albums_table.sql +++ b/php/database/albums_table.sql @@ -1,5 +1,4 @@ # Dump of table lychee_albums -# Version 2.5 # ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS `?` ( diff --git a/php/database/log_table.sql b/php/database/log_table.sql index 800b00c..c5869bf 100644 --- a/php/database/log_table.sql +++ b/php/database/log_table.sql @@ -1,5 +1,4 @@ # Dump of table lychee_log -# Version 2.5 # ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS `?` ( diff --git a/php/database/photos_table.sql b/php/database/photos_table.sql index b8d5ef9..bd265e8 100644 --- a/php/database/photos_table.sql +++ b/php/database/photos_table.sql @@ -1,5 +1,4 @@ # Dump of table lychee_photos -# Version 2.5 # ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS `?` ( diff --git a/php/database/settings_content.sql b/php/database/settings_content.sql index cbcc9d6..907e6c4 100644 --- a/php/database/settings_content.sql +++ b/php/database/settings_content.sql @@ -1,5 +1,4 @@ # Content of table lychee_settings -# Version 2.5 # ------------------------------------------------------------ INSERT INTO `?` (`key`, `value`) diff --git a/php/database/settings_table.sql b/php/database/settings_table.sql index 80eccce..bdc1cf2 100644 --- a/php/database/settings_table.sql +++ b/php/database/settings_table.sql @@ -1,5 +1,4 @@ # Dump of table lychee_settings -# Version 2.5 # ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS `?` ( From 2f70bfac41e0130cfa57ffdaf6aca47f580d388a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:17:47 +0100 Subject: [PATCH 028/183] Removed __clone --- php/modules/Database.php | 6 ------ php/modules/Plugins.php | 6 ------ 2 files changed, 12 deletions(-) diff --git a/php/modules/Database.php b/php/modules/Database.php index 9662be2..6ef3327 100755 --- a/php/modules/Database.php +++ b/php/modules/Database.php @@ -68,12 +68,6 @@ final class Database extends Module { } - private function __clone() { - - # Magic method clone is empty to prevent duplication of connection - - } - public static function connect($host = 'localhost', $user, $password) { # Open a new connection to the MySQL server diff --git a/php/modules/Plugins.php b/php/modules/Plugins.php index 6b83180..c1fd4db 100644 --- a/php/modules/Plugins.php +++ b/php/modules/Plugins.php @@ -45,12 +45,6 @@ final class Plugins implements \SplSubject { } - private function __clone() { - - # Magic method clone is empty to prevent duplication of plugins - - } - public function attach(\SplObserver $observer) { if (!isset($observer)) return false; From aeb62bba48e7db3907895b7452e19c05239d5255 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:30:37 +0100 Subject: [PATCH 029/183] Moved misc file --- php/api.php | 2 +- php/{modules => }/misc.php | 0 plugins/check/index.php | 2 +- plugins/displaylog/index.php | 2 +- view.php | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename php/{modules => }/misc.php (100%) diff --git a/php/api.php b/php/api.php index d64e4fe..76e4ee1 100755 --- a/php/api.php +++ b/php/api.php @@ -20,7 +20,7 @@ if (!empty($fn)) { # Load required files require(__DIR__ . '/define.php'); require(__DIR__ . '/autoload.php'); - require(__DIR__ . '/modules/misc.php'); + require(__DIR__ . '/misc.php'); # Validate parameters if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); diff --git a/php/modules/misc.php b/php/misc.php similarity index 100% rename from php/modules/misc.php rename to php/misc.php diff --git a/plugins/check/index.php b/plugins/check/index.php index d14dc0f..1a56c35 100644 --- a/plugins/check/index.php +++ b/plugins/check/index.php @@ -13,7 +13,7 @@ $lychee = __DIR__ . '/../../'; # Load requirements require($lychee . 'php/define.php'); require($lychee . 'php/autoload.php'); -require($lychee . 'php/modules/misc.php'); +require($lychee . 'php/misc.php'); # Start the session session_start(); diff --git a/plugins/displaylog/index.php b/plugins/displaylog/index.php index dda47a2..0e36c5a 100644 --- a/plugins/displaylog/index.php +++ b/plugins/displaylog/index.php @@ -16,7 +16,7 @@ session_start(); # Load requirements require($lychee . 'php/define.php'); require($lychee . 'php/autoload.php'); -require($lychee . 'php/modules/misc.php'); +require($lychee . 'php/misc.php'); # Set content header('content-type: text/plain'); diff --git a/view.php b/view.php index 821b1f5..0b0e001 100644 --- a/view.php +++ b/view.php @@ -25,7 +25,7 @@ # Load required files require(__DIR__ . '/php/define.php'); require(__DIR__ . '/php/autoload.php'); - require(__DIR__ . '/php/modules/misc.php'); + require(__DIR__ . '/php/misc.php'); echo getGraphHeader($_GET['p']); From 412fbf47eeed2a6ad66ad0a79298d9913a9c5995 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:30:57 +0100 Subject: [PATCH 030/183] exit() after using access-file --- php/api.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/php/api.php b/php/api.php index 76e4ee1..5f50dd9 100755 --- a/php/api.php +++ b/php/api.php @@ -55,18 +55,18 @@ if (!empty($fn)) { $admin = new Admin(); $admin->check($fn); - } else { - - ### - # Guest Access - # Access to view all public folders and photos in Lychee. - ### - - $guest = new Guest(); - $guest->check($fn); + exit(); } + ### + # Guest Access + # Access to view all public folders and photos in Lychee. + ### + + $guest = new Guest(); + $guest->check($fn); + } else { exit('Error: No API function specified!'); From dc35658ddc6c64c07bb9f2ebd202ba9fabc0a376 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 24 Jan 2016 22:31:03 +0100 Subject: [PATCH 031/183] Fixed name --- php/modules/Import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/modules/Import.php b/php/modules/Import.php index 93ceb54..ac1cc98 100644 --- a/php/modules/Import.php +++ b/php/modules/Import.php @@ -1,7 +1,7 @@ Date: Tue, 26 Jan 2016 15:31:53 +0100 Subject: [PATCH 032/183] Namespaces, Plugins via Namespaces, API entry file renamned, Settings::set() --- .gitignore | 7 +- dist/main.js | Bin 192541 -> 192542 bytes dist/view.js | Bin 107009 -> 107011 bytes php/access/Access.php | 11 +- php/access/Admin.php | 14 +- php/access/Guest.php | 12 +- php/access/Installation.php | 10 +- php/autoload.php | 22 +-- php/define.php | 5 - php/helpers/fastImageCopyResampled.php | 35 ++++ php/helpers/getExtension.php | 13 ++ php/helpers/getGraphHeader.php | 47 ++++++ php/helpers/getHashedString.php | 31 ++++ php/helpers/hasPermissions.php | 14 ++ php/helpers/search.php | 63 ++++++++ php/{api.php => index.php} | 25 ++- php/misc.php | 195 ----------------------- php/modules/Album.php | 7 +- php/modules/Config.php | 7 +- php/modules/Database.php | 9 +- php/modules/Import.php | 7 +- php/modules/Log.php | 7 +- php/modules/Module.php | 7 +- php/modules/Photo.php | 11 +- php/modules/Plugins.php | 9 +- php/modules/Session.php | 7 +- php/modules/Settings.php | 66 ++++---- plugins/{check => Diagnostics}/index.php | 18 ++- plugins/{displaylog => Log}/index.php | 34 ++-- src/scripts/api.js | 2 +- src/scripts/contextMenu.js | 4 +- 31 files changed, 329 insertions(+), 370 deletions(-) create mode 100644 php/helpers/fastImageCopyResampled.php create mode 100644 php/helpers/getExtension.php create mode 100644 php/helpers/getGraphHeader.php create mode 100644 php/helpers/getHashedString.php create mode 100644 php/helpers/hasPermissions.php create mode 100755 php/helpers/search.php rename php/{api.php => index.php} (76%) delete mode 100755 php/misc.php rename plugins/{check => Diagnostics}/index.php (97%) rename plugins/{displaylog => Log}/index.php (65%) diff --git a/.gitignore b/.gitignore index 254c796..7763479 100644 --- a/.gitignore +++ b/.gitignore @@ -7,12 +7,13 @@ uploads/big/* uploads/import/* uploads/medium/* uploads/thumb/* -plugins/* !uploads/big/index.html !uploads/import/index.html !uploads/medium/index.html !uploads/thumb/index.html -!plugins/check/ -!plugins/displaylog/ \ No newline at end of file +plugins/* + +!plugins/Diagnostics/ +!plugins/Log/ \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index 7fc8c459c694ab4108d722023329b69ec9d13a2e..56ab19262be169576c9846f89d20c48a12d4af93 100644 GIT binary patch delta 64 zcmbRHfP3Bp?uIRl#jjX1^HNePwwJwPj1c5?$xKYo%P%g;OfJ?}n$F0{Bsu-vZ$>9p UpZs(nf58t%ne7pO7>|Ai08?Tb9{>OV delta 62 zcmV-E0KxyB;0vAL3xKo%bLsH%002V-buV{0!Wm!S*-8JG6^0YVF8X>)LF UVR>wCXD^pf6apQ$S^NRT^COcPH2?qr diff --git a/dist/view.js b/dist/view.js index 084bab82048e3368096d073e4663f0a2df545500..75fb8cf31bb8e951224353713b1ec8288fb26b5c 100644 GIT binary patch delta 23 ecmZoX!q$9*tziq} \ No newline at end of file diff --git a/php/helpers/getExtension.php b/php/helpers/getExtension.php new file mode 100644 index 0000000..21089c0 --- /dev/null +++ b/php/helpers/getExtension.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/php/helpers/getGraphHeader.php b/php/helpers/getGraphHeader.php new file mode 100644 index 0000000..aec92aa --- /dev/null +++ b/php/helpers/getGraphHeader.php @@ -0,0 +1,47 @@ +getPublic('')===false) return false; + + $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); + $result = Database::get()->query($query); + $row = $result->fetch_object(); + + if (!$result||!$row) return false; + + if ($row->medium==='1') $dir = 'medium'; + else $dir = 'big'; + + $parseUrl = parse_url('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); + $url = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '?' . $parseUrl['query']; + $picture = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '/../uploads/' . $dir . '/' . $row->url; + + $url = htmlentities($url); + $picture = htmlentities($picture); + + $row->title = htmlentities($row->title); + $row->description = htmlentities($row->description); + + $return = ''; + $return .= ''; + $return .= ''; + $return .= ''; + + $return .= ''; + $return .= ''; + $return .= ''; + $return .= ''; + + $return .= ''; + $return .= ''; + $return .= ''; + $return .= ''; + $return .= ''; + + return $return; + +} + +?> \ No newline at end of file diff --git a/php/helpers/getHashedString.php b/php/helpers/getHashedString.php new file mode 100644 index 0000000..1205586 --- /dev/null +++ b/php/helpers/getHashedString.php @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/php/helpers/hasPermissions.php b/php/helpers/hasPermissions.php new file mode 100644 index 0000000..f5f8bbd --- /dev/null +++ b/php/helpers/hasPermissions.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/php/helpers/search.php b/php/helpers/search.php new file mode 100755 index 0000000..5786b83 --- /dev/null +++ b/php/helpers/search.php @@ -0,0 +1,63 @@ + null, + 'albums' => null, + 'hash' => '' + ); + + ### + # Photos + ### + + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); + $result = Database::get()->query($query); + + while($photo = $result->fetch_assoc()) { + + $photo = Photo::prepareData($photo); + $return['photos'][$photo['id']] = $photo; + + } + + ### + # Albums + ### + + $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); + $result = Database::get()->query($query); + + while($album = $result->fetch_assoc()) { + + # Turn data from the database into a front-end friendly format + $album = Album::prepareData($album); + + # Thumbs + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::get()->query($query); + + # For each thumb + $k = 0; + while ($thumb = $thumbs->fetch_object()) { + $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; + $k++; + } + + # Add to return + $return['albums'][$album['id']] = $album; + + } + + # Hash + $return['hash'] = md5(json_encode($return)); + + return $return; + +} + +?> \ No newline at end of file diff --git a/php/api.php b/php/index.php similarity index 76% rename from php/api.php rename to php/index.php index 5f50dd9..b80c660 100755 --- a/php/api.php +++ b/php/index.php @@ -2,9 +2,29 @@ ### # @name API +# @author Tobias Reich # @copyright 2015 by Tobias Reich ### +namespace Lychee; + +use Lychee\Modules\Config; +use Lychee\Modules\Settings; + +use Lychee\Access\Installation; +use Lychee\Access\Admin; +use Lychee\Access\Guest; + +require(__DIR__ . '/define.php'); +require(__DIR__ . '/autoload.php'); + +require(__DIR__ . '/helpers/fastImageCopyResampled.php'); +require(__DIR__ . '/helpers/getExtension.php'); +require(__DIR__ . '/helpers/getGraphHeader.php'); +require(__DIR__ . '/helpers/getHashedString.php'); +require(__DIR__ . '/helpers/hasPermissions.php'); +require(__DIR__ . '/helpers/search.php'); + # Define the called function if (isset($_POST['function'])) $fn = $_POST['function']; else if (isset($_GET['function'])) $fn = $_GET['function']; @@ -17,11 +37,6 @@ if (!empty($fn)) { session_start(); date_default_timezone_set('UTC'); - # Load required files - require(__DIR__ . '/define.php'); - require(__DIR__ . '/autoload.php'); - require(__DIR__ . '/misc.php'); - # Validate parameters if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); diff --git a/php/misc.php b/php/misc.php deleted file mode 100755 index 07dde6b..0000000 --- a/php/misc.php +++ /dev/null @@ -1,195 +0,0 @@ - null, - 'albums' => null, - 'hash' => '' - ); - - ### - # Photos - ### - - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); - $result = Database::get()->query($query); - - while($photo = $result->fetch_assoc()) { - - $photo = Photo::prepareData($photo); - $return['photos'][$photo['id']] = $photo; - - } - - ### - # Albums - ### - - $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); - $result = Database::get()->query($query); - - while($album = $result->fetch_assoc()) { - - # Turn data from the database into a front-end friendly format - $album = Album::prepareData($album); - - # Thumbs - $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::get()->query($query); - - # For each thumb - $k = 0; - while ($thumb = $thumbs->fetch_object()) { - $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; - $k++; - } - - # Add to return - $return['albums'][$album['id']] = $album; - - } - - # Hash - $return['hash'] = md5(json_encode($return)); - - return $return; - -} - -function getGraphHeader($photoID) { - - $photo = new Photo($photoID); - if ($photo->getPublic('')===false) return false; - - $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); - $result = Database::get()->query($query); - $row = $result->fetch_object(); - - if (!$result||!$row) return false; - - if ($row->medium==='1') $dir = 'medium'; - else $dir = 'big'; - - $parseUrl = parse_url('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); - $url = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '?' . $parseUrl['query']; - $picture = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '/../uploads/' . $dir . '/' . $row->url; - - $url = htmlentities($url); - $picture = htmlentities($picture); - - $row->title = htmlentities($row->title); - $row->description = htmlentities($row->description); - - $return = ''; - $return .= ''; - $return .= ''; - $return .= ''; - - $return .= ''; - $return .= ''; - $return .= ''; - $return .= ''; - - $return .= ''; - $return .= ''; - $return .= ''; - $return .= ''; - $return .= ''; - - return $return; - -} - -function getExtension($filename) { - - $extension = strpos($filename, '.') !== false - ? strrchr($filename, '.') - : ''; - - return $extension; - -} - -function getHashedString($password) { - - # Inspired by http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/ - - # A higher $cost is more secure but consumes more processing power - $cost = 10; - - # Create a random salt - if (extension_loaded('openssl')) { - $salt = strtr(substr(base64_encode(openssl_random_pseudo_bytes(17)),0,22), '+', '.'); - } elseif (extension_loaded('mcrypt')) { - $salt = strtr(substr(base64_encode(mcrypt_create_iv(17, MCRYPT_DEV_URANDOM)),0,22), '+', '.'); - } else { - $salt = ""; - for ($i = 0; $i < 22; $i++) { - $salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 63), 1); - } - } - - # Prefix information about the hash so PHP knows how to verify it later. - # "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter. - $salt = sprintf("$2a$%02d$", $cost) . $salt; - - # Hash the password with the salt - return crypt($password, $salt); - -} - -function hasPermissions($path) { - - // Check if the given path is readable and writable - // Both functions are also verifying that the path exists - if (is_readable($path)===true&& - is_writeable($path)===true) return true; - - return false; - -} - -function fastimagecopyresampled(&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 4) { - - ### - # Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled. - # Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled". - # Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting. - # Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain. - # - # Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero. - # Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect. - # 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized. - # 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3. - # 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster. - # 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images. - # 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled. - ### - - if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; } - - if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) { - - $temp = imagecreatetruecolor($dst_w * $quality + 1, $dst_h * $quality + 1); - imagecopyresized($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h); - imagecopyresampled($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality); - imagedestroy($temp); - - } else imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); - - return true; - -} - -?> diff --git a/php/modules/Album.php b/php/modules/Album.php index e74997e..34ef0fb 100644 --- a/php/modules/Album.php +++ b/php/modules/Album.php @@ -1,11 +1,6 @@ connect_errno) return false; diff --git a/php/modules/Import.php b/php/modules/Import.php index ac1cc98..564948e 100644 --- a/php/modules/Import.php +++ b/php/modules/Import.php @@ -1,11 +1,6 @@ query($query); + + if (!$result) return false; + return true; + + } + public static function setLogin($oldPassword = '', $username, $password) { # Check dependencies @@ -63,10 +82,7 @@ final class Settings extends Module { # Execute query # Do not prepare $username because it is hashed and save # Preparing (escaping) the username would destroy the hash - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$username' WHERE `key` = 'username'", array(LYCHEE_TABLE_SETTINGS)); - $result = Database::get()->query($query); - - if (!$result) { + if (self::set('username', $username, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -82,13 +98,9 @@ final class Settings extends Module { # Hash password $password = getHashedString($password); - # Execute query # Do not prepare $password because it is hashed and save # Preparing (escaping) the password would destroy the hash - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$password' WHERE `key` = 'password'", array(LYCHEE_TABLE_SETTINGS)); - $result = Database::get()->query($query); - - if (!$result) { + if (self::set('password', $password, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -96,21 +108,17 @@ final class Settings extends Module { } - public static function setDropboxKey($key) { + public static function setDropboxKey($dropboxKey) { # Check dependencies - self::dependencies(isset($key)); + self::dependencies(isset($dropboxKey)); - if (strlen($key)<1||strlen($key)>50) { + if (strlen($dropboxKey)<1||strlen($dropboxKey)>50) { Log::notice(__METHOD__, __LINE__, 'Dropbox key is either too short or too long'); return false; } - # Execute query - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '?' WHERE `key` = 'dropboxKey'", array(LYCHEE_TABLE_SETTINGS, $key)); - $result = Database::get()->query($query); - - if (!$result) { + if (self::set('dropboxKey', $dropboxKey)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -168,14 +176,10 @@ final class Settings extends Module { } - # Execute query # Do not prepare $sorting because it is a true statement # Preparing (escaping) the sorting would destroy it # $sorting is save and can't contain user-input - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingPhotos'", array(LYCHEE_TABLE_SETTINGS)); - $result = Database::get()->query($query); - - if (!$result) { + if (self::set('sortingPhotos', $sorting, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -224,14 +228,10 @@ final class Settings extends Module { } - # Execute query # Do not prepare $sorting because it is a true statement # Preparing (escaping) the sorting would destroy it # $sorting is save and can't contain user-input - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingAlbums'", array(LYCHEE_TABLE_SETTINGS)); - $result = Database::get()->query($query); - - if (!$result) { + if (self::set('sortingAlbums', $sorting, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } diff --git a/plugins/check/index.php b/plugins/Diagnostics/index.php similarity index 97% rename from plugins/check/index.php rename to plugins/Diagnostics/index.php index 1a56c35..70a89ac 100644 --- a/plugins/check/index.php +++ b/plugins/Diagnostics/index.php @@ -7,13 +7,17 @@ # @description This file takes a look at your Lychee-configuration and displays all errors it can find. ### -# Location +namespace Diagnostics; + +use Mysqli; +use Lychee\Modules\Settings; + $lychee = __DIR__ . '/../../'; -# Load requirements require($lychee . 'php/define.php'); require($lychee . 'php/autoload.php'); -require($lychee . 'php/misc.php'); + +require($lychee . 'php/helpers/hasPermissions.php'); # Start the session session_start(); @@ -59,18 +63,18 @@ if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error: Configuration not found. Plea else require(LYCHEE_CONFIG_FILE); # Database -$database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName); +$database = new Mysqli($dbHost, $dbUser, $dbPassword, $dbName); if (mysqli_connect_errno()!=0) $error .= ('Error: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL); -# Load settings -$settings = Settings::get(); - # Config if (!isset($dbName)||$dbName==='') $error .= ('Error: No property for $dbName in config.php' . PHP_EOL); if (!isset($dbUser)||$dbUser==='') $error .= ('Error: No property for $dbUser in config.php' . PHP_EOL); if (!isset($dbPassword)) $error .= ('Error: No property for $dbPassword in config.php' . PHP_EOL); if (!isset($dbHost)||$dbHost==='') $error .= ('Error: No property for $dbHost in config.php' . PHP_EOL); +# Load settings +$settings = Settings::get(); + # Settings if (!isset($settings['username'])||$settings['username']=='') $error .= ('Error: Username empty or not set in database' . PHP_EOL); if (!isset($settings['password'])||$settings['password']=='') $error .= ('Error: Password empty or not set in database' . PHP_EOL); diff --git a/plugins/displaylog/index.php b/plugins/Log/index.php similarity index 65% rename from plugins/displaylog/index.php rename to plugins/Log/index.php index 0e36c5a..1ff92c6 100644 --- a/plugins/displaylog/index.php +++ b/plugins/Log/index.php @@ -1,23 +1,26 @@ query($query); + $query = Database::prepare(Database::get(), "SELECT FROM_UNIXTIME(time), type, function, line, text FROM ?", array(LYCHEE_TABLE_LOG)); + $result = Database::get()->query($query); # Output if ($result->num_rows===0) { diff --git a/src/scripts/api.js b/src/scripts/api.js index 264a7e6..1979d22 100644 --- a/src/scripts/api.js +++ b/src/scripts/api.js @@ -5,7 +5,7 @@ api = { - path : 'php/api.php', + path : 'php/index.php', onError : null } diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index cc036fd..dab6918 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -31,8 +31,8 @@ contextMenu.settings = function(e) { { title: build.iconic('dropbox', 'ionicons') + 'Set Dropbox', fn: settings.setDropboxKey }, { }, { title: build.iconic('info') + 'About Lychee', fn: () => window.open(lychee.website) }, - { title: build.iconic('wrench') + 'Diagnostics', fn: () => window.open('plugins/check/') }, - { title: build.iconic('align-left') + 'Show Log', fn: () => window.open('plugins/displaylog/') }, + { title: build.iconic('wrench') + 'Diagnostics', fn: () => window.open('plugins/Diagnostics/') }, + { title: build.iconic('align-left') + 'Show Log', fn: () => window.open('plugins/Log/') }, { }, { title: build.iconic('account-logout') + 'Sign Out', fn: lychee.logout } ] From 8c76d340a7cbf3140d962fa5e4f6cb5d31e84fe2 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 26 Jan 2016 15:33:59 +0100 Subject: [PATCH 033/183] Renamed folder to Access --- php/{access => Access}/Access.php | 0 php/{access => Access}/Admin.php | 0 php/{access => Access}/Guest.php | 0 php/{access => Access}/Installation.php | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename php/{access => Access}/Access.php (100%) rename php/{access => Access}/Admin.php (100%) rename php/{access => Access}/Guest.php (100%) rename php/{access => Access}/Installation.php (100%) diff --git a/php/access/Access.php b/php/Access/Access.php similarity index 100% rename from php/access/Access.php rename to php/Access/Access.php diff --git a/php/access/Admin.php b/php/Access/Admin.php similarity index 100% rename from php/access/Admin.php rename to php/Access/Admin.php diff --git a/php/access/Guest.php b/php/Access/Guest.php similarity index 100% rename from php/access/Guest.php rename to php/Access/Guest.php diff --git a/php/access/Installation.php b/php/Access/Installation.php similarity index 100% rename from php/access/Installation.php rename to php/Access/Installation.php From 6e7dccc03707b407fcab563f885e2cddc259d5c8 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 26 Jan 2016 15:34:51 +0100 Subject: [PATCH 034/183] Renamed folder to Modules --- php/{modules => Modules}/Album.php | 0 php/{modules => Modules}/Config.php | 0 php/{modules => Modules}/Database.php | 0 php/{modules => Modules}/Import.php | 0 php/{modules => Modules}/Log.php | 0 php/{modules => Modules}/Module.php | 0 php/{modules => Modules}/Photo.php | 0 php/{modules => Modules}/Plugins.php | 0 php/{modules => Modules}/Session.php | 0 php/{modules => Modules}/Settings.php | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename php/{modules => Modules}/Album.php (100%) rename php/{modules => Modules}/Config.php (100%) rename php/{modules => Modules}/Database.php (100%) rename php/{modules => Modules}/Import.php (100%) rename php/{modules => Modules}/Log.php (100%) rename php/{modules => Modules}/Module.php (100%) rename php/{modules => Modules}/Photo.php (100%) rename php/{modules => Modules}/Plugins.php (100%) rename php/{modules => Modules}/Session.php (100%) rename php/{modules => Modules}/Settings.php (100%) diff --git a/php/modules/Album.php b/php/Modules/Album.php similarity index 100% rename from php/modules/Album.php rename to php/Modules/Album.php diff --git a/php/modules/Config.php b/php/Modules/Config.php similarity index 100% rename from php/modules/Config.php rename to php/Modules/Config.php diff --git a/php/modules/Database.php b/php/Modules/Database.php similarity index 100% rename from php/modules/Database.php rename to php/Modules/Database.php diff --git a/php/modules/Import.php b/php/Modules/Import.php similarity index 100% rename from php/modules/Import.php rename to php/Modules/Import.php diff --git a/php/modules/Log.php b/php/Modules/Log.php similarity index 100% rename from php/modules/Log.php rename to php/Modules/Log.php diff --git a/php/modules/Module.php b/php/Modules/Module.php similarity index 100% rename from php/modules/Module.php rename to php/Modules/Module.php diff --git a/php/modules/Photo.php b/php/Modules/Photo.php similarity index 100% rename from php/modules/Photo.php rename to php/Modules/Photo.php diff --git a/php/modules/Plugins.php b/php/Modules/Plugins.php similarity index 100% rename from php/modules/Plugins.php rename to php/Modules/Plugins.php diff --git a/php/modules/Session.php b/php/Modules/Session.php similarity index 100% rename from php/modules/Session.php rename to php/Modules/Session.php diff --git a/php/modules/Settings.php b/php/Modules/Settings.php similarity index 100% rename from php/modules/Settings.php rename to php/Modules/Settings.php From 61fcaa57c026ab8af4827baa426bfad748397af5 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 00:07:22 +0100 Subject: [PATCH 035/183] Added "use SplObserver" --- php/Modules/Plugins.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/php/Modules/Plugins.php b/php/Modules/Plugins.php index 6377855..ab69e83 100644 --- a/php/Modules/Plugins.php +++ b/php/Modules/Plugins.php @@ -3,6 +3,7 @@ namespace Lychee\Modules; use SplSubject; +use SplObserver; final class Plugins implements SplSubject { @@ -42,7 +43,7 @@ final class Plugins implements SplSubject { } - public function attach(\SplObserver $observer) { + public function attach(SplObserver $observer) { if (!isset($observer)) return false; @@ -53,7 +54,7 @@ final class Plugins implements SplSubject { } - public function detach(\SplObserver $observer) { + public function detach(SplObserver $observer) { if (!isset($observer)) return false; From 4974adfed04747fb52cf8f4843203ff7d39f0643 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 00:27:50 +0100 Subject: [PATCH 036/183] Activate plugins directly without extending Module --- php/Modules/Album.php | 52 +++++++++++++++++----------------- php/Modules/Import.php | 8 +++--- php/Modules/Module.php | 14 ---------- php/Modules/Photo.php | 62 ++++++++++++++++++++--------------------- php/Modules/Plugins.php | 8 ++++-- php/Modules/Session.php | 12 ++++---- 6 files changed, 73 insertions(+), 83 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 34ef0fb..bdd540b 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -18,7 +18,7 @@ final class Album extends Module { public function add($title = 'Untitled') { # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Parse if (strlen($title)>50) $title = substr($title, 0, 50); @@ -33,7 +33,7 @@ final class Album extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -85,7 +85,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get album information switch ($this->albumIDs) { @@ -160,7 +160,7 @@ final class Album extends Module { $return['num'] = $photos->num_rows; # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -172,7 +172,7 @@ final class Album extends Module { self::dependencies(isset($public)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Initialize return var $return = array( @@ -227,7 +227,7 @@ final class Album extends Module { $return['num'] = $albums->num_rows; # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -334,7 +334,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Illicit chars $badChars = array_merge( @@ -462,7 +462,7 @@ final class Album extends Module { unlink($filename); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -474,14 +474,14 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Execute query $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -497,14 +497,14 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Execute query $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -520,7 +520,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f') return false; @@ -530,7 +530,7 @@ final class Album extends Module { $album = $albums->fetch_object(); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->public==1) return true; return false; @@ -543,7 +543,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f'||$this->albumIDs==='r') return false; @@ -553,7 +553,7 @@ final class Album extends Module { $album = $albums->fetch_object(); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->downloadable==1) return true; return false; @@ -566,7 +566,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Convert values $public = ($public==='1' ? 1 : 0); @@ -592,7 +592,7 @@ final class Album extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); # Set password if (isset($password)&&strlen($password)>0) return $this->setPassword($password); @@ -607,7 +607,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); if (strlen($password)>0) { @@ -630,7 +630,7 @@ final class Album extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -646,7 +646,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Execute query $query = Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); @@ -654,7 +654,7 @@ final class Album extends Module { $album = $albums->fetch_object(); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->password=='') return true; else if ($album->password===crypt($password, $album->password)) return true; @@ -668,7 +668,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Convert to array $albumIDs = explode(',', $this->albumIDs); @@ -693,7 +693,7 @@ final class Album extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -709,7 +709,7 @@ final class Album extends Module { self::dependencies(isset($this->albumIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Init vars $error = false; @@ -731,7 +731,7 @@ final class Album extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error) return false; if (!$result) { diff --git a/php/Modules/Import.php b/php/Modules/Import.php index 564948e..410d890 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -35,7 +35,7 @@ final class Import extends Module { self::dependencies(isset($urls)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); $error = false; @@ -84,7 +84,7 @@ final class Import extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===false) return true; return false; @@ -117,7 +117,7 @@ final class Import extends Module { # Call plugins # Note that updated albumId and path explicitly passed, rather # than using func_get_args() which will only return original ones - $this->plugins(__METHOD__, 0, array($albumID, $path)); + Plugins::get()->activate(__METHOD__, 0, array($albumID, $path)); # Get all files $files = glob($path . '/*'); @@ -173,7 +173,7 @@ final class Import extends Module { # Call plugins # Note that updated albumId and path explicitly passed, rather # than using func_get_args() which will only return original ones - $this->plugins(__METHOD__, 1, array($albumID, $path)); + Plugins::get()->activate(__METHOD__, 1, array($albumID, $path)); # The following returns will be caught in the front-end if ($contains['photos']===false&&$contains['albums']===false) return 'Warning: Folder empty or no readable files to process!'; diff --git a/php/Modules/Module.php b/php/Modules/Module.php index 35a9d5d..3d8d058 100644 --- a/php/Modules/Module.php +++ b/php/Modules/Module.php @@ -4,20 +4,6 @@ namespace Lychee\Modules; abstract class Module { - protected function plugins($name, $location, $args) { - - self::dependencies(isset($name, $location, $args)); - - # Parse - $location = ($location===0 ? 'before' : 'after'); - - # Call plugins - Plugins::get()->activate($name . ":" . $location, $args); - - return true; - - } - final public static function dependencies($available = false) { if ($available===false) exit('Error: Can not execute function. Missing parameters or variables.'); diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 0dd2f5d..637f635 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -45,7 +45,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); switch($albumID) { @@ -247,7 +247,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -294,7 +294,7 @@ final class Photo extends Module { self::dependencies(isset($url, $filename, $type, $width, $height)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Size of the thumbnail $newWidth = 200; @@ -371,7 +371,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -393,7 +393,7 @@ final class Photo extends Module { self::dependencies(isset($url, $filename, $width, $height)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Set to true when creation of medium-photo failed $error = false; @@ -450,7 +450,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===true) return false; return true; @@ -471,7 +471,7 @@ final class Photo extends Module { self::dependencies(isset($path, $info)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); $swapSize = false; @@ -577,7 +577,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); # SwapSize should be true when the image has been rotated # Return new dimensions in this case @@ -648,7 +648,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get photo $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -689,7 +689,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $photo; @@ -707,7 +707,7 @@ final class Photo extends Module { self::dependencies(isset($url)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); $iptcArray = array(); $info = getimagesize($url, $iptcArray); @@ -797,7 +797,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -814,7 +814,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get photo $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -861,7 +861,7 @@ final class Photo extends Module { readfile(LYCHEE_UPLOADS_BIG . $photo->url); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -880,14 +880,14 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Set title $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -910,14 +910,14 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Set description $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -938,7 +938,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Init vars $error = false; @@ -961,7 +961,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===true) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -983,7 +983,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get photo $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -1012,7 +1012,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); # Photo private return 0; @@ -1030,7 +1030,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get public $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -1045,7 +1045,7 @@ final class Photo extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -1066,14 +1066,14 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Set album $query = Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -1096,7 +1096,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Parse tags $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); @@ -1107,7 +1107,7 @@ final class Photo extends Module { $result = Database::get()->query($query); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); @@ -1128,7 +1128,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get photos $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -1171,7 +1171,7 @@ final class Photo extends Module { self::dependencies(isset($this->photoIDs)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Get photos $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); @@ -1229,7 +1229,7 @@ final class Photo extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; diff --git a/php/Modules/Plugins.php b/php/Modules/Plugins.php index ab69e83..13bb55c 100644 --- a/php/Modules/Plugins.php +++ b/php/Modules/Plugins.php @@ -75,9 +75,13 @@ final class Plugins implements SplSubject { } - public function activate($action, $args) { + public function activate($name, $location, array $args) { - if (!isset($action, $args)) return false; + if (!isset($name, $location, $args)) return false; + + # Parse + $location = ($location===0 ? 'before' : 'after'); + $action = $name . ":" . $location; # Save vars $this->action = $action; diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 2a16b5b..be3e115 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -10,7 +10,7 @@ final class Session extends Module { self::dependencies(isset($public)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); # Return settings $return['config'] = Settings::get(); @@ -57,7 +57,7 @@ final class Session extends Module { } # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -69,7 +69,7 @@ final class Session extends Module { self::dependencies(isset($username, $password)); # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); $username = crypt($username, Settings::get()['username']); $password = crypt($password, Settings::get()['password']); @@ -86,7 +86,7 @@ final class Session extends Module { if ($this->noLogin()===true) return true; # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return false; @@ -109,7 +109,7 @@ final class Session extends Module { public function logout() { # Call plugins - $this->plugins(__METHOD__, 0, func_get_args()); + Plugins::get()->activate(__METHOD__, 0, func_get_args()); $_SESSION['login'] = null; $_SESSION['identifier'] = null; @@ -117,7 +117,7 @@ final class Session extends Module { session_destroy(); # Call plugins - $this->plugins(__METHOD__, 1, func_get_args()); + Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; From cafcc2165f00c9540ae41ee1d2651d1536dd65a0 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 01:06:21 +0100 Subject: [PATCH 037/183] Removed unnecessary self::dependencies checks --- php/Modules/Album.php | 5 +---- php/Modules/Photo.php | 27 +++------------------------ php/Modules/Session.php | 6 ------ 3 files changed, 4 insertions(+), 34 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index bdd540b..000df47 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -43,15 +43,12 @@ final class Album extends Module { } - public static function prepareData($data) { + public static function prepareData(array $data) { # This function requires the following album-attributes and turns them # into a front-end friendly format: id, title, public, sysstamp, password # Note that some attributes remain unchanged - # Check dependencies - self::dependencies(isset($data)); - # Init $album = null; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 637f635..b862d78 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -28,14 +28,11 @@ final class Photo extends Module { } - public function add($files, $albumID = 0, $description = '', $tags = '', $returnOnError = false) { + public function add(array $files, $albumID = 0, $description = '', $tags = '', $returnOnError = false) { # Use $returnOnError if you want to handle errors by your own # e.g. when calling this functions inside an if-condition - # Check dependencies - self::dependencies(isset($files)); - # Check permissions if (hasPermissions(LYCHEE_UPLOADS)===false|| hasPermissions(LYCHEE_UPLOADS_BIG)===false|| @@ -255,9 +252,6 @@ final class Photo extends Module { private function exists($checksum, $photoID = null) { - # Check dependencies - self::dependencies(isset($checksum)); - # Exclude $photoID from select when $photoID is set if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); @@ -290,9 +284,6 @@ final class Photo extends Module { private function createThumb($url, $filename, $type, $width, $height) { - # Check dependencies - self::dependencies(isset($url, $filename, $type, $width, $height)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -389,9 +380,6 @@ final class Photo extends Module { # (boolean) true = Success # (boolean) false = Failure - # Check dependencies - self::dependencies(isset($url, $filename, $width, $height)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -457,7 +445,7 @@ final class Photo extends Module { } - public function adjustFile($path, $info) { + public function adjustFile($path, array $info) { # Function rotates and flips a photo based on its EXIF orientation # Excepts the following: @@ -467,9 +455,6 @@ final class Photo extends Module { # (array) $info = ['orientation', 'width', 'height'] = Success # (boolean) false = Failure - # Check dependencies - self::dependencies(isset($path, $info)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -591,7 +576,7 @@ final class Photo extends Module { } - public static function prepareData($data) { + public static function prepareData(array $data) { # Function turns photo-attributes into a front-end friendly format. Note that some attributes remain unchanged. # Excepts the following: @@ -599,9 +584,6 @@ final class Photo extends Module { # Returns the following: # (array) $photo - # Check dependencies - self::dependencies(isset($data)); - # Init $photo = null; @@ -703,9 +685,6 @@ final class Photo extends Module { # Returns the following: # (array) $return - # Check dependencies - self::dependencies(isset($url)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); diff --git a/php/Modules/Session.php b/php/Modules/Session.php index be3e115..b5ef689 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -6,9 +6,6 @@ final class Session extends Module { public function init($public) { - # Check dependencies - self::dependencies(isset($public)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -65,9 +62,6 @@ final class Session extends Module { public function login($username, $password) { - # Check dependencies - self::dependencies(isset($username, $password)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); From 3287e27ccd33f02f2659db4e39d4f9d6a202eaaf Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 20:18:10 +0100 Subject: [PATCH 038/183] Default param for Session init --- php/Modules/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Modules/Session.php b/php/Modules/Session.php index b5ef689..b7fb8a2 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -4,7 +4,7 @@ namespace Lychee\Modules; final class Session extends Module { - public function init($public) { + public function init($public = true) { # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); From c904b8e2a578793616a19574920587c4d854282c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 20:18:24 +0100 Subject: [PATCH 039/183] Remove skipDuplicates from init response when logged out --- php/Modules/Session.php | 1 + 1 file changed, 1 insertion(+) diff --git a/php/Modules/Session.php b/php/Modules/Session.php index b7fb8a2..75f7322 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -41,6 +41,7 @@ final class Session extends Module { $return['status'] = LYCHEE_STATUS_LOGGEDOUT; # Unset unused vars + unset($return['config']['skipDuplicates']); unset($return['config']['thumbQuality']); unset($return['config']['sortingAlbums']); unset($return['config']['sortingPhotos']); From ad4fbf3ffdf670ecfef3117717320c3b6310afbd Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 20:22:28 +0100 Subject: [PATCH 040/183] Code style adjustment --- php/Modules/Album.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 000df47..486c456 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -4,7 +4,7 @@ namespace Lychee\Modules; final class Album extends Module { - private $albumIDs = null; + private $albumIDs = null; public function __construct($albumIDs) { From b13283e4d47dfcd3c5b9c1e5c279b5610546b8fc Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 21:33:31 +0100 Subject: [PATCH 041/183] Added Validator, removed Module, changed Access classes --- php/Access/Access.php | 8 +- php/Access/Admin.php | 208 ++++++++++++++++++++---------------- php/Access/Guest.php | 65 +++++------ php/Access/Installation.php | 17 +-- php/Modules/Album.php | 29 +++-- php/Modules/Config.php | 2 +- php/Modules/Database.php | 20 ++-- php/Modules/Import.php | 8 +- php/Modules/Log.php | 4 +- php/Modules/Module.php | 15 --- php/Modules/Photo.php | 24 ++--- php/Modules/Session.php | 2 +- php/Modules/Settings.php | 18 +--- php/Modules/Validator.php | 55 ++++++++++ php/index.php | 33 +++--- 15 files changed, 280 insertions(+), 228 deletions(-) delete mode 100644 php/Modules/Module.php create mode 100644 php/Modules/Validator.php diff --git a/php/Access/Access.php b/php/Access/Access.php index 50551f7..b90f210 100644 --- a/php/Access/Access.php +++ b/php/Access/Access.php @@ -2,9 +2,13 @@ namespace Lychee\Access; -interface Access { +abstract class Access { - public function check($fn); + final private static function fnNotFound() { + + exit('Error: Function not found! Please check the spelling of the called function.'); + + } } diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 659e325..c4576d2 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -4,63 +4,62 @@ namespace Lychee\Access; use Lychee\Modules\Album; use Lychee\Modules\Import; -use Lychee\Modules\Module; use Lychee\Modules\Photo; use Lychee\Modules\Session; use Lychee\Modules\Settings; +use Lychee\Modules\Validator; -final class Admin implements Access { +final class Admin extends Access { - public function check($fn) { + public static function init($fn) { switch ($fn) { # Album functions - case 'Album::getAll': $this->getAlbums(); break; - case 'Album::get': $this->getAlbum(); break; - case 'Album::add': $this->addAlbum(); break; - case 'Album::setTitle': $this->setAlbumTitle(); break; - case 'Album::setDescription': $this->setAlbumDescription(); break; - case 'Album::setPublic': $this->setAlbumPublic(); break; - case 'Album::delete': $this->deleteAlbum(); break; - case 'Album::merge': $this->mergeAlbums(); break; + case 'Album::getAll': self::getAlbumsAction(); break; + case 'Album::get': self::getAlbumAction(); break; + case 'Album::add': self::addAlbumAction(); break; + case 'Album::setTitle': self::setAlbumTitleAction(); break; + case 'Album::setDescription': self::setAlbumDescriptionAction(); break; + case 'Album::setPublic': self::setAlbumPublicAction(); break; + case 'Album::delete': self::deleteAlbumAction(); break; + case 'Album::merge': self::mergeAlbumsAction(); break; # Photo functions - case 'Photo::get': $this->getPhoto(); break; - case 'Photo::setTitle': $this->setPhotoTitle(); break; - case 'Photo::setDescription': $this->setPhotoDescription(); break; - case 'Photo::setStar': $this->setPhotoStar(); break; - case 'Photo::setPublic': $this->setPhotoPublic(); break; - case 'Photo::setAlbum': $this->setPhotoAlbum(); break; - case 'Photo::setTags': $this->setPhotoTags(); break; - case 'Photo::duplicate': $this->duplicatePhoto(); break; - case 'Photo::delete': $this->deletePhoto(); break; + case 'Photo::get': self::getPhotoAction(); break; + case 'Photo::setTitle': self::setPhotoTitleAction(); break; + case 'Photo::setDescription': self::setPhotoDescriptionAction(); break; + case 'Photo::setStar': self::setPhotoStarAction(); break; + case 'Photo::setPublic': self::setPhotoPublicAction(); break; + case 'Photo::setAlbum': self::setPhotoAlbumAction(); break; + case 'Photo::setTags': self::setPhotoTagsAction(); break; + case 'Photo::duplicate': self::duplicatePhotoAction(); break; + case 'Photo::delete': self::deletePhotoAction(); break; # Add functions - case 'Photo::add': $this->upload(); break; - case 'Import::url': $this->importUrl(); break; - case 'Import::server': $this->importServer(); break; + case 'Photo::add': self::uploadAction(); break; + case 'Import::url': self::importUrlAction(); break; + case 'Import::server': self::importServerAction(); break; # Search functions - case 'search': $this->search(); break; + case 'search': self::searchAction(); break; # Session functions - case 'Session::init': $this->init(); break; - case 'Session::login': $this->login(); break; - case 'Session::logout': $this->logout(); break; + case 'Session::init': self::initAction(); break; + case 'Session::login': self::loginAction(); break; + case 'Session::logout': self::logoutAction(); break; # Settings functions - case 'Settings::setLogin': $this->setLogin(); break; - case 'Settings::setSorting': $this->setSorting(); break; - case 'Settings::setDropboxKey': $this->setDropboxKey(); break; + case 'Settings::setLogin': self::setLoginAction(); break; + case 'Settings::setSorting': self::setSortingAction(); break; + case 'Settings::setDropboxKey': self::setDropboxKeyAction(); break; # $_GET functions - case 'Album::getArchive': $this->getAlbumArchive(); break; - case 'Photo::getArchive': $this->getPhotoArchive(); break; + case 'Album::getArchive': self::getAlbumArchiveAction(); break; + case 'Photo::getArchive': self::getPhotoArchiveAction(); break; # Error - default: exit('Error: Function not found! Please check the spelling of the called function.'); - return false; break; + default: self::fnNotFound(); break; } @@ -70,64 +69,70 @@ final class Admin implements Access { # Album functions - private function getAlbums() { + private static function getAlbumsAction() { $album = new Album(null); echo json_encode($album->getAll(false)); } - private function getAlbum() { + private static function getAlbumAction() { + + Validator::required(isset($_POST['albumID']), __METHOD__); - Module::dependencies(isset($_POST['albumID'])); $album = new Album($_POST['albumID']); echo json_encode($album->get()); } - private function addAlbum() { + private static function addAlbumAction() { + + Validator::required(isset($_POST['title']), __METHOD__); - Module::dependencies(isset($_POST['title'])); $album = new Album(null); echo $album->add($_POST['title']); } - private function setAlbumTitle() { + private static function setAlbumTitleAction() { + + Validator::required(isset($_POST['albumIDs'], $_POST['title']), __METHOD__); - Module::dependencies(isset($_POST['albumIDs'], $_POST['title'])); $album = new Album($_POST['albumIDs']); echo $album->setTitle($_POST['title']); } - private function setAlbumDescription() { + private static function setAlbumDescriptionAction() { + + Validator::required(isset($_POST['albumID'], $_POST['description']), __METHOD__); - Module::dependencies(isset($_POST['albumID'], $_POST['description'])); $album = new Album($_POST['albumID']); echo $album->setDescription($_POST['description']); } - private function setAlbumPublic() { + private static function setAlbumPublicAction() { + + Validator::required(isset($_POST['albumID'], $_POST['password'], $_POST['visible'], $_POST['downloadable']), __METHOD__); - Module::dependencies(isset($_POST['albumID'], $_POST['password'], $_POST['visible'], $_POST['downloadable'])); $album = new Album($_POST['albumID']); echo $album->setPublic($_POST['public'], $_POST['password'], $_POST['visible'], $_POST['downloadable']); } - private function deleteAlbum() { + private static function deleteAlbumAction() { + + Validator::required(isset($_POST['albumIDs']), __METHOD__); - Module::dependencies(isset($_POST['albumIDs'])); $album = new Album($_POST['albumIDs']); echo $album->delete(); } - private function mergeAlbums() { + private static function mergeAlbumsAction() { - Module::dependencies(isset($_POST['albumIDs'])); + Validator::required(isset($_POST['albumIDs'])); $album = new Album($_POST['albumIDs']); echo $album->merge(); @@ -135,73 +140,82 @@ final class Admin implements Access { # Photo functions - private function getPhoto() { + private static function getPhotoAction() { + + Validator::required(isset($_POST['photoID'], $_POST['albumID']), __METHOD__); - Module::dependencies(isset($_POST['photoID'], $_POST['albumID'])); $photo = new Photo($_POST['photoID']); echo json_encode($photo->get($_POST['albumID'])); } - private function setPhotoTitle() { + private static function setPhotoTitleAction() { + + Validator::required(isset($_POST['photoIDs'], $_POST['title']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'], $_POST['title'])); $photo = new Photo($_POST['photoIDs']); echo $photo->setTitle($_POST['title']); } - private function setPhotoDescription() { + private static function setPhotoDescriptionAction() { + + Validator::required(isset($_POST['photoID'], $_POST['description']), __METHOD__); - Module::dependencies(isset($_POST['photoID'], $_POST['description'])); $photo = new Photo($_POST['photoID']); echo $photo->setDescription($_POST['description']); } - private function setPhotoStar() { + private static function setPhotoStarAction() { + + Validator::required(isset($_POST['photoIDs']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'])); $photo = new Photo($_POST['photoIDs']); echo $photo->setStar(); } - private function setPhotoPublic() { + private static function setPhotoPublicAction() { + + Validator::required(isset($_POST['photoID']), __METHOD__); - Module::dependencies(isset($_POST['photoID'])); $photo = new Photo($_POST['photoID']); echo $photo->setPublic(); } - private function setPhotoAlbum() { + private static function setPhotoAlbumAction() { + + Validator::required(isset($_POST['photoIDs'], $_POST['albumID']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'], $_POST['albumID'])); $photo = new Photo($_POST['photoIDs']); echo $photo->setAlbum($_POST['albumID']); } - private function setPhotoTags() { + private static function setPhotoTagsAction() { + + Validator::required(isset($_POST['photoIDs'], $_POST['tags']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'], $_POST['tags'])); $photo = new Photo($_POST['photoIDs']); echo $photo->setTags($_POST['tags']); } - private function duplicatePhoto() { + private static function duplicatePhotoAction() { + + Validator::required(isset($_POST['photoIDs']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'])); $photo = new Photo($_POST['photoIDs']); echo $photo->duplicate(); } - private function deletePhoto() { + private static function deletePhotoAction() { + + Validator::required(isset($_POST['photoIDs']), __METHOD__); - Module::dependencies(isset($_POST['photoIDs'])); $photo = new Photo($_POST['photoIDs']); echo $photo->delete(); @@ -209,59 +223,62 @@ final class Admin implements Access { # Add functions - private function upload() { + private static function uploadAction() { + + Validator::required(isset($_FILES, $_POST['albumID'], $_POST['tags']), __METHOD__); - Module::dependencies(isset($_FILES, $_POST['albumID'], $_POST['tags'])); $photo = new Photo(null); echo $photo->add($_FILES, $_POST['albumID'], '', $_POST['tags']); } - private function importUrl() { + private static function importUrlAction() { + + Validator::required(isset($_POST['url'], $_POST['albumID']), __METHOD__); - Module::dependencies(isset($_POST['url'], $_POST['albumID'])); $import = new Import(); echo $import->url($_POST['url'], $_POST['albumID']); } - private function importServer() { + private static function importServerAction() { + + Validator::required(isset($_POST['albumID'], $_POST['path']), __METHOD__); - Module::dependencies(isset($_POST['albumID'], $_POST['path'])); $import = new Import(); echo $import->server($_POST['path'], $_POST['albumID']); } - # Search function + # Search functions - private function search() { + private static function searchAction() { + + Validator::required(isset($_POST['term']), __METHOD__); - Module::dependencies(isset($_POST['term'])); echo json_encode(search($_POST['term'])); } # Session functions - private function init() { - - global $dbName; + private static function initAction() { $session = new Session(); echo json_encode($session->init(false)); } - private function login() { + private static function loginAction() { + + Validator::required(isset($_POST['user'], $_POST['password']), __METHOD__); - Module::dependencies(isset($_POST['user'], $_POST['password'])); $session = new Session(); echo $session->login($_POST['user'], $_POST['password']); } - private function logout() { + private static function logoutAction() { $session = new Session(); echo $session->logout(); @@ -270,17 +287,17 @@ final class Admin implements Access { # Settings functions - private function setLogin() { + private static function setLoginAction() { - Module::dependencies(isset($_POST['username'], $_POST['password'])); - if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = ''; - echo Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); + Validator::required(isset($_POST['username'], $_POST['password']), __METHOD__); + + echo Settings::setLogin(@$_POST['oldPassword'], $_POST['username'], $_POST['password']); } - private function setSorting() { + private static function setSortingAction() { - Module::dependencies(isset($_POST['typeAlbums'], $_POST['orderAlbums'], $_POST['typePhotos'], $_POST['orderPhotos'])); + Validator::required(isset($_POST['typeAlbums'], $_POST['orderAlbums'], $_POST['typePhotos'], $_POST['orderPhotos']), __METHOD__); $sA = Settings::setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']); $sP = Settings::setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']); @@ -290,26 +307,29 @@ final class Admin implements Access { } - private function setDropboxKey() { + private static function setDropboxKeyAction() { + + Validator::required(isset($_POST['key']), __METHOD__); - Module::dependencies(isset($_POST['key'])); echo Settings::setDropboxKey($_POST['key']); } # Get functions - private function getAlbumArchive() { + private static function getAlbumArchiveAction() { + + Validator::required(isset($_GET['albumID']), __METHOD__); - Module::dependencies(isset($_GET['albumID'])); $album = new Album($_GET['albumID']); $album->getArchive(); } - private function getPhotoArchive() { + private static function getPhotoArchiveAction() { + + Validator::required(isset($_GET['photoID']), __METHOD__); - Module::dependencies(isset($_GET['photoID'])); $photo = new Photo($_GET['photoID']); $photo->getArchive(); diff --git a/php/Access/Guest.php b/php/Access/Guest.php index e1050b4..73fca67 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -3,36 +3,35 @@ namespace Lychee\Access; use Lychee\Modules\Album; -use Lychee\Modules\Module; use Lychee\Modules\Photo; use Lychee\Modules\Session; +use Lychee\Modules\Validator; -final class Guest implements Access { +final class Guest extends Access { - public function check($fn) { + public static function init($fn) { switch ($fn) { # Album functions - case 'Album::getAll': $this->getAlbums(); break; - case 'Album::get': $this->getAlbum(); break; - case 'Album::getPublic': $this->checkAlbumAccess(); break; + case 'Album::getAll': self::getAlbumsAction(); break; + case 'Album::get': self::getAlbumAction(); break; + case 'Album::getPublic': self::checkAlbumAccessAction(); break; # Photo functions - case 'Photo::get': $this->getPhoto(); break; + case 'Photo::get': self::getPhotoAction(); break; # Session functions - case 'Session::init': $this->init(); break; - case 'Session::login': $this->login(); break; - case 'Session::logout': $this->logout(); break; + case 'Session::init': self::initAction(); break; + case 'Session::login': self::loginAction(); break; + case 'Session::logout': self::logoutAction(); break; # $_GET functions - case 'Album::getArchive': $this->getAlbumArchive(); break; - case 'Photo::getArchive': $this->getPhotoArchive(); break; + case 'Album::getArchive': self::getAlbumArchiveAction(); break; + case 'Photo::getArchive': self::getPhotoArchiveAction(); break; # Error - default: exit('Error: Function not found! Please check the spelling of the called function.'); - break; + default: self::fnNotFound(); break; } @@ -42,16 +41,17 @@ final class Guest implements Access { # Album functions - private function getAlbums() { + private static function getAlbumsAction() { $album = new Album(null); echo json_encode($album->getAll(true)); } - private function getAlbum() { + private static function getAlbumAction() { + + Validator::required(isset($_POST['albumID'], $_POST['password']), __METHOD__); - Module::dependencies(isset($_POST['albumID'], $_POST['password'])); $album = new Album($_POST['albumID']); if ($album->getPublic()) { @@ -69,9 +69,10 @@ final class Guest implements Access { } - private function checkAlbumAccess() { + private static function checkAlbumAccessAction() { + + Validator::required(isset($_POST['albumID'], $_POST['password']), __METHOD__); - Module::dependencies(isset($_POST['albumID'], $_POST['password'])); $album = new Album($_POST['albumID']); if ($album->getPublic()) { @@ -91,9 +92,10 @@ final class Guest implements Access { # Photo functions - private function getPhoto() { + private static function getPhotoAction() { + + Validator::required(isset($_POST['photoID'], $_POST['albumID'], $_POST['password']), __METHOD__); - Module::dependencies(isset($_POST['photoID'], $_POST['albumID'], $_POST['password'])); $photo = new Photo($_POST['photoID']); $pgP = $photo->getPublic($_POST['password']); @@ -106,24 +108,23 @@ final class Guest implements Access { # Session functions - private function init() { - - global $dbName; + private static function initAction() { $session = new Session(); echo json_encode($session->init(true)); } - private function login() { + private static function loginAction() { + + Validator::required(isset($_POST['user'], $_POST['password']), __METHOD__); - Module::dependencies(isset($_POST['user'], $_POST['password'])); $session = new Session(); echo $session->login($_POST['user'], $_POST['password']); } - private function logout() { + private static function logoutAction() { $session = new Session(); echo $session->logout(); @@ -132,9 +133,10 @@ final class Guest implements Access { # $_GET functions - private function getAlbumArchive() { + private static function getAlbumArchiveAction() { + + Validator::required(isset($_GET['albumID'], $_GET['password']), __METHOD__); - Module::dependencies(isset($_GET['albumID'], $_GET['password'])); $album = new Album($_GET['albumID']); if ($album->getPublic()&&$album->getDownloadable()) { @@ -152,9 +154,10 @@ final class Guest implements Access { } - private function getPhotoArchive() { + private static function getPhotoArchiveAction() { + + Validator::required(isset($_GET['photoID'], $_GET['password']), __METHOD__); - Module::dependencies(isset($_GET['photoID'], $_GET['password'])); $photo = new Photo($_GET['photoID']); $pgP = $photo->getPublic($_GET['password']); diff --git a/php/Access/Installation.php b/php/Access/Installation.php index ec1cabb..982642f 100644 --- a/php/Access/Installation.php +++ b/php/Access/Installation.php @@ -3,18 +3,18 @@ namespace Lychee\Access; use Lychee\Modules\Config; -use Lychee\Modules\Module; +use Lychee\Modules\Validator; -final class Installation implements Access { +final class Installation extends Access { - public function check($fn) { + public static function init($fn) { switch ($fn) { - case 'Config::create': $this->configCreate(); break; + case 'Config::create': self::configCreateAction(); break; # Error - default: $this->init(); break; + default: self::initAction(); break; } @@ -22,14 +22,15 @@ final class Installation implements Access { } - private function configCreate() { + private static function configCreateAction() { + + Validator::required(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix'])); - Module::dependencies(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix'])); echo Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']); } - private function init() { + private static function initAction() { $return = array( 'status' => LYCHEE_STATUS_NOCONFIG diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 486c456..b5b051a 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Album extends Module { +final class Album { private $albumIDs = null; @@ -79,7 +79,7 @@ final class Album extends Module { public function get() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -163,10 +163,7 @@ final class Album extends Module { } - public function getAll($public) { - - # Check dependencies - self::dependencies(isset($public)); + public function getAll($public = true) { # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -328,7 +325,7 @@ final class Album extends Module { public function getArchive() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -468,7 +465,7 @@ final class Album extends Module { public function setTitle($title = 'Untitled') { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -491,7 +488,7 @@ final class Album extends Module { public function setDescription($description = '') { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -514,7 +511,7 @@ final class Album extends Module { public function getPublic() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -537,7 +534,7 @@ final class Album extends Module { public function getDownloadable() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -560,7 +557,7 @@ final class Album extends Module { public function setPublic($public, $password, $visible, $downloadable) { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -601,7 +598,7 @@ final class Album extends Module { private function setPassword($password) { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -640,7 +637,7 @@ final class Album extends Module { public function checkPassword($password) { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -662,7 +659,7 @@ final class Album extends Module { public function merge() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -703,7 +700,7 @@ final class Album extends Module { public function delete() { # Check dependencies - self::dependencies(isset($this->albumIDs)); + Validator::required(isset($this->albumIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); diff --git a/php/Modules/Config.php b/php/Modules/Config.php index 85cd28f..0c03786 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Config extends Module { +final class Config { public static function create($host, $user, $password, $name = 'lychee', $prefix = '') { diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 6804e80..770d62b 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -4,7 +4,7 @@ namespace Lychee\Modules; use Mysqli; -final class Database extends Module { +final class Database { private $connection = null; private static $instance = null; @@ -39,7 +39,7 @@ final class Database extends Module { private function __construct($host, $user, $password, $name = 'lychee', $dbTablePrefix) { # Check dependencies - Module::dependencies(isset($host, $user, $password, $name)); + Validator::required(isset($host, $user, $password, $name), __METHOD__); # Define the table prefix defineTablePrefix($dbTablePrefix); @@ -79,6 +79,9 @@ final class Database extends Module { private static function setCharset($connection) { + # Check dependencies + Validator::required(isset($connection), __METHOD__); + # Avoid sql injection on older MySQL versions by using GBK if ($connection->server_version<50500) @$connection->set_charset('GBK'); else @$connection->set_charset('utf8'); @@ -93,7 +96,7 @@ final class Database extends Module { public static function createDatabase($connection, $name = 'lychee') { # Check dependencies - Module::dependencies(isset($connection, $name)); + Validator::required(isset($connection), __METHOD__); # Check if database exists if ($connection->select_db($name)) return true; @@ -110,7 +113,7 @@ final class Database extends Module { private static function createTables($connection) { # Check dependencies - Module::dependencies(isset($connection)); + Validator::required(isset($connection), __METHOD__); # Check if tables exist $query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); @@ -229,7 +232,7 @@ final class Database extends Module { private static function update($connection, $dbName) { # Check dependencies - Module::dependencies(isset($connection)); + Validator::required(isset($connection, $dbName), __METHOD__); # Get current version $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); @@ -253,6 +256,9 @@ final class Database extends Module { public static function setVersion($connection, $version) { + # Check dependencies + Validator::required(isset($connection), __METHOD__); + $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); $result = $connection->query($query); if (!$result) { @@ -262,10 +268,10 @@ final class Database extends Module { } - public static function prepare($connection, $query, $data) { + public static function prepare($connection, $query, array $data) { # Check dependencies - Module::dependencies(isset($connection, $query, $data)); + Validator::required(isset($connection, $query), __METHOD__); # Count the number of placeholders and compare it with the number of arguments # If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement diff --git a/php/Modules/Import.php b/php/Modules/Import.php index 410d890..dcc3041 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -2,13 +2,10 @@ namespace Lychee\Modules; -final class Import extends Module { +final class Import { private function photo($path, $albumID = 0, $description = '', $tags = '') { - # Check dependencies - self::dependencies(isset($path)); - # No need to validate photo type and extension in this function. # $photo->add will take care of it. @@ -31,9 +28,6 @@ final class Import extends Module { public function url($urls, $albumID = 0) { - # Check dependencies - self::dependencies(isset($urls)); - # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); diff --git a/php/Modules/Log.php b/php/Modules/Log.php index 4be35e8..44e9696 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Log extends Module { +final class Log { public static function notice($function, $line, $text = '') { @@ -25,7 +25,7 @@ final class Log extends Module { private static function text($type, $function, $line, $text = '') { # Check dependencies - Module::dependencies(isset($type, $function, $line, $text)); + Validator::required(isset($type, $function, $line, $text), __METHOD__); # Get time $sysstamp = time(); diff --git a/php/Modules/Module.php b/php/Modules/Module.php deleted file mode 100644 index 3d8d058..0000000 --- a/php/Modules/Module.php +++ /dev/null @@ -1,15 +0,0 @@ - \ No newline at end of file diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index b862d78..4a069a9 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Photo extends Module { +final class Photo { private $photoIDs = null; @@ -627,7 +627,7 @@ final class Photo extends Module { # (array) $photo # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -790,7 +790,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -856,7 +856,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -886,7 +886,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -914,7 +914,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -959,7 +959,7 @@ final class Photo extends Module { # (int) 2 = Photo public or album public and password correct # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -1006,7 +1006,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -1042,7 +1042,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -1072,7 +1072,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -1104,7 +1104,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -1147,7 +1147,7 @@ final class Photo extends Module { # (boolean) false = Failure # Check dependencies - self::dependencies(isset($this->photoIDs)); + Validator::required(isset($this->photoIDs), __METHOD__); # Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 75f7322..580274e 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Session extends Module { +final class Session { public function init($public = true) { diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index 2088870..d916cce 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -2,7 +2,7 @@ namespace Lychee\Modules; -final class Settings extends Module { +final class Settings { private static $cache = null; @@ -52,9 +52,6 @@ final class Settings extends Module { public static function setLogin($oldPassword = '', $username, $password) { - # Check dependencies - self::dependencies(isset($oldPassword, $username, $password)); - if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) { # Save username @@ -74,7 +71,7 @@ final class Settings extends Module { private static function setUsername($username) { # Check dependencies - self::dependencies(isset($username)); + Validator::required(isset($username), __METHOD__); # Hash username $username = getHashedString($username); @@ -93,7 +90,7 @@ final class Settings extends Module { private static function setPassword($password) { # Check dependencies - self::dependencies(isset($password)); + Validator::required(isset($password), __METHOD__); # Hash password $password = getHashedString($password); @@ -110,9 +107,6 @@ final class Settings extends Module { public static function setDropboxKey($dropboxKey) { - # Check dependencies - self::dependencies(isset($dropboxKey)); - if (strlen($dropboxKey)<1||strlen($dropboxKey)>50) { Log::notice(__METHOD__, __LINE__, 'Dropbox key is either too short or too long'); return false; @@ -128,9 +122,6 @@ final class Settings extends Module { public static function setSortingPhotos($type, $order) { - # Check dependencies - self::dependencies(isset($type, $order)); - $sorting = 'ORDER BY '; # Set row @@ -189,9 +180,6 @@ final class Settings extends Module { public static function setSortingAlbums($type, $order) { - # Check dependencies - self::dependencies(isset($type, $order)); - $sorting = 'ORDER BY '; # Set row diff --git a/php/Modules/Validator.php b/php/Modules/Validator.php new file mode 100644 index 0000000..6aee728 --- /dev/null +++ b/php/Modules/Validator.php @@ -0,0 +1,55 @@ + diff --git a/php/index.php b/php/index.php index b80c660..2e72991 100755 --- a/php/index.php +++ b/php/index.php @@ -10,6 +10,7 @@ namespace Lychee; use Lychee\Modules\Config; use Lychee\Modules\Settings; +use Lychee\Modules\Validator; use Lychee\Access\Installation; use Lychee\Access\Admin; @@ -38,10 +39,10 @@ if (!empty($fn)) { date_default_timezone_set('UTC'); # Validate parameters - if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); - if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); - if (isset($_POST['albumID'])&&preg_match('/^[0-9sfr]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); - if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + if (isset($_POST['albumIDs'])&&Validator::isAlbumIDs($_POST['albumIDs'])===false) exit('Error: Wrong parameter type for albumIDs!'); + if (isset($_POST['photoIDs'])&&Validator::isPhotoIDs($_POST['photoIDs'])===false) exit('Error: Wrong parameter type for photoIDs!'); + if (isset($_POST['albumID'])&&Validator::isAlbumID($_POST['albumID'])==false) exit('Error: Wrong parameter type for albumID!'); + if (isset($_POST['photoID'])&&Validator::isPhotoID($_POST['photoID'])==false) exit('Error: Wrong parameter type for photoID!'); # Check if a configuration exists if (Config::exists()===false) { @@ -51,9 +52,7 @@ if (!empty($fn)) { # Limited access to configure Lychee. Only available when the config.php file is missing. ### - $installation = new Installation(); - $installation->check($fn); - + Installation::init($fn); exit(); } @@ -67,21 +66,21 @@ if (!empty($fn)) { # Full access to Lychee. Only with correct password/session. ### - $admin = new Admin(); - $admin->check($fn); + Admin::init($fn); + exit(); + } else { + + ### + # Guest Access + # Access to view all public folders and photos in Lychee. + ### + + Guest::init($fn); exit(); } - ### - # Guest Access - # Access to view all public folders and photos in Lychee. - ### - - $guest = new Guest(); - $guest->check($fn); - } else { exit('Error: No API function specified!'); From e89203bcb1ae1f35fa364f995d42a26372ffda9a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 21:43:57 +0100 Subject: [PATCH 042/183] // for comments and spaces for alignment --- php/Access/Admin.php | 94 +-- php/Access/Guest.php | 74 +-- php/Access/Installation.php | 6 +- php/Modules/Album.php | 491 +++++++-------- php/Modules/Config.php | 50 +- php/Modules/Database.php | 162 ++--- php/Modules/Import.php | 94 +-- php/Modules/Log.php | 10 +- php/Modules/Photo.php | 806 ++++++++++++------------- php/Modules/Plugins.php | 22 +- php/Modules/Session.php | 46 +- php/Modules/Settings.php | 126 ++-- php/database/update_020700.php | 32 +- php/database/update_030000.php | 29 +- php/database/update_030001.php | 49 +- php/database/update_030003.php | 19 +- php/define.php | 22 +- php/helpers/fastImageCopyResampled.php | 28 +- php/helpers/getGraphHeader.php | 24 +- php/helpers/getHashedString.php | 21 +- php/helpers/hasPermissions.php | 3 +- php/helpers/search.php | 42 +- php/index.php | 59 +- 23 files changed, 1139 insertions(+), 1170 deletions(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index c4576d2..84175d8 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -15,51 +15,51 @@ final class Admin extends Access { switch ($fn) { - # Album functions - case 'Album::getAll': self::getAlbumsAction(); break; - case 'Album::get': self::getAlbumAction(); break; - case 'Album::add': self::addAlbumAction(); break; - case 'Album::setTitle': self::setAlbumTitleAction(); break; - case 'Album::setDescription': self::setAlbumDescriptionAction(); break; - case 'Album::setPublic': self::setAlbumPublicAction(); break; - case 'Album::delete': self::deleteAlbumAction(); break; - case 'Album::merge': self::mergeAlbumsAction(); break; + // Album functions + case 'Album::getAll': self::getAlbumsAction(); break; + case 'Album::get': self::getAlbumAction(); break; + case 'Album::add': self::addAlbumAction(); break; + case 'Album::setTitle': self::setAlbumTitleAction(); break; + case 'Album::setDescription': self::setAlbumDescriptionAction(); break; + case 'Album::setPublic': self::setAlbumPublicAction(); break; + case 'Album::delete': self::deleteAlbumAction(); break; + case 'Album::merge': self::mergeAlbumsAction(); break; - # Photo functions - case 'Photo::get': self::getPhotoAction(); break; - case 'Photo::setTitle': self::setPhotoTitleAction(); break; - case 'Photo::setDescription': self::setPhotoDescriptionAction(); break; - case 'Photo::setStar': self::setPhotoStarAction(); break; - case 'Photo::setPublic': self::setPhotoPublicAction(); break; - case 'Photo::setAlbum': self::setPhotoAlbumAction(); break; - case 'Photo::setTags': self::setPhotoTagsAction(); break; - case 'Photo::duplicate': self::duplicatePhotoAction(); break; - case 'Photo::delete': self::deletePhotoAction(); break; + // Photo functions + case 'Photo::get': self::getPhotoAction(); break; + case 'Photo::setTitle': self::setPhotoTitleAction(); break; + case 'Photo::setDescription': self::setPhotoDescriptionAction(); break; + case 'Photo::setStar': self::setPhotoStarAction(); break; + case 'Photo::setPublic': self::setPhotoPublicAction(); break; + case 'Photo::setAlbum': self::setPhotoAlbumAction(); break; + case 'Photo::setTags': self::setPhotoTagsAction(); break; + case 'Photo::duplicate': self::duplicatePhotoAction(); break; + case 'Photo::delete': self::deletePhotoAction(); break; - # Add functions - case 'Photo::add': self::uploadAction(); break; - case 'Import::url': self::importUrlAction(); break; - case 'Import::server': self::importServerAction(); break; + // Add functions + case 'Photo::add': self::uploadAction(); break; + case 'Import::url': self::importUrlAction(); break; + case 'Import::server': self::importServerAction(); break; - # Search functions - case 'search': self::searchAction(); break; + // Search functions + case 'search': self::searchAction(); break; - # Session functions - case 'Session::init': self::initAction(); break; - case 'Session::login': self::loginAction(); break; - case 'Session::logout': self::logoutAction(); break; + // Session functions + case 'Session::init': self::initAction(); break; + case 'Session::login': self::loginAction(); break; + case 'Session::logout': self::logoutAction(); break; - # Settings functions - case 'Settings::setLogin': self::setLoginAction(); break; - case 'Settings::setSorting': self::setSortingAction(); break; - case 'Settings::setDropboxKey': self::setDropboxKeyAction(); break; + // Settings functions + case 'Settings::setLogin': self::setLoginAction(); break; + case 'Settings::setSorting': self::setSortingAction(); break; + case 'Settings::setDropboxKey': self::setDropboxKeyAction(); break; - # $_GET functions - case 'Album::getArchive': self::getAlbumArchiveAction(); break; - case 'Photo::getArchive': self::getPhotoArchiveAction(); break; + // $_GET functions + case 'Album::getArchive': self::getAlbumArchiveAction(); break; + case 'Photo::getArchive': self::getPhotoArchiveAction(); break; - # Error - default: self::fnNotFound(); break; + // Error + default: self::fnNotFound(); break; } @@ -67,7 +67,7 @@ final class Admin extends Access { } - # Album functions + // Album functions private static function getAlbumsAction() { @@ -138,7 +138,7 @@ final class Admin extends Access { } - # Photo functions + // Photo functions private static function getPhotoAction() { @@ -221,7 +221,7 @@ final class Admin extends Access { } - # Add functions + // Add functions private static function uploadAction() { @@ -250,7 +250,7 @@ final class Admin extends Access { } - # Search functions + // Search functions private static function searchAction() { @@ -260,7 +260,7 @@ final class Admin extends Access { } - # Session functions + // Session functions private static function initAction() { @@ -285,7 +285,7 @@ final class Admin extends Access { } - # Settings functions + // Settings functions private static function setLoginAction() { @@ -302,8 +302,8 @@ final class Admin extends Access { $sA = Settings::setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']); $sP = Settings::setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']); - if ($sA===true&&$sP===true) echo true; - else echo false; + if ($sA===true&&$sP===true) echo true; + else echo false; } @@ -315,7 +315,7 @@ final class Admin extends Access { } - # Get functions + // Get functions private static function getAlbumArchiveAction() { diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 73fca67..e8e2c9c 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -13,25 +13,25 @@ final class Guest extends Access { switch ($fn) { - # Album functions - case 'Album::getAll': self::getAlbumsAction(); break; - case 'Album::get': self::getAlbumAction(); break; - case 'Album::getPublic': self::checkAlbumAccessAction(); break; + // Album functions + case 'Album::getAll': self::getAlbumsAction(); break; + case 'Album::get': self::getAlbumAction(); break; + case 'Album::getPublic': self::checkAlbumAccessAction(); break; - # Photo functions - case 'Photo::get': self::getPhotoAction(); break; + // Photo functions + case 'Photo::get': self::getPhotoAction(); break; - # Session functions - case 'Session::init': self::initAction(); break; - case 'Session::login': self::loginAction(); break; - case 'Session::logout': self::logoutAction(); break; + // Session functions + case 'Session::init': self::initAction(); break; + case 'Session::login': self::loginAction(); break; + case 'Session::logout': self::logoutAction(); break; - # $_GET functions - case 'Album::getArchive': self::getAlbumArchiveAction(); break; - case 'Photo::getArchive': self::getPhotoArchiveAction(); break; + // $_GET functions + case 'Album::getArchive': self::getAlbumArchiveAction(); break; + case 'Photo::getArchive': self::getPhotoArchiveAction(); break; - # Error - default: self::fnNotFound(); break; + // Error + default: self::fnNotFound(); break; } @@ -39,7 +39,7 @@ final class Guest extends Access { } - # Album functions + // Album functions private static function getAlbumsAction() { @@ -56,13 +56,13 @@ final class Guest extends Access { if ($album->getPublic()) { - # Album public - if ($album->checkPassword($_POST['password'])) echo json_encode($album->get()); - else echo 'Warning: Wrong password!'; + // Album public + if ($album->checkPassword($_POST['password'])) echo json_encode($album->get()); + else echo 'Warning: Wrong password!'; } else { - # Album private + // Album private echo 'Warning: Album private!'; } @@ -77,20 +77,20 @@ final class Guest extends Access { if ($album->getPublic()) { - # Album public - if ($album->checkPassword($_POST['password'])) echo true; - else echo false; + // Album public + if ($album->checkPassword($_POST['password'])) echo true; + else echo false; } else { - # Album private + // Album private echo false; } } - # Photo functions + // Photo functions private static function getPhotoAction() { @@ -100,13 +100,13 @@ final class Guest extends Access { $pgP = $photo->getPublic($_POST['password']); - if ($pgP===2) echo json_encode($photo->get($_POST['albumID'])); - else if ($pgP===1) echo 'Warning: Wrong password!'; - else if ($pgP===0) echo 'Warning: Photo private!'; + if ($pgP===2) echo json_encode($photo->get($_POST['albumID'])); + else if ($pgP===1) echo 'Warning: Wrong password!'; + else if ($pgP===0) echo 'Warning: Photo private!'; } - # Session functions + // Session functions private static function initAction() { @@ -131,7 +131,7 @@ final class Guest extends Access { } - # $_GET functions + // $_GET functions private static function getAlbumArchiveAction() { @@ -141,13 +141,13 @@ final class Guest extends Access { if ($album->getPublic()&&$album->getDownloadable()) { - # Album Public - if ($album->checkPassword($_GET['password'])) $album->getArchive(); - else exit('Warning: Wrong password!'); + // Album Public + if ($album->checkPassword($_GET['password'])) $album->getArchive(); + else exit('Warning: Wrong password!'); } else { - # Album Private + // Album Private exit('Warning: Album private or not downloadable!'); } @@ -162,15 +162,15 @@ final class Guest extends Access { $pgP = $photo->getPublic($_GET['password']); - # Photo Download + // Photo Download if ($pgP===2) { - # Photo Public + // Photo Public $photo->getArchive(); } else { - # Photo Private + // Photo Private exit('Warning: Photo private or password incorrect!'); } diff --git a/php/Access/Installation.php b/php/Access/Installation.php index 982642f..946f6bc 100644 --- a/php/Access/Installation.php +++ b/php/Access/Installation.php @@ -11,10 +11,10 @@ final class Installation extends Access { switch ($fn) { - case 'Config::create': self::configCreateAction(); break; + case 'Config::create': self::configCreateAction(); break; - # Error - default: self::initAction(); break; + // Error + default: self::initAction(); break; } diff --git a/php/Modules/Album.php b/php/Modules/Album.php index b5b051a..ebfe111 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -8,8 +8,8 @@ final class Album { public function __construct($albumIDs) { - # Init vars - $this->albumIDs = $albumIDs; + // Init vars + $this->albumIDs = $albumIDs; return true; @@ -17,22 +17,22 @@ final class Album { public function add($title = 'Untitled') { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Parse + // Parse if (strlen($title)>50) $title = substr($title, 0, 50); - # Properties - $public = 0; - $visible = 1; + // Properties + $public = 0; + $visible = 1; - # Database - $sysstamp = time(); - $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); - $result = Database::get()->query($query); + // Database + $sysstamp = time(); + $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -45,31 +45,31 @@ final class Album { public static function prepareData(array $data) { - # This function requires the following album-attributes and turns them - # into a front-end friendly format: id, title, public, sysstamp, password - # Note that some attributes remain unchanged + // This function requires the following album-attributes and turns them + // into a front-end friendly format: id, title, public, sysstamp, password + // Note that some attributes remain unchanged - # Init + // Init $album = null; - # Set unchanged attributes - $album['id'] = $data['id']; - $album['title'] = $data['title']; - $album['public'] = $data['public']; + // Set unchanged attributes + $album['id'] = $data['id']; + $album['title'] = $data['title']; + $album['public'] = $data['public']; - # Additional attributes - # Only part of $album when available - if (isset($data['description'])) $album['description'] = $data['description']; - if (isset($data['visible'])) $album['visible'] = $data['visible']; - if (isset($data['downloadable'])) $album['downloadable'] = $data['downloadable']; + // Additional attributes + // Only part of $album when available + if (isset($data['description'])) $album['description'] = $data['description']; + if (isset($data['visible'])) $album['visible'] = $data['visible']; + if (isset($data['downloadable'])) $album['downloadable'] = $data['downloadable']; - # Parse date + // Parse date $album['sysdate'] = date('F Y', $data['sysstamp']); - # Parse password + // Parse password $album['password'] = ($data['password']=='' ? '0' : '1'); - # Parse thumbs or set default value + // Parse thumbs or set default value $album['thumbs'] = (isset($data['thumbs']) ? explode(',', $data['thumbs']) : array()); return $album; @@ -78,85 +78,90 @@ final class Album { public function get() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get album information + // Get album information switch ($this->albumIDs) { - case 'f': $return['public'] = '0'; - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - break; + case 'f': + $return['public'] = '0'; + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + break; - case 's': $return['public'] = '0'; - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - break; + case 's': + $return['public'] = '0'; + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + break; - case 'r': $return['public'] = '0'; - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - break; + case 'r': + $return['public'] = '0'; + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + break; - case '0': $return['public'] = '0'; - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - break; + case '0': + $return['public'] = '0'; + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + break; - default: $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $return = $albums->fetch_assoc(); - $return = Album::prepareData($return); - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - break; + default: + $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); + $return = $albums->fetch_assoc(); + $return = Album::prepareData($return); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + break; } - # Get photos - $photos = Database::get()->query($query); - $previousPhotoID = ''; + // Get photos + $photos = Database::get()->query($query); + $previousPhotoID = ''; while ($photo = $photos->fetch_assoc()) { - # Turn data from the database into a front-end friendly format + // Turn data from the database into a front-end friendly format $photo = Photo::prepareData($photo); - # Set previous and next photoID for navigation purposes + // Set previous and next photoID for navigation purposes $photo['previousPhoto'] = $previousPhotoID; - $photo['nextPhoto'] = ''; + $photo['nextPhoto'] = ''; - # Set current photoID as nextPhoto of previous photo + // Set current photoID as nextPhoto of previous photo if ($previousPhotoID!=='') $return['content'][$previousPhotoID]['nextPhoto'] = $photo['id']; $previousPhotoID = $photo['id']; - # Add to return + // Add to return $return['content'][$photo['id']] = $photo; } if ($photos->num_rows===0) { - # Album empty + // Album empty $return['content'] = false; } else { - # Enable next and previous for the first and last photo - $lastElement = end($return['content']); - $lastElementId = $lastElement['id']; - $firstElement = reset($return['content']); - $firstElementId = $firstElement['id']; + // Enable next and previous for the first and last photo + $lastElement = end($return['content']); + $lastElementId = $lastElement['id']; + $firstElement = reset($return['content']); + $firstElementId = $firstElement['id']; if ($lastElementId!==$firstElementId) { - $return['content'][$lastElementId]['nextPhoto'] = $firstElementId; - $return['content'][$firstElementId]['previousPhoto'] = $lastElementId; + $return['content'][$lastElementId]['nextPhoto'] = $firstElementId; + $return['content'][$firstElementId]['previousPhoto'] = $lastElementId; } } - $return['id'] = $this->albumIDs; - $return['num'] = $photos->num_rows; + $return['id'] = $this->albumIDs; + $return['num'] = $photos->num_rows; - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -165,45 +170,45 @@ final class Album { public function getAll($public = true) { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Initialize return var + // Initialize return var $return = array( - 'smartalbums' => null, - 'albums' => null, - 'num' => 0 + 'smartalbums' => null, + 'albums' => null, + 'num' => 0 ); - # Get SmartAlbums + // Get SmartAlbums if ($public===false) $return['smartalbums'] = $this->getSmartInfo(); - # Albums query - if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); - else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + // Albums query + if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); - # Execute query + // Execute query $albums = Database::get()->query($query); if (!$albums) { Log::error(__METHOD__, __LINE__, 'Could not get all albums (' . Database::get()->error . ')'); exit('Error: ' . Database::get()->error); } - # For each album + // For each album while ($album = $albums->fetch_assoc()) { - # Turn data from the database into a front-end friendly format + // Turn data from the database into a front-end friendly format $album = Album::prepareData($album); - # Thumbs + // Thumbs if (($public===true&&$album['password']==='0')|| ($public===false)) { - # Execute query - $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::get()->query($query); + // Execute query + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::get()->query($query); - # For each thumb + // For each thumb $k = 0; while ($thumb = $thumbs->fetch_object()) { $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; @@ -212,15 +217,15 @@ final class Album { } - # Add to return + // Add to return $return['albums'][] = $album; } - # Num of albums + // Num of albums $return['num'] = $albums->num_rows; - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -229,25 +234,25 @@ final class Album { private function getSmartInfo() { - # Initialize return var + // Initialize return var $return = array( - 'unsorted' => null, - 'public' => null, - 'starred' => null, - 'recent' => null + 'unsorted' => null, + 'public' => null, + 'starred' => null, + 'recent' => null ); - ### - # Unsorted - ### + /** + * Unsorted + */ - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $unsorted = Database::get()->query($query); - $i = 0; + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $unsorted = Database::get()->query($query); + $i = 0; $return['unsorted'] = array( - 'thumbs' => array(), - 'num' => $unsorted->num_rows + 'thumbs' => array(), + 'num' => $unsorted->num_rows ); while($row = $unsorted->fetch_object()) { @@ -257,17 +262,17 @@ final class Album { } else break; } - ### - # Starred - ### + /** + * Starred + */ - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $starred = Database::get()->query($query); - $i = 0; + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $starred = Database::get()->query($query); + $i = 0; $return['starred'] = array( - 'thumbs' => array(), - 'num' => $starred->num_rows + 'thumbs' => array(), + 'num' => $starred->num_rows ); while($row3 = $starred->fetch_object()) { @@ -277,17 +282,17 @@ final class Album { } else break; } - ### - # Public - ### + /** + * Public + */ - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $public = Database::get()->query($query); - $i = 0; + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $public = Database::get()->query($query); + $i = 0; $return['public'] = array( - 'thumbs' => array(), - 'num' => $public->num_rows + 'thumbs' => array(), + 'num' => $public->num_rows ); while($row2 = $public->fetch_object()) { @@ -297,17 +302,17 @@ final class Album { } else break; } - ### - # Recent - ### + /** + * Recent + */ - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $recent = Database::get()->query($query); - $i = 0; + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $recent = Database::get()->query($query); + $i = 0; $return['recent'] = array( - 'thumbs' => array(), - 'num' => $recent->num_rows + 'thumbs' => array(), + 'num' => $recent->num_rows ); while($row3 = $recent->fetch_object()) { @@ -317,117 +322,117 @@ final class Album { } else break; } - # Return SmartAlbums + // Return SmartAlbums return $return; } public function getArchive() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Illicit chars + // Illicit chars $badChars = array_merge( - array_map('chr', range(0,31)), - array("<", ">", ":", '"', "/", "\\", "|", "?", "*") - ); + array_map('chr', range(0,31)), + array("<", ">", ":", '"', "/", "\\", "|", "?", "*") + ); - # Photos query + // Photos query switch($this->albumIDs) { case 's': - $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS)); - $zipTitle = 'Public'; + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS)); + $zipTitle = 'Public'; break; case 'f': - $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS)); - $zipTitle = 'Starred'; + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS)); + $zipTitle = 'Starred'; break; case 'r': - $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); - $zipTitle = 'Recent'; + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); + $zipTitle = 'Recent'; break; default: - $photos = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $zipTitle = 'Unsorted'; + $photos = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $zipTitle = 'Unsorted'; } - # Get title from database when album is not a SmartAlbum + // Get title from database when album is not a SmartAlbum if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); $album = Database::get()->query($query); - # Error in database query + // Error in database query if (!$album) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # Fetch object + // Fetch object $album = $album->fetch_object(); - # Photo not found + // Photo not found if ($album===null) { Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); return false; } - # Set title + // Set title $zipTitle = $album->title; } - # Escape title + // Escape title $zipTitle = str_replace($badChars, '', $zipTitle); $filename = LYCHEE_DATA . $zipTitle . '.zip'; - # Create zip + // Create zip $zip = new ZipArchive(); if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive'); return false; } - # Execute query + // Execute query $photos = Database::get()->query($photos); - # Check if album empty + // Check if album empty if ($photos->num_rows==0) { Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive without images'); return false; } - # Parse each path + // Parse each path $files = array(); while ($photo = $photos->fetch_object()) { - # Parse url + // Parse url $photo->url = LYCHEE_UPLOADS_BIG . $photo->url; - # Parse title + // Parse title $photo->title = str_replace($badChars, '', $photo->title); if (!isset($photo->title)||$photo->title==='') $photo->title = 'Untitled'; - # Check if readable + // Check if readable if (!@is_readable($photo->url)) continue; - # Get extension of image + // Get extension of image $extension = getExtension($photo->url); - # Set title for photo + // Set title for photo $zipFileName = $zipTitle . '/' . $photo->title . $extension; - # Check for duplicates + // Check for duplicates if (!empty($files)) { $i = 1; while (in_array($zipFileName, $files)) { - # Set new title for photo + // Set new title for photo $zipFileName = $zipTitle . '/' . $photo->title . '-' . $i . $extension; $i++; @@ -435,27 +440,27 @@ final class Album { } } - # Add to array + // Add to array $files[] = $zipFileName; - # Add photo to zip + // Add photo to zip $zip->addFile($photo->url, $zipFileName); } - # Finish zip + // Finish zip $zip->close(); - # Send zip + // Send zip header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); header("Content-Length: " . filesize($filename)); readfile($filename); - # Delete zip + // Delete zip unlink($filename); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -464,17 +469,17 @@ final class Album { public function setTitle($title = 'Untitled') { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Execute query - $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); + // Execute query + $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -487,17 +492,17 @@ final class Album { public function setDescription($description = '') { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Execute query - $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); - $result = Database::get()->query($query); + // Execute query + $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -510,20 +515,20 @@ final class Album { public function getPublic() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f') return false; - # Execute query - $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + // Execute query + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); + $album = $albums->fetch_object(); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->public==1) return true; @@ -533,20 +538,20 @@ final class Album { public function getDownloadable() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f'||$this->albumIDs==='r') return false; - # Execute query - $query = Database::prepare(Database::get(), "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + // Execute query + $query = Database::prepare(Database::get(), "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); + $album = $albums->fetch_object(); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->downloadable==1) return true; @@ -556,39 +561,39 @@ final class Album { public function setPublic($public, $password, $visible, $downloadable) { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Convert values - $public = ($public==='1' ? 1 : 0); - $visible = ($visible==='1' ? 1 : 0); - $downloadable = ($downloadable==='1' ? 1 : 0); + // Convert values + $public = ($public==='1' ? 1 : 0); + $visible = ($visible==='1' ? 1 : 0); + $downloadable = ($downloadable==='1' ? 1 : 0); - # Set public - $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); - $result = Database::get()->query($query); + // Set public + $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # Reset permissions for photos + // Reset permissions for photos if ($public===1) { - $query = Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $result = Database::get()->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - # Set password + // Set password if (isset($password)&&strlen($password)>0) return $this->setPassword($password); return true; @@ -597,33 +602,33 @@ final class Album { private function setPassword($password) { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); if (strlen($password)>0) { - # Get hashed password + // Get hashed password $password = getHashedString($password); - # Set hashed password - # Do not prepare $password because it is hashed and save - # Preparing (escaping) the password would destroy the hash - $query = Database::prepare(Database::get(), "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + // Set hashed password + // Do not prepare $password because it is hashed and save + // Preparing (escaping) the password would destroy the hash + $query = Database::prepare(Database::get(), "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); } else { - # Unset password - $query = Database::prepare(Database::get(), "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + // Unset password + $query = Database::prepare(Database::get(), "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); } - # Execute query - $result = Database::get()->query($query); + // Execute query + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -636,18 +641,18 @@ final class Album { public function checkPassword($password) { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Execute query - $query = Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + // Execute query + $query = Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::get()->query($query); + $album = $albums->fetch_object(); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($album->password=='') return true; @@ -658,35 +663,35 @@ final class Album { public function merge() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Convert to array + // Convert to array $albumIDs = explode(',', $this->albumIDs); - # Get first albumID + // Get first albumID $albumID = array_splice($albumIDs, 0, 1); $albumID = $albumID[0]; - $query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); - $result = Database::get()->query($query); + $query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); + $result = Database::get()->query($query); if (!$result) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # $albumIDs contains all IDs without the first albumID - # Convert to string + // $albumIDs contains all IDs without the first albumID + // Convert to string $filteredIDs = implode(',', $albumIDs); - $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs)); - $result = Database::get()->query($query); + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -699,20 +704,20 @@ final class Album { public function delete() { - # Check dependencies + // Check dependencies Validator::required(isset($this->albumIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Init vars + // Init vars $error = false; - # Execute query - $query = Database::prepare(Database::get(), "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); + // Execute query + $query = Database::prepare(Database::get(), "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); $photos = Database::get()->query($query); - # For each album delete photo + // For each album delete photo while ($row = $photos->fetch_object()) { $photo = new Photo($row->id); @@ -720,11 +725,11 @@ final class Album { } - # Delete albums - $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $result = Database::get()->query($query); + // Delete albums + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error) return false; diff --git a/php/Modules/Config.php b/php/Modules/Config.php index 0c03786..060b1df 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -6,43 +6,37 @@ final class Config { public static function create($host, $user, $password, $name = 'lychee', $prefix = '') { - # Open a new connection to the MySQL server + // Open a new connection to the MySQL server $connection = Database::connect($host, $user, $password); - # Check if the connection was successful + // Check if the connection was successful if ($connection===false) return 'Warning: Connection failed!'; - # Check if user can create the database before saving the configuration + // Check if user can create the database before saving the configuration if (!Database::createDatabase($connection, $name)) return 'Warning: Creation failed!'; - # Escape data - $host = mysqli_real_escape_string($connection, $host); - $user = mysqli_real_escape_string($connection, $user); - $password = mysqli_real_escape_string($connection, $password); - $name = mysqli_real_escape_string($connection, $name); - $prefix = mysqli_real_escape_string($connection, $prefix); + // Escape data + $host = mysqli_real_escape_string($connection, $host); + $user = mysqli_real_escape_string($connection, $user); + $password = mysqli_real_escape_string($connection, $password); + $name = mysqli_real_escape_string($connection, $name); + $prefix = mysqli_real_escape_string($connection, $prefix); - # Save config.php + // Save config.php $config = ""; - # Save file + // Save file if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!'; return true; @@ -60,11 +54,11 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); require(LYCHEE_CONFIG_FILE); return(array( - 'host' => $dbHost, - 'user' => $dbUser, - 'password' => $dbPassword, - 'name' => $dbName, - 'prefix' => $dbTablePrefix + 'host' => $dbHost, + 'user' => $dbUser, + 'password' => $dbPassword, + 'name' => $dbName, + 'prefix' => $dbTablePrefix )); } diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 770d62b..bac8126 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -10,10 +10,10 @@ final class Database { private static $instance = null; private static $versions = array( - '020700', #2.7.0 - '030000', #3.0.0 - '030001', #3.0.1 - '030003' #3.0.3 + '020700', // 2.7.0 + '030000', // 3.0.0 + '030001', // 3.0.1 + '030003' // 3.0.3 ); public static function get() { @@ -38,27 +38,27 @@ final class Database { private function __construct($host, $user, $password, $name = 'lychee', $dbTablePrefix) { - # Check dependencies + // Check dependencies Validator::required(isset($host, $user, $password, $name), __METHOD__); - # Define the table prefix + // Define the table prefix defineTablePrefix($dbTablePrefix); - # Open a new connection to the MySQL server + // Open a new connection to the MySQL server $connection = self::connect($host, $user, $password); - # Check if the connection was successful + // Check if the connection was successful if ($connection===false) exit('Error: ' . $connection->connect_error); if (!self::setCharset($connection)) exit('Error: Could not set database charset!'); - # Create database + // Create database if (!self::createDatabase($connection, $name)) exit('Error: Could not create database!'); - # Create tables + // Create tables if (!self::createTables($connection)) exit('Error: Could not create tables!'); - # Update database + // Update database if (!self::update($connection, $name)) exit('Error: Could not update database and tables!'); $this->connection = $connection; @@ -67,10 +67,10 @@ final class Database { public static function connect($host = 'localhost', $user, $password) { - # Open a new connection to the MySQL server + // Open a new connection to the MySQL server $connection = new Mysqli($host, $user, $password); - # Check if the connection was successful + // Check if the connection was successful if ($connection->connect_errno) return false; return $connection; @@ -79,14 +79,14 @@ final class Database { private static function setCharset($connection) { - # Check dependencies + // Check dependencies Validator::required(isset($connection), __METHOD__); - # Avoid sql injection on older MySQL versions by using GBK + // Avoid sql injection on older MySQL versions by using GBK if ($connection->server_version<50500) @$connection->set_charset('GBK'); else @$connection->set_charset('utf8'); - # Set unicode + // Set unicode $connection->query('SET NAMES utf8;'); return true; @@ -95,14 +95,14 @@ final class Database { public static function createDatabase($connection, $name = 'lychee') { - # Check dependencies + // Check dependencies Validator::required(isset($connection), __METHOD__); - # Check if database exists + // Check if database exists if ($connection->select_db($name)) return true; - # Create database - $query = self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); + // Create database + $query = self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); $result = $connection->query($query); if (!$connection->select_db($name)) return false; @@ -112,68 +112,68 @@ final class Database { private static function createTables($connection) { - # Check dependencies + // Check dependencies Validator::required(isset($connection), __METHOD__); - # Check if tables exist + // Check if tables exist $query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); if ($connection->query($query)) return true; - # Create log + // Create log $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); if (!$connection->query($exist)) { - # Read file - $file = __DIR__ . '/../database/log_table.sql'; - $query = @file_get_contents($file); + // Read file + $file = __DIR__ . '/../database/log_table.sql'; + $query = @file_get_contents($file); if (!isset($query)||$query===false) return false; - # Create table + // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG)); if (!$connection->query($query)) return false; } - # Create settings + // Create settings $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); if (!$connection->query($exist)) { - # Read file - $file = __DIR__ . '/../database/settings_table.sql'; - $query = @file_get_contents($file); + // Read file + $file = __DIR__ . '/../database/settings_table.sql'; + $query = @file_get_contents($file); if (!isset($query)||$query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_settings'); return false; } - # Create table + // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); if (!$connection->query($query)) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } - # Read file - $file = __DIR__ . '/../database/settings_content.sql'; - $query = @file_get_contents($file); + // Read file + $file = __DIR__ . '/../database/settings_content.sql'; + $query = @file_get_contents($file); if (!isset($query)||$query===false) { Log::error(__METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); return false; } - # Add content + // Add content $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); if (!$connection->query($query)) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } - # Generate identifier - $identifier = md5(microtime(true)); - $query = self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); + // Generate identifier + $identifier = md5(microtime(true)); + $query = self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); if (!$connection->query($query)) { Log::error(__METHOD__, __LINE__, $connection->error); return false; @@ -181,20 +181,20 @@ final class Database { } - # Create albums + // Create albums $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); if (!$connection->query($exist)) { - # Read file - $file = __DIR__ . '/../database/albums_table.sql'; - $query = @file_get_contents($file); + // Read file + $file = __DIR__ . '/../database/albums_table.sql'; + $query = @file_get_contents($file); if (!isset($query)||$query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_albums'); return false; } - # Create table + // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS)); if (!$connection->query($query)) { Log::error(__METHOD__, __LINE__, $connection->error); @@ -203,20 +203,20 @@ final class Database { } - # Create photos + // Create photos $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); if (!$connection->query($exist)) { - # Read file - $file = __DIR__ . '/../database/photos_table.sql'; - $query = @file_get_contents($file); + // Read file + $file = __DIR__ . '/../database/photos_table.sql'; + $query = @file_get_contents($file); if (!isset($query)||$query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_photos'); return false; } - # Create table + // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS)); if (!$connection->query($query)) { Log::error(__METHOD__, __LINE__, $connection->error); @@ -231,21 +231,21 @@ final class Database { private static function update($connection, $dbName) { - # Check dependencies + // Check dependencies Validator::required(isset($connection, $dbName), __METHOD__); - # Get current version - $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); - $results = $connection->query($query); - $current = $results->fetch_object()->value; + // Get current version + $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); + $results = $connection->query($query); + $current = $results->fetch_object()->value; - # For each update + // For each update foreach (self::$versions as $version) { - # Only update when newer version available + // Only update when newer version available if ($version<=$current) continue; - # Load update + // Load update include(__DIR__ . '/../database/update_' . $version . '.php'); } @@ -256,10 +256,10 @@ final class Database { public static function setVersion($connection, $version) { - # Check dependencies + // Check dependencies Validator::required(isset($connection), __METHOD__); - $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); + $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); $result = $connection->query($query); if (!$result) { Log::error(__METHOD__, __LINE__, 'Could not update database (' . $connection->error . ')'); @@ -270,62 +270,62 @@ final class Database { public static function prepare($connection, $query, array $data) { - # Check dependencies + // Check dependencies Validator::required(isset($connection, $query), __METHOD__); - # Count the number of placeholders and compare it with the number of arguments - # If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement - # This avoids problems with placeholders in user-input - # $skip = Number of placeholders which need to be skipped - $skip = 0; - $temp = ''; - $num = array( - 'placeholder' => substr_count($query, '?'), - 'data' => count($data) + // Count the number of placeholders and compare it with the number of arguments + // If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement + // This avoids problems with placeholders in user-input + // $skip = Number of placeholders which need to be skipped + $skip = 0; + $temp = ''; + $num = array( + 'placeholder' => substr_count($query, '?'), + 'data' => count($data) ); if (($num['data']-$num['placeholder'])<0) Log::notice(__METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); foreach ($data as $value) { - # Escape + // Escape $value = mysqli_real_escape_string($connection, $value); - # Recalculate number of placeholders + // Recalculate number of placeholders $num['placeholder'] = substr_count($query, '?'); - # Calculate number of skips + // Calculate number of skips if ($num['placeholder']>$num['data']) $skip = $num['placeholder'] - $num['data']; if ($skip>0) { - # Need to skip $skip placeholders, because the user input contained placeholders - # Calculate a substring which does not contain the user placeholders - # 1 or -1 is the length of the placeholder (placeholder = ?) + // Need to skip $skip placeholders, because the user input contained placeholders + // Calculate a substring which does not contain the user placeholders + // 1 or -1 is the length of the placeholder (placeholder = ?) $pos = -1; for ($i=$skip; $i>0; $i--) $pos = strpos($query, '?', $pos + 1); $pos++; - $temp = substr($query, 0, $pos); # First part of $query - $query = substr($query, $pos); # Last part of $query + $temp = substr($query, 0, $pos); // First part of $query + $query = substr($query, $pos); // Last part of $query } - # Replace + // Replace $query = preg_replace('/\?/', $value, $query, 1); if ($skip>0) { - # Reassemble the parts of $query + // Reassemble the parts of $query $query = $temp . $query; } - # Reset skip + // Reset skip $skip = 0; - # Decrease number of data elements + // Decrease number of data elements $num['data']--; } diff --git a/php/Modules/Import.php b/php/Modules/Import.php index dcc3041..886e83b 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -6,20 +6,20 @@ final class Import { private function photo($path, $albumID = 0, $description = '', $tags = '') { - # No need to validate photo type and extension in this function. - # $photo->add will take care of it. + // No need to validate photo type and extension in this function. + // $photo->add will take care of it. - $info = getimagesize($path); - $size = filesize($path); - $photo = new Photo(null); + $info = getimagesize($path); + $size = filesize($path); + $photo = new Photo(null); - $nameFile = array(array()); - $nameFile[0]['name'] = $path; - $nameFile[0]['type'] = $info['mime']; - $nameFile[0]['tmp_name'] = $path; - $nameFile[0]['error'] = 0; - $nameFile[0]['size'] = $size; - $nameFile[0]['error'] = UPLOAD_ERR_OK; + $nameFile = array(array()); + $nameFile[0]['name'] = $path; + $nameFile[0]['type'] = $info['mime']; + $nameFile[0]['tmp_name'] = $path; + $nameFile[0]['error'] = 0; + $nameFile[0]['size'] = $size; + $nameFile[0]['error'] = UPLOAD_ERR_OK; if (!$photo->add($nameFile, $albumID, $description, $tags, true)) return false; return true; @@ -28,21 +28,21 @@ final class Import { public function url($urls, $albumID = 0) { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); $error = false; - # Parse URLs + // Parse URLs $urls = str_replace(' ', '%20', $urls); $urls = explode(',', $urls); foreach ($urls as &$url) { - # Validate photo type and extension even when $this->photo (=> $photo->add) will do the same. - # This prevents us from downloading invalid photos. + // Validate photo type and extension even when $this->photo (=> $photo->add) will do the same. + // This prevents us from downloading invalid photos. - # Verify extension + // Verify extension $extension = getExtension($url); if (!in_array(strtolower($extension), Photo::$validExtensions, true)) { $error = true; @@ -50,7 +50,7 @@ final class Import { continue; } - # Verify image + // Verify image $type = @exif_imagetype($url); if (!in_array($type, Photo::$validTypes, true)) { $error = true; @@ -58,9 +58,9 @@ final class Import { continue; } - $pathinfo = pathinfo($url); - $filename = $pathinfo['filename'] . '.' . $pathinfo['extension']; - $tmp_name = LYCHEE_DATA . $filename; + $pathinfo = pathinfo($url); + $filename = $pathinfo['filename'] . '.' . $pathinfo['extension']; + $tmp_name = LYCHEE_DATA . $filename; if (@copy($url, $tmp_name)===false) { $error = true; @@ -68,7 +68,7 @@ final class Import { continue; } - # Import photo + // Import photo if (!$this->photo($tmp_name, $albumID)) { $error = true; Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $tmp_name); @@ -77,7 +77,7 @@ final class Import { } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===false) return true; @@ -87,16 +87,16 @@ final class Import { public function server($path, $albumID = 0) { - # Parse path - if (!isset($path)) $path = LYCHEE_UPLOADS_IMPORT; - if (substr($path, -1)==='/') $path = substr($path, 0, -1); + // Parse path + if (!isset($path)) $path = LYCHEE_UPLOADS_IMPORT; + if (substr($path, -1)==='/') $path = substr($path, 0, -1); if (is_dir($path)===false) { Log::error(__METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); return 'Error: Given path is not a directory!'; } - # Skip folders of Lychee + // Skip folders of Lychee if ($path===LYCHEE_UPLOADS_BIG||($path . '/')===LYCHEE_UPLOADS_BIG|| $path===LYCHEE_UPLOADS_MEDIUM||($path . '/')===LYCHEE_UPLOADS_MEDIUM|| $path===LYCHEE_UPLOADS_THUMB||($path . '/')===LYCHEE_UPLOADS_THUMB) { @@ -104,22 +104,22 @@ final class Import { return 'Error: Given path is a reserved path of Lychee!'; } - $error = false; - $contains['photos'] = false; - $contains['albums'] = false; + $error = false; + $contains['photos'] = false; + $contains['albums'] = false; - # Call plugins - # Note that updated albumId and path explicitly passed, rather - # than using func_get_args() which will only return original ones + // Call plugins + // Note that updated albumId and path explicitly passed, rather + // than using func_get_args() which will only return original ones Plugins::get()->activate(__METHOD__, 0, array($albumID, $path)); - # Get all files + // Get all files $files = glob($path . '/*'); foreach ($files as $file) { - # It is possible to move a file because of directory permissions but - # the file may still be unreadable by the user + // It is possible to move a file because of directory permissions but + // the file may still be unreadable by the user if (!is_readable($file)) { $error = true; Log::error(__METHOD__, __LINE__, 'Could not read file or directory: ' . $file); @@ -128,7 +128,7 @@ final class Import { if (@exif_imagetype($file)!==false) { - # Photo + // Photo $contains['photos'] = true; @@ -140,11 +140,11 @@ final class Import { } else if (is_dir($file)) { - # Folder + // Folder - $album = new Album(null); - $newAlbumID = $album->add('[Import] ' . basename($file)); - $contains['albums'] = true; + $album = new Album(null); + $newAlbumID = $album->add('[Import] ' . basename($file)); + $contains['albums'] = true; if ($newAlbumID===false) { $error = true; @@ -164,14 +164,14 @@ final class Import { } - # Call plugins - # Note that updated albumId and path explicitly passed, rather - # than using func_get_args() which will only return original ones + // Call plugins + // Note that updated albumId and path explicitly passed, rather + // than using func_get_args() which will only return original ones Plugins::get()->activate(__METHOD__, 1, array($albumID, $path)); - # The following returns will be caught in the front-end - if ($contains['photos']===false&&$contains['albums']===false) return 'Warning: Folder empty or no readable files to process!'; - if ($contains['photos']===false&&$contains['albums']===true) return 'Notice: Import only contained albums!'; + // The following returns will be caught in the front-end + if ($contains['photos']===false&&$contains['albums']===false) return 'Warning: Folder empty or no readable files to process!'; + if ($contains['photos']===false&&$contains['albums']===true) return 'Notice: Import only contained albums!'; if ($error===true) return false; return true; diff --git a/php/Modules/Log.php b/php/Modules/Log.php index 44e9696..de49453 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -24,15 +24,15 @@ final class Log { private static function text($type, $function, $line, $text = '') { - # Check dependencies + // Check dependencies Validator::required(isset($type, $function, $line, $text), __METHOD__); - # Get time + // Get time $sysstamp = time(); - # Save in database - $query = Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); - $result = Database::get()->query($query); + // Save in database + $query = Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); + $result = Database::get()->query($query); if (!$result) return false; return true; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 4a069a9..039fe79 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -21,8 +21,8 @@ final class Photo { public function __construct($photoIDs) { - # Init vars - $this->photoIDs = $photoIDs; + // Init vars + $this->photoIDs = $photoIDs; return true; @@ -30,10 +30,10 @@ final class Photo { public function add(array $files, $albumID = 0, $description = '', $tags = '', $returnOnError = false) { - # Use $returnOnError if you want to handle errors by your own - # e.g. when calling this functions inside an if-condition + // Use $returnOnError if you want to handle errors by your own + // e.g. when calling this functions inside an if-condition - # Check permissions + // Check permissions if (hasPermissions(LYCHEE_UPLOADS)===false|| hasPermissions(LYCHEE_UPLOADS_BIG)===false|| hasPermissions(LYCHEE_UPLOADS_THUMB)===false) { @@ -41,77 +41,77 @@ final class Photo { exit('Error: An upload-folder is missing or not readable and writable!'); } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); switch($albumID) { case 's': - # s for public (share) - $public = 1; - $star = 0; - $albumID = 0; + // s for public (share) + $public = 1; + $star = 0; + $albumID = 0; break; case 'f': - # f for starred (fav) - $star = 1; - $public = 0; - $albumID = 0; + // f for starred (fav) + $star = 1; + $public = 0; + $albumID = 0; break; case 'r': - # r for recent - $public = 0; - $star = 0; - $albumID = 0; + // r for recent + $public = 0; + $star = 0; + $albumID = 0; break; default: - $star = 0; - $public = 0; + $star = 0; + $public = 0; break; } foreach ($files as $file) { - # Check if file exceeds the upload_max_filesize directive + // Check if file exceeds the upload_max_filesize directive if ($file['error']===UPLOAD_ERR_INI_SIZE) { Log::error(__METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); if ($returnOnError===true) return false; exit('Error: The uploaded file exceeds the upload_max_filesize directive in php.ini!'); } - # Check if file was only partially uploaded + // Check if file was only partially uploaded if ($file['error']===UPLOAD_ERR_PARTIAL) { Log::error(__METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); if ($returnOnError===true) return false; exit('Error: The uploaded file was only partially uploaded!'); } - # Check if writing file to disk failed + // Check if writing file to disk failed if ($file['error']===UPLOAD_ERR_CANT_WRITE) { Log::error(__METHOD__, __LINE__, 'Failed to write photo to disk'); if ($returnOnError===true) return false; exit('Error: Failed to write photo to disk!'); } - # Check if a extension stopped the file upload + // Check if a extension stopped the file upload if ($file['error']===UPLOAD_ERR_EXTENSION) { Log::error(__METHOD__, __LINE__, 'A PHP extension stopped the file upload'); if ($returnOnError===true) return false; exit('Error: A PHP extension stopped the file upload!'); } - # Check if the upload was successful + // Check if the upload was successful if ($file['error']!==UPLOAD_ERR_OK) { Log::error(__METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); if ($returnOnError===true) return false; exit('Error: Upload failed!'); } - # Verify extension + // Verify extension $extension = getExtension($file['name']); if (!in_array(strtolower($extension), self::$validExtensions, true)) { Log::error(__METHOD__, __LINE__, 'Photo format not supported'); @@ -119,7 +119,7 @@ final class Photo { exit('Error: Photo format not supported!'); } - # Verify image + // Verify image $type = @exif_imagetype($file['tmp_name']); if (!in_array($type, self::$validTypes, true)) { Log::error(__METHOD__, __LINE__, 'Photo type not supported'); @@ -127,16 +127,16 @@ final class Photo { exit('Error: Photo type not supported!'); } - # Generate id + // Generate id $id = str_replace('.', '', microtime(true)); while(strlen($id)<14) $id .= 0; - # Set paths - $tmp_name = $file['tmp_name']; - $photo_name = md5($id) . $extension; - $path = LYCHEE_UPLOADS_BIG . $photo_name; + // Set paths + $tmp_name = $file['tmp_name']; + $photo_name = md5($id) . $extension; + $path = LYCHEE_UPLOADS_BIG . $photo_name; - # Calculate checksum + // Calculate checksum $checksum = sha1_file($tmp_name); if ($checksum===false) { Log::error(__METHOD__, __LINE__, 'Could not calculate checksum for photo'); @@ -144,29 +144,29 @@ final class Photo { exit('Error: Could not calculate checksum for photo!'); } - # Check if image exists based on checksum + // Check if image exists based on checksum if ($checksum===false) { - $checksum = ''; - $exists = false; + $checksum = ''; + $exists = false; } else { $exists = $this->exists($checksum); if ($exists!==false) { - $photo_name = $exists['photo_name']; - $path = $exists['path']; - $path_thumb = $exists['path_thumb']; - $medium = ($exists['medium']==='1' ? 1 : 0); - $exists = true; + $photo_name = $exists['photo_name']; + $path = $exists['path']; + $path_thumb = $exists['path_thumb']; + $medium = ($exists['medium']==='1' ? 1 : 0); + $exists = true; } } if ($exists===false) { - # Import if not uploaded via web + // Import if not uploaded via web if (!is_uploaded_file($tmp_name)) { if (!@copy($tmp_name, $path)) { Log::error(__METHOD__, __LINE__, 'Could not copy photo to uploads'); @@ -183,8 +183,8 @@ final class Photo { } else { - # Photo already exists - # Check if the user wants to skip duplicates + // Photo already exists + // Check if the user wants to skip duplicates if (Settings::get()['skipDuplicates']==='1') { Log::notice(__METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); if ($returnOnError===true) return false; @@ -193,46 +193,46 @@ final class Photo { } - # Read infos + // Read infos $info = $this->getInfo($path); - # Use title of file if IPTC title missing + // Use title of file if IPTC title missing if ($info['title']==='') $info['title'] = substr(basename($file['name'], $extension), 0, 30); - # Use description parameter if set + // Use description parameter if set if ($description==='') $description = $info['description']; if ($exists===false) { - # Set orientation based on EXIF data + // Set orientation based on EXIF data if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') { $adjustFile = $this->adjustFile($path, $info); if ($adjustFile!==false) $info = $adjustFile; else Log::notice(__METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); } - # Set original date + // Set original date if ($info['takestamp']!==''&&$info['takestamp']!==0) @touch($path, $info['takestamp']); - # Create Thumb + // Create Thumb if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { Log::error(__METHOD__, __LINE__, 'Could not create thumbnail for photo'); if ($returnOnError===true) return false; exit('Error: Could not create thumbnail for photo!'); } - # Create Medium + // Create Medium if ($this->createMedium($path, $photo_name, $info['width'], $info['height'])) $medium = 1; else $medium = 0; - # Set thumb url + // Set thumb url $path_thumb = md5($id) . '.jpeg'; } - # Save to DB - $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); - $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); + // Save to DB + $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); $result = Database::get()->query($query); if (!$result) { @@ -243,7 +243,7 @@ final class Photo { } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -252,11 +252,11 @@ final class Photo { private function exists($checksum, $photoID = null) { - # Exclude $photoID from select when $photoID is set + // Exclude $photoID from select when $photoID is set if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); - $result = Database::get()->query($query); + $result = Database::get()->query($query); if (!$result) { Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum'); @@ -268,10 +268,10 @@ final class Photo { $result = $result->fetch_object(); $return = array( - 'photo_name' => $result->url, - 'path' => LYCHEE_UPLOADS_BIG . $result->url, - 'path_thumb' => $result->thumbUrl, - 'medium' => $result->medium + 'photo_name' => $result->url, + 'path' => LYCHEE_UPLOADS_BIG . $result->url, + 'path_thumb' => $result->thumbUrl, + 'medium' => $result->medium ); return $return; @@ -284,36 +284,36 @@ final class Photo { private function createThumb($url, $filename, $type, $width, $height) { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Size of the thumbnail - $newWidth = 200; - $newHeight = 200; + // Size of the thumbnail + $newWidth = 200; + $newHeight = 200; - $photoName = explode('.', $filename); - $newUrl = LYCHEE_UPLOADS_THUMB . $photoName[0] . '.jpeg'; - $newUrl2x = LYCHEE_UPLOADS_THUMB . $photoName[0] . '@2x.jpeg'; + $photoName = explode('.', $filename); + $newUrl = LYCHEE_UPLOADS_THUMB . $photoName[0] . '.jpeg'; + $newUrl2x = LYCHEE_UPLOADS_THUMB . $photoName[0] . '@2x.jpeg'; - # Create thumbnails with Imagick + // Create thumbnails with Imagick if(extension_loaded('imagick')&&Settings::get()['imagick']==='1') { - # Read image + // Read image $thumb = new Imagick(); $thumb->readImage($url); $thumb->setImageCompressionQuality(Settings::get()['thumbQuality']); $thumb->setImageFormat('jpeg'); - # Copy image for 2nd thumb version + // Copy image for 2nd thumb version $thumb2x = clone $thumb; - # Create 1st version + // Create 1st version $thumb->cropThumbnailImage($newWidth, $newHeight); $thumb->writeImage($newUrl); $thumb->clear(); $thumb->destroy(); - # Create 2nd version + // Create 2nd version $thumb2x->cropThumbnailImage($newWidth*2, $newHeight*2); $thumb2x->writeImage($newUrl2x); $thumb2x->clear(); @@ -321,47 +321,47 @@ final class Photo { } else { - # Create image - $thumb = imagecreatetruecolor($newWidth, $newHeight); - $thumb2x = imagecreatetruecolor($newWidth*2, $newHeight*2); + // Create image + $thumb = imagecreatetruecolor($newWidth, $newHeight); + $thumb2x = imagecreatetruecolor($newWidth*2, $newHeight*2); - # Set position + // Set position if ($width<$height) { - $newSize = $width; - $startWidth = 0; - $startHeight = $height/2 - $width/2; + $newSize = $width; + $startWidth = 0; + $startHeight = $height/2 - $width/2; } else { - $newSize = $height; - $startWidth = $width/2 - $height/2; - $startHeight = 0; + $newSize = $height; + $startWidth = $width/2 - $height/2; + $startHeight = 0; } - # Create new image + // Create new image switch($type) { - case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; - case 'image/png': $sourceImg = imagecreatefrompng($url); break; - case 'image/gif': $sourceImg = imagecreatefromgif($url); break; - default: Log::error(__METHOD__, __LINE__, 'Type of photo is not supported'); - return false; - break; + case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; + case 'image/png': $sourceImg = imagecreatefrompng($url); break; + case 'image/gif': $sourceImg = imagecreatefromgif($url); break; + default: Log::error(__METHOD__, __LINE__, 'Type of photo is not supported'); + return false; + break; } - # Create thumb + // Create thumb fastImageCopyResampled($thumb, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth, $newHeight, $newSize, $newSize); imagejpeg($thumb, $newUrl, Settings::get()['thumbQuality']); imagedestroy($thumb); - # Create retina thumb + // Create retina thumb fastImageCopyResampled($thumb2x, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth*2, $newHeight*2, $newSize, $newSize); imagejpeg($thumb2x, $newUrl2x, Settings::get()['thumbQuality']); imagedestroy($thumb2x); - # Free memory + // Free memory imagedestroy($sourceImg); } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -370,40 +370,40 @@ final class Photo { private function createMedium($url, $filename, $width, $height) { - # Function creates a smaller version of a photo when its size is bigger than a preset size - # Excepts the following: - # (string) $url = Path to the photo-file - # (string) $filename = Name of the photo-file - # (int) $width = Width of the photo - # (int) $height = Height of the photo - # Returns the following - # (boolean) true = Success - # (boolean) false = Failure + // Function creates a smaller version of a photo when its size is bigger than a preset size + // Excepts the following: + // (string) $url = Path to the photo-file + // (string) $filename = Name of the photo-file + // (int) $width = Width of the photo + // (int) $height = Height of the photo + // Returns the following + // (boolean) true = Success + // (boolean) false = Failure - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Set to true when creation of medium-photo failed + // Set to true when creation of medium-photo failed $error = false; - # Size of the medium-photo - # When changing these values, - # also change the size detection in the front-end - $newWidth = 1920; - $newHeight = 1080; + // Size of the medium-photo + // When changing these values, + // also change the size detection in the front-end + $newWidth = 1920; + $newHeight = 1080; - # Check permissions + // Check permissions if (hasPermissions(LYCHEE_UPLOADS_MEDIUM)===false) { - # Permissions are missing + // Permissions are missing Log::notice(__METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.'); $error = true; } - # Is photo big enough? - # Is medium activated? - # Is Imagick installed and activated? + // Is photo big enough? + // Is medium activated? + // Is Imagick installed and activated? if (($error===false)&& ($width>$newWidth||$height>$newHeight)&& (Settings::get()['medium']==='1')&& @@ -411,14 +411,14 @@ final class Photo { $newUrl = LYCHEE_UPLOADS_MEDIUM . $filename; - # Read image + // Read image $medium = new Imagick(); $medium->readImage($url); - # Adjust image + // Adjust image $medium->scaleImage($newWidth, $newHeight, true); - # Save image + // Save image try { $medium->writeImage($newUrl); } catch (ImagickException $err) { Log::notice(__METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); @@ -430,14 +430,14 @@ final class Photo { } else { - # Photo too small or - # Medium is deactivated or - # Imagick not installed + // Photo too small or + // Medium is deactivated or + // Imagick not installed $error = true; } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===true) return false; @@ -447,15 +447,15 @@ final class Photo { public function adjustFile($path, array $info) { - # Function rotates and flips a photo based on its EXIF orientation - # Excepts the following: - # (string) $path = Path to the photo-file - # (array) $info = ['orientation', 'width', 'height'] - # Returns the following - # (array) $info = ['orientation', 'width', 'height'] = Success - # (boolean) false = Failure + // Function rotates and flips a photo based on its EXIF orientation + // Excepts the following: + // (string) $path = Path to the photo-file + // (array) $info = ['orientation', 'width', 'height'] + // Returns the following + // (array) $info = ['orientation', 'width', 'height'] = Success + // (boolean) false = Failure - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); $swapSize = false; @@ -469,13 +469,13 @@ final class Photo { break; case 6: - $rotateImage = 90; - $swapSize = true; + $rotateImage = 90; + $swapSize = true; break; case 8: - $rotateImage = 270; - $swapSize = true; + $rotateImage = 270; + $swapSize = true; break; default: @@ -496,52 +496,52 @@ final class Photo { } else { - $newWidth = $info['width']; - $newHeight = $info['height']; - $sourceImg = imagecreatefromjpeg($path); + $newWidth = $info['width']; + $newHeight = $info['height']; + $sourceImg = imagecreatefromjpeg($path); switch ($info['orientation']) { case 2: - # mirror - # not yet implemented + // mirror + // not yet implemented return false; break; case 3: - $sourceImg = imagerotate($sourceImg, -180, 0); + $sourceImg = imagerotate($sourceImg, -180, 0); break; case 4: - # rotate 180 and mirror - # not yet implemented + // rotate 180 and mirror + // not yet implemented return false; break; case 5: - # rotate 90 and mirror - # not yet implemented + // rotate 90 and mirror + // not yet implemented return false; break; case 6: - $sourceImg = imagerotate($sourceImg, -90, 0); - $newWidth = $info['height']; - $newHeight = $info['width']; - $swapSize = true; + $sourceImg = imagerotate($sourceImg, -90, 0); + $newWidth = $info['height']; + $newHeight = $info['width']; + $swapSize = true; break; case 7: - # rotate -90 and mirror - # not yet implemented + // rotate -90 and mirror + // not yet implemented return false; break; case 8: - $sourceImg = imagerotate($sourceImg, 90, 0); - $newWidth = $info['height']; - $newHeight = $info['width']; - $swapSize = true; + $sourceImg = imagerotate($sourceImg, 90, 0); + $newWidth = $info['height']; + $newHeight = $info['width']; + $swapSize = true; break; default: @@ -550,26 +550,26 @@ final class Photo { } - # Recreate photo + // Recreate photo $newSourceImg = imagecreatetruecolor($newWidth, $newHeight); imagecopyresampled($newSourceImg, $sourceImg, 0, 0, 0, 0, $newWidth, $newHeight, $newWidth, $newHeight); imagejpeg($newSourceImg, $path, 100); - # Free memory + // Free memory imagedestroy($sourceImg); imagedestroy($newSourceImg); } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - # SwapSize should be true when the image has been rotated - # Return new dimensions in this case + // SwapSize should be true when the image has been rotated + // Return new dimensions in this case if ($swapSize===true) { - $swapSize = $info['width']; - $info['width'] = $info['height']; - $info['height'] = $swapSize; + $swapSize = $info['width']; + $info['width'] = $info['height']; + $info['height'] = $swapSize; } return $info; @@ -578,39 +578,39 @@ final class Photo { public static function prepareData(array $data) { - # Function turns photo-attributes into a front-end friendly format. Note that some attributes remain unchanged. - # Excepts the following: - # (array) $data = ['id', 'title', 'tags', 'public', 'star', 'album', 'thumbUrl', 'takestamp', 'url'] - # Returns the following: - # (array) $photo + // Function turns photo-attributes into a front-end friendly format. Note that some attributes remain unchanged. + // Excepts the following: + // (array) $data = ['id', 'title', 'tags', 'public', 'star', 'album', 'thumbUrl', 'takestamp', 'url'] + // Returns the following: + // (array) $photo - # Init + // Init $photo = null; - # Set unchanged attributes - $photo['id'] = $data['id']; - $photo['title'] = $data['title']; - $photo['tags'] = $data['tags']; - $photo['public'] = $data['public']; - $photo['star'] = $data['star']; - $photo['album'] = $data['album']; + // Set unchanged attributes + $photo['id'] = $data['id']; + $photo['title'] = $data['title']; + $photo['tags'] = $data['tags']; + $photo['public'] = $data['public']; + $photo['star'] = $data['star']; + $photo['album'] = $data['album']; - # Parse urls - $photo['thumbUrl'] = LYCHEE_URL_UPLOADS_THUMB . $data['thumbUrl']; - $photo['url'] = LYCHEE_URL_UPLOADS_BIG . $data['url']; + // Parse urls + $photo['thumbUrl'] = LYCHEE_URL_UPLOADS_THUMB . $data['thumbUrl']; + $photo['url'] = LYCHEE_URL_UPLOADS_BIG . $data['url']; - # Use takestamp as sysdate when possible + // Use takestamp as sysdate when possible if (isset($data['takestamp'])&&$data['takestamp']!=='0') { - # Use takestamp - $photo['cameraDate'] = '1'; - $photo['sysdate'] = date('d F Y', $data['takestamp']); + // Use takestamp + $photo['cameraDate'] = '1'; + $photo['sysdate'] = date('d F Y', $data['takestamp']); } else { - # Use sysstamp from the id - $photo['cameraDate'] = '0'; - $photo['sysdate'] = date('d F Y', substr($data['id'], 0, -4)); + // Use sysstamp from the id + $photo['cameraDate'] = '0'; + $photo['sysdate'] = date('d F Y', substr($data['id'], 0, -4)); } @@ -620,57 +620,57 @@ final class Photo { public function get($albumID) { - # Functions returns data of a photo - # Excepts the following: - # (string) $albumID = Album which is currently visible to the user - # Returns the following: - # (array) $photo + // Functions returns data of a photo + // Excepts the following: + // (string) $albumID = Album which is currently visible to the user + // Returns the following: + // (array) $photo - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get photo - $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_assoc(); + // Get photo + $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); + $photo = $photos->fetch_assoc(); - # Parse photo + // Parse photo $photo['sysdate'] = date('d M. Y', substr($photo['id'], 0, -4)); if (strlen($photo['takestamp'])>1) $photo['takedate'] = date('d M. Y', $photo['takestamp']); - # Parse medium - if ($photo['medium']==='1') $photo['medium'] = LYCHEE_URL_UPLOADS_MEDIUM . $photo['url']; - else $photo['medium'] = ''; + // Parse medium + if ($photo['medium']==='1') $photo['medium'] = LYCHEE_URL_UPLOADS_MEDIUM . $photo['url']; + else $photo['medium'] = ''; - # Parse paths - $photo['url'] = LYCHEE_URL_UPLOADS_BIG . $photo['url']; - $photo['thumbUrl'] = LYCHEE_URL_UPLOADS_THUMB . $photo['thumbUrl']; + // Parse paths + $photo['url'] = LYCHEE_URL_UPLOADS_BIG . $photo['url']; + $photo['thumbUrl'] = LYCHEE_URL_UPLOADS_THUMB . $photo['thumbUrl']; if ($albumID!='false') { - # Only show photo as public when parent album is public - # Check if parent album is not 'Unsorted' + // Only show photo as public when parent album is public + // Check if parent album is not 'Unsorted' if ($photo['album']!=='0') { - # Get album - $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); - $albums = Database::get()->query($query); - $album = $albums->fetch_assoc(); + // Get album + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); + $albums = Database::get()->query($query); + $album = $albums->fetch_assoc(); - # Parse album + // Parse album $photo['public'] = ($album['public']==='1' ? '2' : $photo['public']); } - $photo['original_album'] = $photo['album']; - $photo['album'] = $albumID; + $photo['original_album'] = $photo['album']; + $photo['album'] = $albumID; } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $photo; @@ -679,33 +679,33 @@ final class Photo { public function getInfo($url) { - # Functions returns information and metadata of a photo - # Excepts the following: - # (string) $url = Path to photo-file - # Returns the following: - # (array) $return + // Functions returns information and metadata of a photo + // Excepts the following: + // (string) $url = Path to photo-file + // Returns the following: + // (array) $return - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - $iptcArray = array(); - $info = getimagesize($url, $iptcArray); + $iptcArray = array(); + $info = getimagesize($url, $iptcArray); - # General information - $return['type'] = $info['mime']; - $return['width'] = $info[0]; - $return['height'] = $info[1]; + // General information + $return['type'] = $info['mime']; + $return['width'] = $info[0]; + $return['height'] = $info[1]; - # Size + // Size $size = filesize($url)/1024; if ($size>=1024) $return['size'] = round($size/1024, 1) . ' MB'; else $return['size'] = round($size, 1) . ' KB'; - # IPTC Metadata Fallback - $return['title'] = ''; - $return['description'] = ''; + // IPTC Metadata Fallback + $return['title'] = ''; + $return['description'] = ''; - # IPTC Metadata + // IPTC Metadata if(isset($iptcArray['APP13'])) { $iptcInfo = iptcparse($iptcArray['APP13']); @@ -724,21 +724,21 @@ final class Photo { } - # EXIF Metadata Fallback - $return['orientation'] = ''; - $return['iso'] = ''; - $return['aperture'] = ''; - $return['make'] = ''; - $return['model'] = ''; - $return['shutter'] = ''; - $return['focal'] = ''; - $return['takestamp'] = 0; + // EXIF Metadata Fallback + $return['orientation'] = ''; + $return['iso'] = ''; + $return['aperture'] = ''; + $return['make'] = ''; + $return['model'] = ''; + $return['shutter'] = ''; + $return['focal'] = ''; + $return['takestamp'] = 0; - # Read EXIF + // Read EXIF if ($info['mime']=='image/jpeg') $exif = @exif_read_data($url, 'EXIF', 0); else $exif = false; - # EXIF Metadata + // EXIF Metadata if ($exif!==false) { if (isset($exif['Orientation'])) $return['orientation'] = $exif['Orientation']; @@ -775,7 +775,7 @@ final class Photo { } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -784,62 +784,62 @@ final class Photo { public function getArchive() { - # Functions starts a download of a photo - # Returns the following: - # (boolean + output) true = Success - # (boolean) false = Failure + // Functions starts a download of a photo + // Returns the following: + // (boolean + output) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get photo - $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); + // Get photo + $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); + $photo = $photos->fetch_object(); - # Error in database query + // Error in database query if (!$photos) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # Photo not found + // Photo not found if ($photo===null) { Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); return false; } - # Get extension + // Get extension $extension = getExtension($photo->url); if ($extension===false) { Log::error(__METHOD__, __LINE__, 'Invalid photo extension'); return false; } - # Illicit chars - $badChars = array_merge( - array_map('chr', range(0,31)), - array("<", ">", ":", '"', "/", "\\", "|", "?", "*") - ); + // Illicit chars + $badChars = array_merge( + array_map('chr', range(0,31)), + array("<", ">", ":", '"', "/", "\\", "|", "?", "*") + ); - # Parse title + // Parse title if ($photo->title=='') $photo->title = 'Untitled'; - # Escape title + // Escape title $photo->title = str_replace($badChars, '', $photo->title); - # Set headers + // Set headers header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"" . $photo->title . $extension . "\""); header("Content-Length: " . filesize(LYCHEE_UPLOADS_BIG . $photo->url)); - # Send file + // Send file readfile(LYCHEE_UPLOADS_BIG . $photo->url); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; @@ -848,24 +848,24 @@ final class Photo { public function setTitle($title) { - # Functions sets the title of a photo - # Excepts the following: - # (string) $title = Title with a maximum length of 50 chars - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions sets the title of a photo + // Excepts the following: + // (string) $title = Title with a maximum length of 50 chars + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Set title - $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); - $result = Database::get()->query($query); + // Set title + $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -878,24 +878,24 @@ final class Photo { public function setDescription($description) { - # Functions sets the description of a photo - # Excepts the following: - # (string) $description = Description with a maximum length of 1000 chars - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions sets the description of a photo + // Excepts the following: + // (string) $description = Description with a maximum length of 1000 chars + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Set description - $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); - $result = Database::get()->query($query); + // Set description + $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -908,38 +908,38 @@ final class Photo { public function setStar() { - # Functions stars a photo - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions stars a photo + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Init vars - $error = false; + // Init vars + $error = false; - # Get photos - $query = Database::prepare(Database::get(), "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + // Get photos + $query = Database::prepare(Database::get(), "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); - # For each photo + // For each photo while ($photo = $photos->fetch_object()) { - # Invert star + // Invert star $star = ($photo->star==0 ? 1 : 0); - # Set star - $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); - $star = Database::get()->query($query); + // Set star + $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); + $star = Database::get()->query($query); if (!$star) $error = true; } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error===true) { @@ -952,78 +952,78 @@ final class Photo { public function getPublic($password) { - # Functions checks if photo or parent album is public - # Returns the following: - # (int) 0 = Photo private and parent album private - # (int) 1 = Album public, but password incorrect - # (int) 2 = Photo public or album public and password correct + // Functions checks if photo or parent album is public + // Returns the following: + // (int) 0 = Photo private and parent album private + // (int) 1 = Album public, but password incorrect + // (int) 2 = Photo public or album public and password correct - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get photo - $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); + // Get photo + $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); + $photo = $photos->fetch_object(); - # Check if public + // Check if public if ($photo->public==='1') { - # Photo public + // Photo public return 2; } else { - # Check if album public - $album = new Album($photo->album); - $agP = $album->getPublic(); - $acP = $album->checkPassword($password); + // Check if album public + $album = new Album($photo->album); + $agP = $album->getPublic(); + $acP = $album->checkPassword($password); - # Album public and password correct + // Album public and password correct if ($agP===true&&$acP===true) return 2; - # Album public, but password incorrect + // Album public, but password incorrect if ($agP===true&&$acP===false) return 1; } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - # Photo private + // Photo private return 0; } public function setPublic() { - # Functions toggles the public property of a photo - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions toggles the public property of a photo + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get public - $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); + // Get public + $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); + $photo = $photos->fetch_object(); - # Invert public + // Invert public $public = ($photo->public==0 ? 1 : 0); - # Set public - $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs)); - $result = Database::get()->query($query); + // Set public + $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -1036,22 +1036,22 @@ final class Photo { function setAlbum($albumID) { - # Functions sets the parent album of a photo - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions sets the parent album of a photo + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Set album - $query = Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); - $result = Database::get()->query($query); + // Set album + $query = Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -1064,28 +1064,28 @@ final class Photo { public function setTags($tags) { - # Functions sets the tags of a photo - # Excepts the following: - # (string) $tags = Comma separated list of tags with a maximum length of 1000 chars - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions sets the tags of a photo + // Excepts the following: + // (string) $tags = Comma separated list of tags with a maximum length of 1000 chars + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Parse tags + // Parse tags $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); $tags = preg_replace('/,$|^,|(\ ){0,}$/', '', $tags); - # Set tags - $query = Database::prepare(Database::get(), "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs)); - $result = Database::get()->query($query); + // Set tags + $query = Database::prepare(Database::get(), "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs)); + $result = Database::get()->query($query); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if (!$result) { @@ -1098,36 +1098,36 @@ final class Photo { public function duplicate() { - # Functions duplicates a photo - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions duplicates a photo + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get photos - $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + // Get photos + $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); if (!$photos) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # For each photo + // For each photo while ($photo = $photos->fetch_object()) { - # Generate id + // Generate id $id = str_replace('.', '', microtime(true)); while(strlen($id)<14) $id .= 0; - # Duplicate entry - $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); - $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); - $duplicate = Database::get()->query($query); + // Duplicate entry + $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); + $duplicate = Database::get()->query($query); if (!$duplicate) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; @@ -1141,65 +1141,65 @@ final class Photo { public function delete() { - # Functions deletes a photo with all its data and files - # Returns the following: - # (boolean) true = Success - # (boolean) false = Failure + // Functions deletes a photo with all its data and files + // Returns the following: + // (boolean) true = Success + // (boolean) false = Failure - # Check dependencies + // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Get photos - $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + // Get photos + $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $photos = Database::get()->query($query); if (!$photos) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } - # For each photo + // For each photo while ($photo = $photos->fetch_object()) { - # Check if other photos are referring to this images - # If so, only delete the db entry + // Check if other photos are referring to this images + // If so, only delete the db entry if ($this->exists($photo->checksum, $photo->id)===false) { - # Get retina thumb url + // Get retina thumb url $thumbUrl2x = explode(".", $photo->thumbUrl); $thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1]; - # Delete big + // Delete big if (file_exists(LYCHEE_UPLOADS_BIG . $photo->url)&&!unlink(LYCHEE_UPLOADS_BIG . $photo->url)) { Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/big/'); return false; } - # Delete medium + // Delete medium if (file_exists(LYCHEE_UPLOADS_MEDIUM . $photo->url)&&!unlink(LYCHEE_UPLOADS_MEDIUM . $photo->url)) { Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/medium/'); return false; } - # Delete thumb + // Delete thumb if (file_exists(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)&&!unlink(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)) { Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/'); return false; } - # Delete thumb@2x - if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)) { + // Delete thumb@2x + if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)) { Log::error(__METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/'); return false; } } - # Delete db entry - $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); - $delete = Database::get()->query($query); + // Delete db entry + $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); + $delete = Database::get()->query($query); if (!$delete) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; @@ -1207,7 +1207,7 @@ final class Photo { } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; diff --git a/php/Modules/Plugins.php b/php/Modules/Plugins.php index 13bb55c..ed17f02 100644 --- a/php/Modules/Plugins.php +++ b/php/Modules/Plugins.php @@ -30,7 +30,7 @@ final class Plugins implements SplSubject { private function __construct(array $plugins) { - # Load plugins + // Load plugins foreach ($plugins as $plugin) { if ($plugin==='') continue; @@ -47,7 +47,7 @@ final class Plugins implements SplSubject { if (!isset($observer)) return false; - # Add observer + // Add observer $this->observers[] = $observer; return true; @@ -58,7 +58,7 @@ final class Plugins implements SplSubject { if (!isset($observer)) return false; - # Remove observer + // Remove observer $key = array_search($observer, $this->observers, true); if ($key) unset($this->observers[$key]); @@ -68,7 +68,7 @@ final class Plugins implements SplSubject { public function notify() { - # Notify each observer + // Notify each observer foreach ($this->observers as $value) $value->update($this); return true; @@ -79,15 +79,15 @@ final class Plugins implements SplSubject { if (!isset($name, $location, $args)) return false; - # Parse - $location = ($location===0 ? 'before' : 'after'); - $action = $name . ":" . $location; + // Parse + $location = ($location===0 ? 'before' : 'after'); + $action = $name . ":" . $location; - # Save vars - $this->action = $action; - $this->args = $args; + // Save vars + $this->action = $action; + $this->args = $args; - # Notify observers + // Notify observers $this->notify(); return true; diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 580274e..94c4278 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -6,23 +6,23 @@ final class Session { public function init($public = true) { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - # Return settings + // Return settings $return['config'] = Settings::get(); - # Path to Lychee for the server-import dialog + // Path to Lychee for the server-import dialog $return['config']['location'] = LYCHEE; - # Remove username and password from response + // Remove username and password from response unset($return['config']['username']); unset($return['config']['password']); - # Remove identifier from response + // Remove identifier from response unset($return['config']['identifier']); - # Check if login credentials exist and login if they don't + // Check if login credentials exist and login if they don't if ($this->noLogin()===true) { $public = false; $return['config']['login'] = false; @@ -32,15 +32,15 @@ final class Session { if ($public===false) { - # Logged in + // Logged in $return['status'] = LYCHEE_STATUS_LOGGEDIN; } else { - # Logged out + // Logged out $return['status'] = LYCHEE_STATUS_LOGGEDOUT; - # Unset unused vars + // Unset unused vars unset($return['config']['skipDuplicates']); unset($return['config']['thumbQuality']); unset($return['config']['sortingAlbums']); @@ -54,7 +54,7 @@ final class Session { } - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return $return; @@ -63,24 +63,24 @@ final class Session { public function login($username, $password) { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); $username = crypt($username, Settings::get()['username']); $password = crypt($password, Settings::get()['password']); - # Check login with crypted hash + // Check login with crypted hash if (Settings::get()['username']===$username&& Settings::get()['password']===$password) { - $_SESSION['login'] = true; - $_SESSION['identifier'] = Settings::get()['identifier']; + $_SESSION['login'] = true; + $_SESSION['identifier'] = Settings::get()['identifier']; return true; } - # No login + // No login if ($this->noLogin()===true) return true; - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return false; @@ -89,11 +89,11 @@ final class Session { private function noLogin() { - # Check if login credentials exist and login if they don't + // Check if login credentials exist and login if they don't if (Settings::get()['username']===''&& Settings::get()['password']==='') { - $_SESSION['login'] = true; - $_SESSION['identifier'] = Settings::get()['identifier']; + $_SESSION['login'] = true; + $_SESSION['identifier'] = Settings::get()['identifier']; return true; } @@ -103,15 +103,15 @@ final class Session { public function logout() { - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - $_SESSION['login'] = null; - $_SESSION['identifier'] = null; + $_SESSION['login'] = null; + $_SESSION['identifier'] = null; session_destroy(); - # Call plugins + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); return true; diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index d916cce..9d22d99 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -10,14 +10,14 @@ final class Settings { if (self::$cache) return self::$cache; - # Execute query - $query = Database::prepare(Database::get(), "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS)); - $settings = Database::get()->query($query); + // Execute query + $query = Database::prepare(Database::get(), "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS)); + $settings = Database::get()->query($query); - # Add each to return + // Add each to return while ($setting = $settings->fetch_object()) $return[$setting->key] = $setting->value; - # Convert plugins to array + // Convert plugins to array $return['plugins'] = explode(';', $return['plugins']); self::$cache = $return; @@ -30,12 +30,12 @@ final class Settings { if ($row===false) { - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '?' WHERE `key` = '?'", array(LYCHEE_TABLE_SETTINGS, $value, $key)); + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '?' WHERE `key` = '?'", array(LYCHEE_TABLE_SETTINGS, $value, $key)); } elseif ($row===true) { - # Do not prepare $value because it has already been escaped or is a true statement - $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$value' WHERE `key` = '?'", array(LYCHEE_TABLE_SETTINGS, $key)); + // Do not prepare $value because it has already been escaped or is a true statement + $query = Database::prepare(Database::get(), "UPDATE ? SET value = '$value' WHERE `key` = '?'", array(LYCHEE_TABLE_SETTINGS, $key)); } else { @@ -54,10 +54,10 @@ final class Settings { if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) { - # Save username + // Save username if (self::setUsername($username)!==true) exit('Error: Updating username failed!'); - # Save password + // Save password if (self::setPassword($password)!==true) exit('Error: Updating password failed!'); return true; @@ -70,15 +70,15 @@ final class Settings { private static function setUsername($username) { - # Check dependencies + // Check dependencies Validator::required(isset($username), __METHOD__); - # Hash username + // Hash username $username = getHashedString($username); - # Execute query - # Do not prepare $username because it is hashed and save - # Preparing (escaping) the username would destroy the hash + // Execute query + // Do not prepare $username because it is hashed and save + // Preparing (escaping) the username would destroy the hash if (self::set('username', $username, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; @@ -89,14 +89,14 @@ final class Settings { private static function setPassword($password) { - # Check dependencies + // Check dependencies Validator::required(isset($password), __METHOD__); - # Hash password + // Hash password $password = getHashedString($password); - # Do not prepare $password because it is hashed and save - # Preparing (escaping) the password would destroy the hash + // Do not prepare $password because it is hashed and save + // Preparing (escaping) the password would destroy the hash if (self::set('password', $password, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; @@ -124,52 +124,34 @@ final class Settings { $sorting = 'ORDER BY '; - # Set row + // Set row switch ($type) { - case 'id': $sorting .= 'id'; - break; - - case 'title': $sorting .= 'title'; - break; - - case 'description': $sorting .= 'description'; - break; - - case 'public': $sorting .= 'public'; - break; - - case 'type': $sorting .= 'type'; - break; - - case 'star': $sorting .= 'star'; - break; - - case 'takestamp': $sorting .= 'takestamp'; - break; - - default: exit('Error: Unknown type for sorting!'); + case 'id': $sorting .= 'id'; break; + case 'title': $sorting .= 'title'; break; + case 'description': $sorting .= 'description'; break; + case 'public': $sorting .= 'public'; break; + case 'type': $sorting .= 'type'; break; + case 'star': $sorting .= 'star'; break; + case 'takestamp': $sorting .= 'takestamp'; break; + default: exit('Error: Unknown type for sorting!'); } $sorting .= ' '; - # Set order + // Set order switch ($order) { - case 'ASC': $sorting .= 'ASC'; - break; - - case 'DESC': $sorting .= 'DESC'; - break; - - default: exit('Error: Unknown order for sorting!'); + case 'ASC': $sorting .= 'ASC'; break; + case 'DESC': $sorting .= 'DESC'; break; + default: exit('Error: Unknown order for sorting!'); } - # Do not prepare $sorting because it is a true statement - # Preparing (escaping) the sorting would destroy it - # $sorting is save and can't contain user-input + // Do not prepare $sorting because it is a true statement + // Preparing (escaping) the sorting would destroy it + // $sorting is save and can't contain user-input if (self::set('sortingPhotos', $sorting, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; @@ -182,43 +164,31 @@ final class Settings { $sorting = 'ORDER BY '; - # Set row + // Set row switch ($type) { - case 'id': $sorting .= 'id'; - break; - - case 'title': $sorting .= 'title'; - break; - - case 'description': $sorting .= 'description'; - break; - - case 'public': $sorting .= 'public'; - break; - - default: exit('Error: Unknown type for sorting!'); + case 'id': $sorting .= 'id'; break; + case 'title': $sorting .= 'title'; break; + case 'description': $sorting .= 'description'; break; + case 'public': $sorting .= 'public'; break; + default: exit('Error: Unknown type for sorting!'); } $sorting .= ' '; - # Set order + // Set order switch ($order) { - case 'ASC': $sorting .= 'ASC'; - break; - - case 'DESC': $sorting .= 'DESC'; - break; - - default: exit('Error: Unknown order for sorting!'); + case 'ASC': $sorting .= 'ASC'; break; + case 'DESC': $sorting .= 'DESC'; break; + default: exit('Error: Unknown order for sorting!'); } - # Do not prepare $sorting because it is a true statement - # Preparing (escaping) the sorting would destroy it - # $sorting is save and can't contain user-input + // Do not prepare $sorting because it is a true statement + // Preparing (escaping) the sorting would destroy it + // $sorting is save and can't contain user-input if (self::set('sortingAlbums', $sorting, true)===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; diff --git a/php/database/update_020700.php b/php/database/update_020700.php index c610054..292d9e6 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -1,43 +1,43 @@ query($query)) { - $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); - $result = $connection->query($query); + $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); + $result = $connection->query($query); if (!$result) { Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } -# Create medium folder +// Create medium folder if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) { - # Only create the folder when it is missing - if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false) + // Only create the folder when it is missing + if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false) { Log::error('update_020700', __LINE__, 'Could not create medium-folder'); + } } -# Add medium to settings -$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +// Add medium to settings +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } -# Set version +// Set version if (Database::setVersion($connection, '020700')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030000.php b/php/database/update_030000.php index 937f1d4..c5a5f2a 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -1,37 +1,36 @@ query($query); +// Remove login +// Login now saved as crypt without md5. Legacy code has been removed. +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$resetUsername = $connection->query($query); if (!$resetUsername) { Log::error('update_030000', __LINE__, 'Could not reset username (' . $connection->error . ')'); return false; } -$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$resetPassword = $connection->query($query); +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$resetPassword = $connection->query($query); if (!$resetPassword) { Log::error('update_030000', __LINE__, 'Could not reset password (' . $connection->error . ')'); return false; } -# Make public albums private and reset password -# Password now saved as crypt without md5. Legacy code has been removed. -$query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); -$resetPublic = $connection->query($query); +// Make public albums private and reset password +// Password now saved as crypt without md5. Legacy code has been removed. +$query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); +$resetPublic = $connection->query($query); if (!$resetPublic) { Log::error('update_030000', __LINE__, 'Could not reset public albums (' . $connection->error . ')'); return false; } -# Set version +// Set version if (Database::setVersion($connection, '030000')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030001.php b/php/database/update_030001.php index c13505c..2e3309c 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -1,62 +1,61 @@ query($query); +// Change length of photo title +$query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); +$result = $connection->query($query); if (!$result) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } -# Change length of album title -$query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); -$result = $connection->query($query); +// Change length of album title +$query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); +$result = $connection->query($query); if (!$result) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } -# Add album sorting to settings -$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +// Add album sorting to settings +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } -# Rename sorting to sortingPhotos -$query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +// Rename sorting to sortingPhotos +$query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if (!$result) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } -# Add identifier to settings -$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +// Add identifier to settings +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $identifier = md5(microtime(true)); - $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); - $result = $connection->query($query); + $identifier = md5(microtime(true)); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); + $result = $connection->query($query); if (!$result) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } -# Set version +// Set version if (Database::setVersion($connection, '030001')===false) return false; ?> \ No newline at end of file diff --git a/php/database/update_030003.php b/php/database/update_030003.php index dd09fe7..16b22b1 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -1,25 +1,24 @@ query($query); +// Add skipDuplicates to settings +$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); if ($result->num_rows===0) { - $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($query); if (!$result) { Log::error('update_030003', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } } -# Set version +// Set version if (Database::setVersion($connection, '030003')===false) return false; ?> \ No newline at end of file diff --git a/php/define.php b/php/define.php index cf35353..a215adc 100644 --- a/php/define.php +++ b/php/define.php @@ -1,14 +1,14 @@ getPublic('')===false) return false; - $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); - $result = Database::get()->query($query); - $row = $result->fetch_object(); + $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); + $result = Database::get()->query($query); + $row = $result->fetch_object(); if (!$result||!$row) return false; - if ($row->medium==='1') $dir = 'medium'; - else $dir = 'big'; + if ($row->medium==='1') $dir = 'medium'; + else $dir = 'big'; - $parseUrl = parse_url('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); - $url = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '?' . $parseUrl['query']; - $picture = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '/../uploads/' . $dir . '/' . $row->url; + $parseUrl = parse_url('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); + $url = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '?' . $parseUrl['query']; + $picture = $parseUrl['scheme'] . '://' . $parseUrl['host'] . $parseUrl['path'] . '/../uploads/' . $dir . '/' . $row->url; - $url = htmlentities($url); - $picture = htmlentities($picture); + $url = htmlentities($url); + $picture = htmlentities($picture); - $row->title = htmlentities($row->title); - $row->description = htmlentities($row->description); + $row->title = htmlentities($row->title); + $row->description = htmlentities($row->description); $return = ''; $return .= ''; diff --git a/php/helpers/getHashedString.php b/php/helpers/getHashedString.php index 1205586..3c5f890 100644 --- a/php/helpers/getHashedString.php +++ b/php/helpers/getHashedString.php @@ -2,28 +2,35 @@ function getHashedString($password) { - # Inspired by http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/ + // Inspired by http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/ - # A higher $cost is more secure but consumes more processing power + // A higher $cost is more secure but consumes more processing power $cost = 10; - # Create a random salt + // Create a random salt if (extension_loaded('openssl')) { + $salt = strtr(substr(base64_encode(openssl_random_pseudo_bytes(17)),0,22), '+', '.'); + } elseif (extension_loaded('mcrypt')) { + $salt = strtr(substr(base64_encode(mcrypt_create_iv(17, MCRYPT_DEV_URANDOM)),0,22), '+', '.'); + } else { - $salt = ""; + + $salt = ''; + for ($i = 0; $i < 22; $i++) { $salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 63), 1); } + } - # Prefix information about the hash so PHP knows how to verify it later. - # "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter. + // Prefix information about the hash so PHP knows how to verify it later. + // "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter. $salt = sprintf("$2a$%02d$", $cost) . $salt; - # Hash the password with the salt + // Hash the password with the salt return crypt($password, $salt); } diff --git a/php/helpers/hasPermissions.php b/php/helpers/hasPermissions.php index f5f8bbd..c862436 100644 --- a/php/helpers/hasPermissions.php +++ b/php/helpers/hasPermissions.php @@ -4,8 +4,7 @@ function hasPermissions($path) { // Check if the given path is readable and writable // Both functions are also verifying that the path exists - if (is_readable($path)===true&& - is_writeable($path)===true) return true; + if (is_readable($path)===true&&is_writeable($path)===true) return true; return false; diff --git a/php/helpers/search.php b/php/helpers/search.php index 5786b83..f975577 100755 --- a/php/helpers/search.php +++ b/php/helpers/search.php @@ -2,21 +2,19 @@ function search($term) { - $return['albums'] = ''; - - # Initialize return var + // Initialize return var $return = array( - 'photos' => null, - 'albums' => null, - 'hash' => '' + 'photos' => null, + 'albums' => null, + 'hash' => '' ); - ### - # Photos - ### + /** + * Photos + */ - $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); - $result = Database::get()->query($query); + $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); + $result = Database::get()->query($query); while($photo = $result->fetch_assoc()) { @@ -25,35 +23,35 @@ function search($term) { } - ### - # Albums - ### + /** + * Albums + */ - $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); + $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); $result = Database::get()->query($query); while($album = $result->fetch_assoc()) { - # Turn data from the database into a front-end friendly format + // Turn data from the database into a front-end friendly format $album = Album::prepareData($album); - # Thumbs - $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::get()->query($query); + // Thumbs + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::get()->query($query); - # For each thumb + // For each thumb $k = 0; while ($thumb = $thumbs->fetch_object()) { $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; $k++; } - # Add to return + // Add to return $return['albums'][$album['id']] = $album; } - # Hash + // Hash $return['hash'] = md5(json_encode($return)); return $return; diff --git a/php/index.php b/php/index.php index 2e72991..04b9858 100755 --- a/php/index.php +++ b/php/index.php @@ -1,10 +1,9 @@ Date: Sat, 30 Jan 2016 23:07:59 +0100 Subject: [PATCH 043/183] Fixed database updates --- php/database/update_020700.php | 4 ++++ php/database/update_030000.php | 4 ++++ php/database/update_030001.php | 4 ++++ php/database/update_030003.php | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/php/database/update_020700.php b/php/database/update_020700.php index 292d9e6..757276b 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -4,6 +4,10 @@ * Update to version 2.7.0 */ +namespace Lychee\Database; + +use Lychee\Modules\Database; + if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Add medium to photos diff --git a/php/database/update_030000.php b/php/database/update_030000.php index c5a5f2a..b3a58d8 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -4,6 +4,10 @@ * Update to version 3.0.0 */ +namespace Lychee\Database; + +use Lychee\Modules\Database; + if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Remove login diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 2e3309c..5555e7d 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -4,6 +4,10 @@ * Update to version 3.0.1 */ +namespace Lychee\Database; + +use Lychee\Modules\Database; + if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Change length of photo title diff --git a/php/database/update_030003.php b/php/database/update_030003.php index 16b22b1..ae73e44 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -4,6 +4,10 @@ * Update to version 3.0.3 */ +namespace Lychee\Database; + +use Lychee\Modules\Database; + if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Add skipDuplicates to settings From b89b82fa36468165efe68f9de8a85eedccd416a4 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:16:42 +0100 Subject: [PATCH 044/183] Fixed search --- php/helpers/search.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php/helpers/search.php b/php/helpers/search.php index f975577..e1a4e97 100755 --- a/php/helpers/search.php +++ b/php/helpers/search.php @@ -1,5 +1,7 @@ Date: Sat, 30 Jan 2016 23:16:59 +0100 Subject: [PATCH 045/183] Removed unnecessary namespace --- php/database/update_020700.php | 2 -- php/database/update_030000.php | 2 -- php/database/update_030001.php | 2 -- php/database/update_030003.php | 2 -- 4 files changed, 8 deletions(-) diff --git a/php/database/update_020700.php b/php/database/update_020700.php index 757276b..ea87e45 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -4,8 +4,6 @@ * Update to version 2.7.0 */ -namespace Lychee\Database; - use Lychee\Modules\Database; if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); diff --git a/php/database/update_030000.php b/php/database/update_030000.php index b3a58d8..2062203 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -4,8 +4,6 @@ * Update to version 3.0.0 */ -namespace Lychee\Database; - use Lychee\Modules\Database; if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 5555e7d..575f02c 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -4,8 +4,6 @@ * Update to version 3.0.1 */ -namespace Lychee\Database; - use Lychee\Modules\Database; if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); diff --git a/php/database/update_030003.php b/php/database/update_030003.php index ae73e44..d204ad5 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -4,8 +4,6 @@ * Update to version 3.0.3 */ -namespace Lychee\Database; - use Lychee\Modules\Database; if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); From e8387e8794a441834099e674c50cb4c8a87caca7 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:17:23 +0100 Subject: [PATCH 046/183] Fixed missing Database and Photo in getGraphHeader --- php/helpers/getGraphHeader.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php/helpers/getGraphHeader.php b/php/helpers/getGraphHeader.php index 2453c3a..e601fcc 100644 --- a/php/helpers/getGraphHeader.php +++ b/php/helpers/getGraphHeader.php @@ -1,5 +1,8 @@ Date: Sat, 30 Jan 2016 23:17:46 +0100 Subject: [PATCH 047/183] Fixed set login of initial username and password --- php/Access/Admin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 84175d8..54f6e12 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -291,7 +291,8 @@ final class Admin extends Access { Validator::required(isset($_POST['username'], $_POST['password']), __METHOD__); - echo Settings::setLogin(@$_POST['oldPassword'], $_POST['username'], $_POST['password']); + if (isset($_POST['oldPassword'])===false) $_POST['oldPassword'] = ''; + echo Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); } From e2eaa38b9c5abfbd7bc9fd517255d9502c94fb4c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:23:58 +0100 Subject: [PATCH 048/183] Added missing argument --- php/Access/Admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 54f6e12..fe84782 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -132,7 +132,7 @@ final class Admin extends Access { private static function mergeAlbumsAction() { - Validator::required(isset($_POST['albumIDs'])); + Validator::required(isset($_POST['albumIDs']), __METHOD__); $album = new Album($_POST['albumIDs']); echo $album->merge(); From b78cc31127797b42192828d6901be721b4cf1485 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:24:08 +0100 Subject: [PATCH 049/183] Fixed ZipArchive not found --- php/Modules/Album.php | 2 ++ php/Modules/Photo.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index ebfe111..fa38eb0 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -2,6 +2,8 @@ namespace Lychee\Modules; +use ZipArchive; + final class Album { private $albumIDs = null; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 039fe79..c677007 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -2,6 +2,8 @@ namespace Lychee\Modules; +use ZipArchive; + final class Photo { private $photoIDs = null; From 76d1b227bf0c970da6cca138d5ecf1478d80f690 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:57:20 +0100 Subject: [PATCH 050/183] Fixed outdated require in view.php --- view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view.php b/view.php index 0b0e001..638af87 100644 --- a/view.php +++ b/view.php @@ -25,7 +25,7 @@ # Load required files require(__DIR__ . '/php/define.php'); require(__DIR__ . '/php/autoload.php'); - require(__DIR__ . '/php/misc.php'); + require(__DIR__ . '/php/helpers/getGraphHeader.php'); echo getGraphHeader($_GET['p']); From 36dd48ec2762db7d675dc6d745a32420979c772c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:58:08 +0100 Subject: [PATCH 051/183] Fixed link check when sharing a photo --- src/scripts/photo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index 7c73d44..5ca7bac 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -621,7 +621,7 @@ photo.share = function(photoID, service) { break } - if (link.length!=='') location.href = link + if (link!=='') location.href = link } From 7dd82fc516612cf6bf9489e7f84fcfdb61321696 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:58:24 +0100 Subject: [PATCH 052/183] Improved lychee.dropbox and lychee.dropboxKey check --- src/scripts/lychee.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 1efc4eb..1f88917 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -330,7 +330,7 @@ lychee.retinize = function(path = '') { lychee.loadDropbox = function(callback) { - if (!lychee.dropbox && lychee.dropboxKey) { + if (lychee.dropbox===false && lychee.dropboxKey!=null && lychee.dropboxKey!=='') { loadingBar.show() @@ -351,7 +351,7 @@ lychee.loadDropbox = function(callback) { } s.parentNode.insertBefore(g, s) - } else if (lychee.dropbox&&lychee.dropboxKey) { + } else if (lychee.dropbox===true && lychee.dropboxKey!=null && lychee.dropboxKey!=='') { callback() From 00cd60a58884c95f18bfe7cb8c097a0976ea3422 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 30 Jan 2016 23:58:29 +0100 Subject: [PATCH 053/183] Rebuild --- dist/main.js | Bin 192542 -> 192604 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index 56ab19262be169576c9846f89d20c48a12d4af93..fb1b9858be5599778086302b0d507decbb98683a 100644 GIT binary patch delta 163 zcmbRDfcwq^?uHh|Ele9cjB_fJGg4FaQi}2mlJYBTZEY0|)ztDzb8-}IQKh_7E7jDL zloV}kw;%Liy1}RlQfoj^?QAcmnQBa2`O_0CnZ&326fzl1Uzp4!ynR9;lK|iL<@HR{ Y@))_M+rDE8oqqNO6Z`gA@0eN`0eCey{r~^~ delta 102 zcmV-s0Ga>X;0vDM3xI?Hv;we55g}}OV`yb%E@X0VaAI$GCMLJzNCMaa0wyN6;7S6S zCIN4k!Ri7OmydA*GXV;h@aX~-mw)O44yWaD0uBc*Y-Mg|bZEEbe*%_nmwfI5RRIdO I(e46^0UG!yR{#J2 From 84afba9548c234cbe4809865f96b9cb3628f3b2f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 00:01:42 +0100 Subject: [PATCH 054/183] Added missing Album and Photo class to search --- php/helpers/search.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/php/helpers/search.php b/php/helpers/search.php index e1a4e97..6b17fd9 100755 --- a/php/helpers/search.php +++ b/php/helpers/search.php @@ -1,6 +1,8 @@ Date: Sun, 31 Jan 2016 00:56:16 +0100 Subject: [PATCH 055/183] Missing parameter --- php/Access/Installation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Access/Installation.php b/php/Access/Installation.php index 946f6bc..0a4a2e2 100644 --- a/php/Access/Installation.php +++ b/php/Access/Installation.php @@ -24,7 +24,7 @@ final class Installation extends Access { private static function configCreateAction() { - Validator::required(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix'])); + Validator::required(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']), __METHOD__); echo Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']); From 207e98a81ccbe8bed2a46b7f34c024758585e21d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 00:56:42 +0100 Subject: [PATCH 056/183] fnNotFound was not callable from extending class --- php/Access/Access.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Access/Access.php b/php/Access/Access.php index b90f210..6b471fe 100644 --- a/php/Access/Access.php +++ b/php/Access/Access.php @@ -4,7 +4,7 @@ namespace Lychee\Access; abstract class Access { - final private static function fnNotFound() { + final protected static function fnNotFound() { exit('Error: Function not found! Please check the spelling of the called function.'); From f90e171e9c7a73ca60c701413425b1d823f13573 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 12:28:22 +0100 Subject: [PATCH 057/183] Added lychee-create-medium #453 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 388ed11..77886e4 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Here's a list of all available Plugins and Extensions: | lychee-rss | Creates a RSS-Feed out of your photos | [More »](https://github.com/cternes/Lychee-RSS) | | lychee-FlashAir | Import from a Toshiba FlashAir WiFi SD card | [More »](https://github.com/mhp/Lychee-FlashAir) | | lychee-webroot | Controls photos accessibility and keeps Lychee files hidden | [More »](https://github.com/Bramas/lychee-webroot) | +| lychee-create-medium | Generate missing medium size photos | [More »](https://github.com/Bramas/lychee-create-medium) | ## Troubleshooting From 4328b516a52497e3547a3859b98ff970e264010a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 12:46:43 +0100 Subject: [PATCH 058/183] Updated path to the diagnostics --- docs/FAQ.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index d0874dd..d0764a4 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,5 +1,5 @@ #### Lychee is not working -If Lychee is not working properly, try to open `plugins/check/index.php`. This script will display all errors it can find. +If Lychee is not working properly, try to open `plugins/Diagnostics/index.php`. This script will display all errors it can find. #### What do I need to run Lychee on my server? To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. @@ -38,7 +38,7 @@ To backup your Lychee installation you need to do the following steps: - INSERT INTO lychee_photos_backup SELECT * FROM lychee_photos; - CREATE TABLE lychee_settings_backup LIKE lychee_settings; - INSERT INTO lychee_settings_backup SELECT * FROM lychee_settings; - + #### Can I use my existing folder-structure? No. Lychee has it's own folder-structure and database. Please upload or import all your photos to use them. From a5437a3e6613036bbc3c50f2b46a7b0bb8d7ab1d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 12:47:00 +0100 Subject: [PATCH 059/183] Updated contributing guidelines --- CONTRIBUTING.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc00b9f..86eed15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,8 +2,8 @@ Read the following before reporting a bug on GitHub: -1. Update to the newest version of Lychee -2. Update your Browser to the newest version +1. Update Lychee to the newest version +2. Update your browser to the newest version 2. Take a look in the [FAQ](https://github.com/electerious/Lychee/blob/master/docs/FAQ.md) 3. Check if someone has [already reported](https://github.com/electerious/Lychee/issues) the same bug @@ -12,7 +12,7 @@ When reporting a bug on GitHub, make sure you include the following information: - Detailed description of the problem - How to reproduce the issue (step-by-step) - What you have already tried -- Output of the diagnostics (`plugins/check/index.php`) +- Output of the diagnostics (`plugins/Diagnostics/index.php`) - Browser and system version - Attach files when you have problems which specific photos @@ -23,15 +23,15 @@ Check if there are branches newer than `master`. Always fork the newest availabl Please follow the conventions already established in the code. - **Spacing**:
- Use tabs for indentation. No spaces. + Use tabs for indentation. Spaces for alignment. - **Naming**:
Keep variable and method names concise and descriptive. - **Quotes**:
Single-quoted strings are preferred to double-quoted strings - + - **Comments**:
- Please use single-line comments to annotate significant additions. Use `#` for comments in PHP; `//` for comments in JS and CSS. - -Merge your changes when the forked branch has been updated in the meanwhile. Make sure your code is 100% working before creating a Pull-Request on GitHub. + Please use single-line comments to annotate significant additions. Use `//` for comments in PHP, JS and CSS. + +Merge your changes when the forked branch has been updated in the meanwhile. Make sure your code is 100% working before creating a Pull-Request on GitHub. \ No newline at end of file From 0b5d605860b2aeb540925dec598cc6fa38ad4f1a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 13:53:32 +0100 Subject: [PATCH 060/183] Removed unused function --- php/Modules/Validator.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/php/Modules/Validator.php b/php/Modules/Validator.php index 6aee728..759969a 100644 --- a/php/Modules/Validator.php +++ b/php/Modules/Validator.php @@ -12,20 +12,6 @@ final class Validator { } - public static function isNull() { - - $args = func_get_args(); - - for ($i = 0; $i < count($args); $i++) { - - if (is_null($args[$i])===true) return true; - - } - - return false; - - } - public static function isAlbumIDs($albumIDs) { return (preg_match('/^[0-9\,]{1,}$/', $albumIDs)===1 ? true : false); From 34839d38052945d4ce6378269665c8bdf4d93617 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 13:55:23 +0100 Subject: [PATCH 061/183] Added error handling to getGraphHeader --- php/helpers/getGraphHeader.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/php/helpers/getGraphHeader.php b/php/helpers/getGraphHeader.php index e601fcc..8843a96 100644 --- a/php/helpers/getGraphHeader.php +++ b/php/helpers/getGraphHeader.php @@ -10,9 +10,18 @@ function getGraphHeader($photoID) { $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); $result = Database::get()->query($query); - $row = $result->fetch_object(); - if (!$result||!$row) return false; + if ($result===false) { + Log::error(__METHOD__, __LINE__, Database::get()->error); + return false; + } + + $row = $result->fetch_object(); + + if ($row===null) { + Log::error(__METHOD__, __LINE__, 'Could not find photo in database'); + return false; + } if ($row->medium==='1') $dir = 'medium'; else $dir = 'big'; From 64e0d66d83760e6710e11706f85b82162e769ee6 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 15:44:54 +0100 Subject: [PATCH 062/183] Improved if conditions --- php/Modules/Album.php | 33 ++++++++++-------- php/Modules/Database.php | 64 ++++++++++++++++++++-------------- php/Modules/Log.php | 2 +- php/Modules/Photo.php | 50 ++++++++++++++------------ php/Modules/Settings.php | 2 +- php/database/update_020700.php | 9 ++--- php/database/update_030000.php | 18 +++++----- php/database/update_030001.php | 10 +++--- php/database/update_030003.php | 2 +- 9 files changed, 106 insertions(+), 84 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index fa38eb0..57620ea 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -37,7 +37,7 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -191,9 +191,10 @@ final class Album { // Execute query $albums = Database::get()->query($query); - if (!$albums) { - Log::error(__METHOD__, __LINE__, 'Could not get all albums (' . Database::get()->error . ')'); - exit('Error: ' . Database::get()->error); + + if ($albums===false) { + Log::error(__METHOD__, __LINE__, 'Could not get albums from database (' . Database::get()->error . ')'); + exit('Error: Could not get albums from database!'); } // For each album @@ -210,6 +211,11 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); $thumbs = Database::get()->query($query); + if ($thumbs===false) { + Log::error(__METHOD__, __LINE__, 'Could not get thumbs of album from database (' . Database::get()->error . ')'); + exit('Error: Could not get thumbs of album from database!'); + } + // For each thumb $k = 0; while ($thumb = $thumbs->fetch_object()) { @@ -368,8 +374,7 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); $album = Database::get()->query($query); - // Error in database query - if (!$album) { + if ($album===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -484,7 +489,7 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -507,7 +512,7 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -577,7 +582,7 @@ final class Album { // Set public $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); $result = Database::get()->query($query); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -586,7 +591,7 @@ final class Album { if ($public===1) { $query = Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); $result = Database::get()->query($query); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -633,7 +638,7 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -681,7 +686,7 @@ final class Album { $query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); $result = Database::get()->query($query); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -696,7 +701,7 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -735,7 +740,7 @@ final class Album { Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($error) return false; - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } diff --git a/php/Modules/Database.php b/php/Modules/Database.php index bac8126..eec4be8 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -99,13 +99,13 @@ final class Database { Validator::required(isset($connection), __METHOD__); // Check if database exists - if ($connection->select_db($name)) return true; + if ($connection->select_db($name)===true) return true; // Create database $query = self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); $result = $connection->query($query); - if (!$connection->select_db($name)) return false; + if ($connection->select_db($name)===false) return false; return true; } @@ -120,37 +120,41 @@ final class Database { if ($connection->query($query)) return true; // Create log - $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); - if (!$connection->query($exist)) { + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); + $result = $connection->query($exist); + if ($result===false) { // Read file $file = __DIR__ . '/../database/log_table.sql'; $query = @file_get_contents($file); - if (!isset($query)||$query===false) return false; + if ($query===false) return false; // Create table - $query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG)); - if (!$connection->query($query)) return false; + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG)); + $result = $connection->query($exist); + if ($result===false) return false; } // Create settings - $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); - if (!$connection->query($exist)) { + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($exist); + if ($result===false) { // Read file $file = __DIR__ . '/../database/settings_table.sql'; $query = @file_get_contents($file); - if (!isset($query)||$query===false) { + if ($query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_settings'); return false; } // Create table - $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); - if (!$connection->query($query)) { + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($exist); + if ($result===false) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } @@ -159,14 +163,15 @@ final class Database { $file = __DIR__ . '/../database/settings_content.sql'; $query = @file_get_contents($file); - if (!isset($query)||$query===false) { + if ($query===false) { Log::error(__METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); return false; } // Add content - $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); - if (!$connection->query($query)) { + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); + $result = $connection->query($exist); + if ($result===false) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } @@ -174,7 +179,8 @@ final class Database { // Generate identifier $identifier = md5(microtime(true)); $query = self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); - if (!$connection->query($query)) { + $result = $connection->query($exist); + if ($result===false) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } @@ -182,21 +188,23 @@ final class Database { } // Create albums - $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); - if (!$connection->query($exist)) { + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); + $result = $connection->query($exist); + if ($result===false) { // Read file $file = __DIR__ . '/../database/albums_table.sql'; $query = @file_get_contents($file); - if (!isset($query)||$query===false) { + if ($query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_albums'); return false; } // Create table - $query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS)); - if (!$connection->query($query)) { + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS)); + $result = $connection->query($exist); + if ($result===false) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } @@ -204,21 +212,23 @@ final class Database { } // Create photos - $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); - if (!$connection->query($exist)) { + $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); + $result = $connection->query($exist); + if ($result===false) { // Read file $file = __DIR__ . '/../database/photos_table.sql'; $query = @file_get_contents($file); - if (!isset($query)||$query===false) { + if ($query===false) { Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_photos'); return false; } // Create table - $query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS)); - if (!$connection->query($query)) { + $query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS)); + $result = $connection->query($exist); + if ($result===false) { Log::error(__METHOD__, __LINE__, $connection->error); return false; } @@ -261,7 +271,7 @@ final class Database { $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } diff --git a/php/Modules/Log.php b/php/Modules/Log.php index de49453..55c4a90 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -34,7 +34,7 @@ final class Log { $query = Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); $result = Database::get()->query($query); - if (!$result) return false; + if ($result===false) return false; return true; } diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index c677007..9f747f5 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -237,7 +237,7 @@ final class Photo { $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); $result = Database::get()->query($query); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); if ($returnOnError===true) return false; exit('Error: Could not save photo in database!'); @@ -260,8 +260,8 @@ final class Photo { $result = Database::get()->query($query); - if (!$result) { - Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum'); + if ($result===false) { + Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum (' . Database::get()->error . ')'); return false; } @@ -800,14 +800,15 @@ final class Photo { // Get photo $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); - // Error in database query - if (!$photos) { + if ($photos===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } + // Get photo object + $photo = $photos->fetch_object(); + // Photo not found if ($photo===null) { Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); @@ -870,7 +871,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -900,7 +901,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -935,9 +936,10 @@ final class Photo { $star = ($photo->star==0 ? 1 : 0); // Set star - $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); - $star = Database::get()->query($query); - if (!$star) $error = true; + $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); + $result = Database::get()->query($query); + + if ($result===false) $error = true; } @@ -1028,7 +1030,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1056,7 +1058,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1090,7 +1092,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if (!$result) { + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1114,7 +1116,8 @@ final class Photo { // Get photos $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::get()->query($query); - if (!$photos) { + + if ($photos===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1127,10 +1130,11 @@ final class Photo { while(strlen($id)<14) $id .= 0; // Duplicate entry - $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); - $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); - $duplicate = Database::get()->query($query); - if (!$duplicate) { + $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); + $result = Database::get()->query($query); + + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1157,7 +1161,8 @@ final class Photo { // Get photos $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::get()->query($query); - if (!$photos) { + + if ($photos===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } @@ -1201,8 +1206,9 @@ final class Photo { // Delete db entry $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); - $delete = Database::get()->query($query); - if (!$delete) { + $result = Database::get()->query($query); + + if ($result===false) { Log::error(__METHOD__, __LINE__, Database::get()->error); return false; } diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index 9d22d99..17cef65 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -45,7 +45,7 @@ final class Settings { $result = Database::get()->query($query); - if (!$result) return false; + if ($result===false) return false; return true; } diff --git a/php/database/update_020700.php b/php/database/update_020700.php index ea87e45..5720970 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -9,11 +9,12 @@ use Lychee\Modules\Database; if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Add medium to photos -$query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); -if (!$connection->query($query)) { +$query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); +$result = $connection->query($query); +if ($result===false) { $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } @@ -33,7 +34,7 @@ $result = $connection->query($query); if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } diff --git a/php/database/update_030000.php b/php/database/update_030000.php index 2062203..1600659 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -10,24 +10,24 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Remove login // Login now saved as crypt without md5. Legacy code has been removed. -$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$resetUsername = $connection->query($query); -if (!$resetUsername) { +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); +if ($result===false) { Log::error('update_030000', __LINE__, 'Could not reset username (' . $connection->error . ')'); return false; } -$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$resetPassword = $connection->query($query); -if (!$resetPassword) { +$query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); +$result = $connection->query($query); +if ($result===false) { Log::error('update_030000', __LINE__, 'Could not reset password (' . $connection->error . ')'); return false; } // Make public albums private and reset password // Password now saved as crypt without md5. Legacy code has been removed. -$query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); -$resetPublic = $connection->query($query); -if (!$resetPublic) { +$query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); +$result = $connection->query($query); +if ($result===false) { Log::error('update_030000', __LINE__, 'Could not reset public albums (' . $connection->error . ')'); return false; } diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 575f02c..932effb 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -11,7 +11,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Change length of photo title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); $result = $connection->query($query); -if (!$result) { +if ($result===false) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } @@ -19,7 +19,7 @@ if (!$result) { // Change length of album title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); $result = $connection->query($query); -if (!$result) { +if ($result===false) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } @@ -30,7 +30,7 @@ $result = $connection->query($query); if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } @@ -39,7 +39,7 @@ if ($result->num_rows===0) { // Rename sorting to sortingPhotos $query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = $connection->query($query); -if (!$result) { +if ($result===false) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } @@ -51,7 +51,7 @@ if ($result->num_rows===0) { $identifier = md5(microtime(true)); $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } diff --git a/php/database/update_030003.php b/php/database/update_030003.php index d204ad5..8145323 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -14,7 +14,7 @@ $result = $connection->query($query); if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); $result = $connection->query($query); - if (!$result) { + if ($result===false) { Log::error('update_030003', __LINE__, 'Could not update database (' . $connection->error . ')'); return false; } From f650de8967b937b02e47286dbb7e63e735363f2b Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 15:53:44 +0100 Subject: [PATCH 063/183] Removed newline at end of file --- php/Access/Admin.php | 4 +++- php/Access/Guest.php | 2 +- php/Modules/Album.php | 2 +- php/Modules/Config.php | 2 +- php/Modules/Database.php | 2 +- php/Modules/Import.php | 2 +- php/Modules/Photo.php | 2 +- php/Modules/Validator.php | 2 +- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index fe84782..2a5b3f5 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -336,4 +336,6 @@ final class Admin extends Access { } -} \ No newline at end of file +} + +?> \ No newline at end of file diff --git a/php/Access/Guest.php b/php/Access/Guest.php index e8e2c9c..de30713 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -179,4 +179,4 @@ final class Guest extends Access { } -?> +?> \ No newline at end of file diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 57620ea..ead3348 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -750,4 +750,4 @@ final class Album { } -?> +?> \ No newline at end of file diff --git a/php/Modules/Config.php b/php/Modules/Config.php index 060b1df..8ce5dc5 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -65,4 +65,4 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); } -?> +?> \ No newline at end of file diff --git a/php/Modules/Database.php b/php/Modules/Database.php index eec4be8..7659fbb 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -346,4 +346,4 @@ final class Database { } -?> +?> \ No newline at end of file diff --git a/php/Modules/Import.php b/php/Modules/Import.php index 886e83b..17b73b4 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -180,4 +180,4 @@ final class Import { } -?> +?> \ No newline at end of file diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 9f747f5..1423b6d 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -1224,4 +1224,4 @@ final class Photo { } -?> +?> \ No newline at end of file diff --git a/php/Modules/Validator.php b/php/Modules/Validator.php index 759969a..c20e598 100644 --- a/php/Modules/Validator.php +++ b/php/Modules/Validator.php @@ -38,4 +38,4 @@ final class Validator { } -?> +?> \ No newline at end of file From 83e3271f434b286ea090f303addc3ce3a2413115 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 17:51:17 +0100 Subject: [PATCH 064/183] Code style adjustment --- src/scripts/photo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index 5ca7bac..a636938 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -553,7 +553,7 @@ photo.editTags = function(photoIDs) { photo.setTags = function(photoIDs, tags) { if (!photoIDs) return false - if (photoIDs instanceof Array===false) photoIDs = [photoIDs] + if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] // Parse tags tags = tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g, ',') From 7dc4e01313126bf29bb34a95d86f7868a0668cad Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 17:51:42 +0100 Subject: [PATCH 065/183] Fixed missing params var when Album::add returns and error --- src/scripts/album.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 6f3a9b7..0eeb637 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -112,7 +112,11 @@ album.add = function() { if (title.length===0) title = 'Untitled' - api.post('Album::add', { title }, function(data) { + let params = { + title + } + + api.post('Album::add', params, function(data) { // Avoid first album to be true if (data===true) data = 1 From 7b86a737af15b0a34a3b376cae4b503632838d07 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 18:49:31 +0100 Subject: [PATCH 066/183] Added Database::execute to run a query Database::execute automatically logs errors --- php/Modules/Album.php | 177 +++++++++++++++---------------- php/Modules/Database.php | 124 +++++++++++++--------- php/Modules/Import.php | 20 ++-- php/Modules/Log.php | 20 ++-- php/Modules/Photo.php | 187 ++++++++++++++++----------------- php/Modules/Settings.php | 31 ++---- php/database/update_020700.php | 30 +++--- php/database/update_030000.php | 25 ++--- php/database/update_030001.php | 54 +++++----- php/database/update_030003.php | 15 +-- php/helpers/getGraphHeader.php | 9 +- php/helpers/search.php | 12 ++- 12 files changed, 353 insertions(+), 351 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index ead3348..9007032 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -32,15 +32,12 @@ final class Album { // Database $sysstamp = time(); $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return Database::get()->insert_id; } @@ -111,7 +108,7 @@ final class Album { default: $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $return = $albums->fetch_assoc(); $return = Album::prepareData($return); $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); @@ -120,8 +117,11 @@ final class Album { } // Get photos - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $previousPhotoID = ''; + + if ($photos===false) exit('Error: Could not get photos of album from database!'); + while ($photo = $photos->fetch_assoc()) { // Turn data from the database into a front-end friendly format @@ -190,12 +190,9 @@ final class Album { else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); // Execute query - $albums = Database::get()->query($query); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($albums===false) { - Log::error(__METHOD__, __LINE__, 'Could not get albums from database (' . Database::get()->error . ')'); - exit('Error: Could not get albums from database!'); - } + if ($albums===false) exit('Error: Could not get albums from database!'); // For each album while ($album = $albums->fetch_assoc()) { @@ -209,12 +206,9 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::get()->query($query); + $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($thumbs===false) { - Log::error(__METHOD__, __LINE__, 'Could not get thumbs of album from database (' . Database::get()->error . ')'); - exit('Error: Could not get thumbs of album from database!'); - } + if ($thumbs===false) exit('Error: Could not get thumbs of album from database!'); // For each thumb $k = 0; @@ -255,9 +249,11 @@ final class Album { */ $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $unsorted = Database::get()->query($query); + $unsorted = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; + if ($unsorted===false) exit('Error: Could not get unsorted photos from database!'); + $return['unsorted'] = array( 'thumbs' => array(), 'num' => $unsorted->num_rows @@ -275,9 +271,11 @@ final class Album { */ $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $starred = Database::get()->query($query); + $starred = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; + if ($starred===false) exit('Error: Could not get starred photos from database!'); + $return['starred'] = array( 'thumbs' => array(), 'num' => $starred->num_rows @@ -295,9 +293,11 @@ final class Album { */ $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $public = Database::get()->query($query); + $public = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; + if ($public===false) exit('Error: Could not get public photos from database!'); + $return['public'] = array( 'thumbs' => array(), 'num' => $public->num_rows @@ -315,9 +315,11 @@ final class Album { */ $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $recent = Database::get()->query($query); + $recent = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; + if ($recent===false) exit('Error: Could not get recent photos from database!'); + $return['recent'] = array( 'thumbs' => array(), 'num' => $recent->num_rows @@ -372,20 +374,17 @@ final class Album { if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $album = Database::get()->query($query); + $album = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($album===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($album===false) exit('Error: Could not get album from database!'); - // Fetch object + // Get album object $album = $album->fetch_object(); // Photo not found if ($album===null) { - Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); + exit('Error: Could not find specified album!'); } // Set title @@ -401,17 +400,19 @@ final class Album { // Create zip $zip = new ZipArchive(); if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { - Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive'); return false; } // Execute query - $photos = Database::get()->query($photos); + $photos = Database::execute(Database::get(), $photos, __METHOD__, __LINE__); + + if ($album===null) exit('Error: Could not get photos from database!'); // Check if album empty if ($photos->num_rows==0) { - Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive without images'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive without images'); + exit('Error: Could not create ZipArchive without images!'); } // Parse each path @@ -484,15 +485,12 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -507,15 +505,12 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -532,8 +527,12 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) return false; + + // Get album object + $album = $albums->fetch_object(); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); @@ -555,8 +554,12 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) return false; + + // Get album object + $album = $albums->fetch_object(); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); @@ -581,20 +584,18 @@ final class Album { // Set public $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs)); - $result = Database::get()->query($query); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($result===false) return false; // Reset permissions for photos if ($public===1) { + $query = Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $result = Database::get()->query($query); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($result===false) return false; + } // Call plugins @@ -602,7 +603,6 @@ final class Album { // Set password if (isset($password)&&strlen($password)>0) return $this->setPassword($password); - return true; } @@ -633,15 +633,12 @@ final class Album { } // Execute query - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -656,14 +653,19 @@ final class Album { // Execute query $query = Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $albums = Database::get()->query($query); - $album = $albums->fetch_object(); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) return false; + + // Get album object + $album = $albums->fetch_object(); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); + // Check if password is correct if ($album->password=='') return true; - else if ($album->password===crypt($password, $album->password)) return true; + if ($album->password===crypt($password, $album->password)) return true; return false; } @@ -684,27 +686,21 @@ final class Album { $albumID = $albumID[0]; $query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; // $albumIDs contains all IDs without the first albumID // Convert to string $filteredIDs = implode(',', $albumIDs); $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -718,32 +714,37 @@ final class Album { Plugins::get()->activate(__METHOD__, 0, func_get_args()); // Init vars - $error = false; + $photoIDs = array(); // Execute query $query = Database::prepare(Database::get(), "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs)); - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - // For each album delete photo - while ($row = $photos->fetch_object()) { + if ($photos===false) return false; - $photo = new Photo($row->id); - if (!$photo->delete($row->id)) $error = true; + // Only delete photos when albums contain photos + if ($photos->num_rows>0) { + + // Add each id to photoIDs + while ($row = $photos->fetch_object()) $photoIDs[] = $row->id; + + // Convert photoIDs to a string + $photoIDs = implode(',', $photoIDs); + + // Delete all photos + $photo = new Photo($photoIDs); + if ($photo->delete()!==true) return false; } // Delete albums $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($error) return false; - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 7659fbb..5177b75 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -87,8 +87,10 @@ final class Database { else @$connection->set_charset('utf8'); // Set unicode - $connection->query('SET NAMES utf8;'); + $query = 'SET NAMES utf8'; + $result = self::execute($connection, $query, null, null); + if ($result===false) return false; return true; } @@ -103,8 +105,9 @@ final class Database { // Create database $query = self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name)); - $result = $connection->query($query); + $result = self::execute($connection, $query, null, null); + if ($result===false) return false; if ($connection->select_db($name)===false) return false; return true; @@ -116,12 +119,14 @@ final class Database { Validator::required(isset($connection), __METHOD__); // Check if tables exist - $query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); - if ($connection->query($query)) return true; + $query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG)); + $result = self::execute($connection, $query, null, null); + if ($result!==false) return true; - // Create log + // Check if log table exists $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG)); - $result = $connection->query($exist); + $result = self::execute($connection, $exist, null, null); + if ($result===false) { // Read file @@ -132,14 +137,16 @@ final class Database { // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG)); - $result = $connection->query($exist); + $result = self::execute($connection, $query, null, null); + if ($result===false) return false; } - // Create settings + // Check if settings table exists $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($exist); + $result = self::execute($connection, $exist, __METHOD__, __LINE__); + if ($result===false) { // Read file @@ -147,49 +154,44 @@ final class Database { $query = @file_get_contents($file); if ($query===false) { - Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_settings'); + Log::error($connection, __METHOD__, __LINE__, 'Could not load query for lychee_settings'); return false; } // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($exist); - if ($result===false) { - Log::error(__METHOD__, __LINE__, $connection->error); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; // Read file $file = __DIR__ . '/../database/settings_content.sql'; $query = @file_get_contents($file); if ($query===false) { - Log::error(__METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); + Log::error($connection, __METHOD__, __LINE__, 'Could not load content-query for lychee_settings'); return false; } // Add content $query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($exist); - if ($result===false) { - Log::error(__METHOD__, __LINE__, $connection->error); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; // Generate identifier $identifier = md5(microtime(true)); $query = self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier)); - $result = $connection->query($exist); - if ($result===false) { - Log::error(__METHOD__, __LINE__, $connection->error); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; } - // Create albums + // Check if albums table exists $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS)); - $result = $connection->query($exist); + $result = self::execute($connection, $exist, __METHOD__, __LINE__); + if ($result===false) { // Read file @@ -197,23 +199,22 @@ final class Database { $query = @file_get_contents($file); if ($query===false) { - Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_albums'); + Log::error($connection, __METHOD__, __LINE__, 'Could not load query for lychee_albums'); return false; } // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS)); - $result = $connection->query($exist); - if ($result===false) { - Log::error(__METHOD__, __LINE__, $connection->error); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; } - // Create photos + // Check if photos table exists $exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS)); - $result = $connection->query($exist); + $result = self::execute($connection, $exist, __METHOD__, __LINE__); + if ($result===false) { // Read file @@ -221,17 +222,15 @@ final class Database { $query = @file_get_contents($file); if ($query===false) { - Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_photos'); + Log::error($connection, __METHOD__, __LINE__, 'Could not load query for lychee_photos'); return false; } // Create table $query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS)); - $result = $connection->query($exist); - if ($result===false) { - Log::error(__METHOD__, __LINE__, $connection->error); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; } @@ -245,9 +244,13 @@ final class Database { Validator::required(isset($connection, $dbName), __METHOD__); // Get current version - $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); - $results = $connection->query($query); - $current = $results->fetch_object()->value; + $query = self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS)); + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; + + // Extract current version + $current = $result->fetch_object()->value; // For each update foreach (self::$versions as $version) { @@ -270,11 +273,9 @@ final class Database { Validator::required(isset($connection), __METHOD__); $query = self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version)); - $result = $connection->query($query); - if ($result===false) { - Log::error(__METHOD__, __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = self::execute($connection, $query, __METHOD__, __LINE__); + + if ($result===false) return false; } @@ -294,7 +295,7 @@ final class Database { 'data' => count($data) ); - if (($num['data']-$num['placeholder'])<0) Log::notice(__METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); + if (($num['data']-$num['placeholder'])<0) Log::notice($connection, __METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.'); foreach ($data as $value) { @@ -344,6 +345,27 @@ final class Database { } + public static function execute($connection, $query, $function, $line) { + + // Check dependencies + Validator::required(isset($connection, $query), __METHOD__); + + // Only activate logging when $function and $line is set + $logging = ($function===null||$line===null ? false : true); + + // Execute query + $result = $connection->query($query); + + // Check if execution failed + if ($result===false) { + if ($logging===true) Log::error($connection, $function, $line, $connection->error); + return false; + } + + return $result; + + } + } ?> \ No newline at end of file diff --git a/php/Modules/Import.php b/php/Modules/Import.php index 17b73b4..37838ab 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -46,7 +46,7 @@ final class Import { $extension = getExtension($url); if (!in_array(strtolower($extension), Photo::$validExtensions, true)) { $error = true; - Log::error(__METHOD__, __LINE__, 'Photo format not supported (' . $url . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo format not supported (' . $url . ')'); continue; } @@ -54,7 +54,7 @@ final class Import { $type = @exif_imagetype($url); if (!in_array($type, Photo::$validTypes, true)) { $error = true; - Log::error(__METHOD__, __LINE__, 'Photo type not supported (' . $url . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo type not supported (' . $url . ')'); continue; } @@ -64,14 +64,14 @@ final class Import { if (@copy($url, $tmp_name)===false) { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')'); continue; } // Import photo if (!$this->photo($tmp_name, $albumID)) { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $tmp_name); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not import file (' . $tmp_name . ')'); continue; } @@ -92,7 +92,7 @@ final class Import { if (substr($path, -1)==='/') $path = substr($path, 0, -1); if (is_dir($path)===false) { - Log::error(__METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); return 'Error: Given path is not a directory!'; } @@ -100,7 +100,7 @@ final class Import { if ($path===LYCHEE_UPLOADS_BIG||($path . '/')===LYCHEE_UPLOADS_BIG|| $path===LYCHEE_UPLOADS_MEDIUM||($path . '/')===LYCHEE_UPLOADS_MEDIUM|| $path===LYCHEE_UPLOADS_THUMB||($path . '/')===LYCHEE_UPLOADS_THUMB) { - Log::error(__METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')'); return 'Error: Given path is a reserved path of Lychee!'; } @@ -122,7 +122,7 @@ final class Import { // the file may still be unreadable by the user if (!is_readable($file)) { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not read file or directory: ' . $file); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not read file or directory (' . $file . ')'); continue; } @@ -134,7 +134,7 @@ final class Import { if (!$this->photo($file, $albumID)) { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $file); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not import file (' . $file . ')'); continue; } @@ -148,7 +148,7 @@ final class Import { if ($newAlbumID===false) { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')'); continue; } @@ -156,7 +156,7 @@ final class Import { if ($import!==true&&$import!=='Notice: Import only contains albums!') { $error = true; - Log::error(__METHOD__, __LINE__, 'Could not import folder. Function returned warning.'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not import folder. Function returned warning.'); continue; } diff --git a/php/Modules/Log.php b/php/Modules/Log.php index 55c4a90..954e0ab 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -4,35 +4,35 @@ namespace Lychee\Modules; final class Log { - public static function notice($function, $line, $text = '') { + public static function notice($connection, $function, $line, $text = '') { - return Log::text('notice', $function, $line, $text); + return Log::text($connection, 'notice', $function, $line, $text); } - public static function warning($function, $line, $text = '') { + public static function warning($connection, $function, $line, $text = '') { - return Log::text('warning', $function, $line, $text); + return Log::text($connection, 'warning', $function, $line, $text); } - public static function error($function, $line, $text = '') { + public static function error($connection, $function, $line, $text = '') { - return Log::text('error', $function, $line, $text); + return Log::text($connection, 'error', $function, $line, $text); } - private static function text($type, $function, $line, $text = '') { + private static function text($connection, $type, $function, $line, $text = '') { // Check dependencies - Validator::required(isset($type, $function, $line, $text), __METHOD__); + Validator::required(isset($connection, $type, $function, $line, $text), __METHOD__); // Get time $sysstamp = time(); // Save in database - $query = Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); - $result = Database::get()->query($query); + $query = Database::prepare($connection, "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text)); + $result = Database::execute($connection, $query, null, null); if ($result===false) return false; return true; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 1423b6d..fbf7854 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -39,7 +39,7 @@ final class Photo { if (hasPermissions(LYCHEE_UPLOADS)===false|| hasPermissions(LYCHEE_UPLOADS_BIG)===false|| hasPermissions(LYCHEE_UPLOADS_THUMB)===false) { - Log::error(__METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); + Log::error(Database::get(), __METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); exit('Error: An upload-folder is missing or not readable and writable!'); } @@ -80,35 +80,35 @@ final class Photo { // Check if file exceeds the upload_max_filesize directive if ($file['error']===UPLOAD_ERR_INI_SIZE) { - Log::error(__METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); + Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); if ($returnOnError===true) return false; exit('Error: The uploaded file exceeds the upload_max_filesize directive in php.ini!'); } // Check if file was only partially uploaded if ($file['error']===UPLOAD_ERR_PARTIAL) { - Log::error(__METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); + Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); if ($returnOnError===true) return false; exit('Error: The uploaded file was only partially uploaded!'); } // Check if writing file to disk failed if ($file['error']===UPLOAD_ERR_CANT_WRITE) { - Log::error(__METHOD__, __LINE__, 'Failed to write photo to disk'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Failed to write photo to disk'); if ($returnOnError===true) return false; exit('Error: Failed to write photo to disk!'); } // Check if a extension stopped the file upload if ($file['error']===UPLOAD_ERR_EXTENSION) { - Log::error(__METHOD__, __LINE__, 'A PHP extension stopped the file upload'); + Log::error(Database::get(), __METHOD__, __LINE__, 'A PHP extension stopped the file upload'); if ($returnOnError===true) return false; exit('Error: A PHP extension stopped the file upload!'); } // Check if the upload was successful if ($file['error']!==UPLOAD_ERR_OK) { - Log::error(__METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); if ($returnOnError===true) return false; exit('Error: Upload failed!'); } @@ -116,7 +116,7 @@ final class Photo { // Verify extension $extension = getExtension($file['name']); if (!in_array(strtolower($extension), self::$validExtensions, true)) { - Log::error(__METHOD__, __LINE__, 'Photo format not supported'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo format not supported'); if ($returnOnError===true) return false; exit('Error: Photo format not supported!'); } @@ -124,7 +124,7 @@ final class Photo { // Verify image $type = @exif_imagetype($file['tmp_name']); if (!in_array($type, self::$validTypes, true)) { - Log::error(__METHOD__, __LINE__, 'Photo type not supported'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo type not supported'); if ($returnOnError===true) return false; exit('Error: Photo type not supported!'); } @@ -141,7 +141,7 @@ final class Photo { // Calculate checksum $checksum = sha1_file($tmp_name); if ($checksum===false) { - Log::error(__METHOD__, __LINE__, 'Could not calculate checksum for photo'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not calculate checksum for photo'); if ($returnOnError===true) return false; exit('Error: Could not calculate checksum for photo!'); } @@ -171,13 +171,13 @@ final class Photo { // Import if not uploaded via web if (!is_uploaded_file($tmp_name)) { if (!@copy($tmp_name, $path)) { - Log::error(__METHOD__, __LINE__, 'Could not copy photo to uploads'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not copy photo to uploads'); if ($returnOnError===true) return false; exit('Error: Could not copy photo to uploads!'); } else @unlink($tmp_name); } else { if (!@move_uploaded_file($tmp_name, $path)) { - Log::error(__METHOD__, __LINE__, 'Could not move photo to uploads'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not move photo to uploads'); if ($returnOnError===true) return false; exit('Error: Could not move photo to uploads!'); } @@ -188,7 +188,7 @@ final class Photo { // Photo already exists // Check if the user wants to skip duplicates if (Settings::get()['skipDuplicates']==='1') { - Log::notice(__METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); + Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); if ($returnOnError===true) return false; exit('Warning: This photo has been skipped because it\'s already in your library.'); } @@ -210,7 +210,7 @@ final class Photo { if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') { $adjustFile = $this->adjustFile($path, $info); if ($adjustFile!==false) $info = $adjustFile; - else Log::notice(__METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); + else Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); } // Set original date @@ -218,7 +218,7 @@ final class Photo { // Create Thumb if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { - Log::error(__METHOD__, __LINE__, 'Could not create thumbnail for photo'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create thumbnail for photo'); if ($returnOnError===true) return false; exit('Error: Could not create thumbnail for photo!'); } @@ -235,10 +235,9 @@ final class Photo { // Save to DB $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); if ($returnOnError===true) return false; exit('Error: Could not save photo in database!'); } @@ -258,12 +257,9 @@ final class Photo { if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($result===false) { - Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum (' . Database::get()->error . ')'); - return false; - } + if ($result===false) return false; if ($result->num_rows===1) { @@ -343,7 +339,7 @@ final class Photo { case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; case 'image/png': $sourceImg = imagecreatefrompng($url); break; case 'image/gif': $sourceImg = imagecreatefromgif($url); break; - default: Log::error(__METHOD__, __LINE__, 'Type of photo is not supported'); + default: Log::error(Database::get(), __METHOD__, __LINE__, 'Type of photo is not supported'); return false; break; } @@ -398,7 +394,7 @@ final class Photo { if (hasPermissions(LYCHEE_UPLOADS_MEDIUM)===false) { // Permissions are missing - Log::notice(__METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.'); + Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.'); $error = true; } @@ -423,7 +419,7 @@ final class Photo { // Save image try { $medium->writeImage($newUrl); } catch (ImagickException $err) { - Log::notice(__METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); + Log::notice(Database::get(), __METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); $error = true; } @@ -636,8 +632,12 @@ final class Photo { // Get photo $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_assoc(); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($photos===false) exit('Error: Could not get photo from database!'); + + // Get photo object + $photo = $photos->fetch_assoc(); // Parse photo $photo['sysdate'] = date('d M. Y', substr($photo['id'], 0, -4)); @@ -659,8 +659,12 @@ final class Photo { // Get album $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); - $albums = Database::get()->query($query); - $album = $albums->fetch_assoc(); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) exit('Error: Could not get album of photo from database!'); + + // Get album object + $album = $albums->fetch_assoc(); // Parse album $photo['public'] = ($album['public']==='1' ? '2' : $photo['public']); @@ -799,26 +803,23 @@ final class Photo { // Get photo $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($photos===false) exit('Error: Could not get photo from database!'); // Get photo object $photo = $photos->fetch_object(); // Photo not found if ($photo===null) { - Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); + exit('Error: Could not find specified photo!'); } // Get extension $extension = getExtension($photo->url); if ($extension===false) { - Log::error(__METHOD__, __LINE__, 'Invalid photo extension'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Invalid photo extension'); return false; } @@ -866,15 +867,12 @@ final class Photo { // Set title $query = Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -896,15 +894,12 @@ final class Photo { // Set description $query = Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -927,7 +922,9 @@ final class Photo { // Get photos $query = Database::prepare(Database::get(), "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($photos===false) return false; // For each photo while ($photo = $photos->fetch_object()) { @@ -937,7 +934,7 @@ final class Photo { // Set star $query = Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); if ($result===false) $error = true; @@ -946,10 +943,7 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($error===true) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($error===true) return false; return true; } @@ -970,8 +964,12 @@ final class Photo { // Get photo $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($photos===false) return 0; + + // Get photo object + $photo = $photos->fetch_object(); // Check if public if ($photo->public==='1') { @@ -1017,23 +1015,24 @@ final class Photo { // Get public $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); - $photo = $photos->fetch_object(); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($photos===false) return false; + + // Get photo object + $photo = $photos->fetch_object(); // Invert public $public = ($photo->public==0 ? 1 : 0); // Set public $query = Database::prepare(Database::get(), "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -1053,15 +1052,12 @@ final class Photo { // Set album $query = Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -1087,15 +1083,12 @@ final class Photo { // Set tags $query = Database::prepare(Database::get(), "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; return true; } @@ -1113,14 +1106,14 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); + // Init vars + $error = false; + // Get photos $query = Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($photos===false) return false; // For each photo while ($photo = $photos->fetch_object()) { @@ -1132,15 +1125,13 @@ final class Photo { // Duplicate entry $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) $error = true; } + if ($error===true) return false; return true; } @@ -1158,14 +1149,14 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); + // Init vars + $error = false; + // Get photos $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); - $photos = Database::get()->query($query); + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($photos===false) return false; // For each photo while ($photo = $photos->fetch_object()) { @@ -1180,44 +1171,42 @@ final class Photo { // Delete big if (file_exists(LYCHEE_UPLOADS_BIG . $photo->url)&&!unlink(LYCHEE_UPLOADS_BIG . $photo->url)) { - Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/big/'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not delete photo in uploads/big/'); + $error = true; } // Delete medium if (file_exists(LYCHEE_UPLOADS_MEDIUM . $photo->url)&&!unlink(LYCHEE_UPLOADS_MEDIUM . $photo->url)) { - Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/medium/'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not delete photo in uploads/medium/'); + $error = true; } // Delete thumb if (file_exists(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)&&!unlink(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)) { - Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/'); + $error = true; } // Delete thumb@2x if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)) { - Log::error(__METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/'); - return false; + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/'); + $error = true; } } // Delete db entry $query = Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) $error = true; } // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); + if ($error===true) return false; return true; } diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index 17cef65..c3e1f1c 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -12,7 +12,7 @@ final class Settings { // Execute query $query = Database::prepare(Database::get(), "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS)); - $settings = Database::get()->query($query); + $settings = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Add each to return while ($setting = $settings->fetch_object()) $return[$setting->key] = $setting->value; @@ -43,7 +43,7 @@ final class Settings { } - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); if ($result===false) return false; return true; @@ -79,10 +79,7 @@ final class Settings { // Execute query // Do not prepare $username because it is hashed and save // Preparing (escaping) the username would destroy the hash - if (self::set('username', $username, true)===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if (self::set('username', $username, true)===false) return false; return true; } @@ -97,10 +94,7 @@ final class Settings { // Do not prepare $password because it is hashed and save // Preparing (escaping) the password would destroy the hash - if (self::set('password', $password, true)===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if (self::set('password', $password, true)===false) return false; return true; } @@ -108,14 +102,11 @@ final class Settings { public static function setDropboxKey($dropboxKey) { if (strlen($dropboxKey)<1||strlen($dropboxKey)>50) { - Log::notice(__METHOD__, __LINE__, 'Dropbox key is either too short or too long'); + Log::notice(Database::get(), __METHOD__, __LINE__, 'Dropbox key is either too short or too long'); return false; } - if (self::set('dropboxKey', $dropboxKey)===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if (self::set('dropboxKey', $dropboxKey)===false) return false; return true; } @@ -152,10 +143,7 @@ final class Settings { // Do not prepare $sorting because it is a true statement // Preparing (escaping) the sorting would destroy it // $sorting is save and can't contain user-input - if (self::set('sortingPhotos', $sorting, true)===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if (self::set('sortingPhotos', $sorting, true)===false) return false; return true; } @@ -189,10 +177,7 @@ final class Settings { // Do not prepare $sorting because it is a true statement // Preparing (escaping) the sorting would destroy it // $sorting is save and can't contain user-input - if (self::set('sortingAlbums', $sorting, true)===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if (self::set('sortingAlbums', $sorting, true)===false) return false; return true; } diff --git a/php/database/update_020700.php b/php/database/update_020700.php index 5720970..d59ea7f 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -10,34 +10,38 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Add medium to photos $query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); -$result = $connection->query($query); +$result = Database::execute($connection, $query, 'update_020700', __LINE__); + if ($result===false) { + $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); - $result = $connection->query($query); - if ($result===false) { - Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = Database::execute($connection, $query, 'update_020700', __LINE__); + + if ($result===false) return false; + } // Create medium folder if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) { + // Only create the folder when it is missing if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false) { - Log::error('update_020700', __LINE__, 'Could not create medium-folder'); + Log::error($connection, 'update_020700', __LINE__, 'Could not create medium-folder'); } + } // Add medium to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +$result = Database::execute($connection, $query, 'update_020700', __LINE__); + if ($result->num_rows===0) { + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); - if ($result===false) { - Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = Database::execute($connection, $query, 'update_020700', __LINE__); + + if ($result===false) return false; + } // Set version diff --git a/php/database/update_030000.php b/php/database/update_030000.php index 1600659..3557be3 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -11,26 +11,21 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Remove login // Login now saved as crypt without md5. Legacy code has been removed. $query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030000', __LINE__, 'Could not reset username (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030000', __LINE__); + +if ($result===false) return false; + $query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030000', __LINE__, 'Could not reset password (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030000', __LINE__); + +if ($result===false) return false; // Make public albums private and reset password // Password now saved as crypt without md5. Legacy code has been removed. $query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030000', __LINE__, 'Could not reset public albums (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030000', __LINE__); + +if ($result===false) return false; // Set version if (Database::setVersion($connection, '030000')===false) return false; diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 932effb..9193fef 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -10,51 +10,51 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Change length of photo title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030001', __LINE__); + +if ($result===false) return false; // Change length of album title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030001', __LINE__); + +if ($result===false) return false; // Add album sorting to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +$result = Database::execute($connection, $query, 'update_030001', __LINE__); + +if ($result===false) return false; + if ($result->num_rows===0) { + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); - if ($result===false) { - Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = Database::execute($connection, $query, 'update_030001', __LINE__); + + if ($result===false) return false; + } // Rename sorting to sortingPhotos $query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); -if ($result===false) { - Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; -} +$result = Database::execute($connection, $query, 'update_030001', __LINE__); + +if ($result===false) return false; // Add identifier to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +$result = Database::execute($connection, $query, 'update_030001', __LINE__); + +if ($result===false) return false; + if ($result->num_rows===0) { + $identifier = md5(microtime(true)); $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); - $result = $connection->query($query); - if ($result===false) { - Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = Database::execute($connection, $query, 'update_030001', __LINE__); + + if ($result===false) return false; + } // Set version diff --git a/php/database/update_030003.php b/php/database/update_030003.php index 8145323..95876d1 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -10,14 +10,17 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); // Add skipDuplicates to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = $connection->query($query); +$result = Database::execute($connection, $query, 'update_030003', __LINE__); + +if ($result===false) return false; + if ($result->num_rows===0) { + $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); - $result = $connection->query($query); - if ($result===false) { - Log::error('update_030003', __LINE__, 'Could not update database (' . $connection->error . ')'); - return false; - } + $result = Database::execute($connection, $query, 'update_030003', __LINE__); + + if ($result===false) return false; + } // Set version diff --git a/php/helpers/getGraphHeader.php b/php/helpers/getGraphHeader.php index 8843a96..77e48a7 100644 --- a/php/helpers/getGraphHeader.php +++ b/php/helpers/getGraphHeader.php @@ -9,17 +9,14 @@ function getGraphHeader($photoID) { if ($photo->getPublic('')===false) return false; $query = Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($result===false) { - Log::error(__METHOD__, __LINE__, Database::get()->error); - return false; - } + if ($result===false) return false; $row = $result->fetch_object(); if ($row===null) { - Log::error(__METHOD__, __LINE__, 'Could not find photo in database'); + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find photo in database'); return false; } diff --git a/php/helpers/search.php b/php/helpers/search.php index 6b17fd9..75b46b0 100755 --- a/php/helpers/search.php +++ b/php/helpers/search.php @@ -18,7 +18,9 @@ function search($term) { */ $query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($result===false) return false; while($photo = $result->fetch_assoc()) { @@ -32,7 +34,9 @@ function search($term) { */ $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term)); - $result = Database::get()->query($query); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($result===false) return false; while($album = $result->fetch_assoc()) { @@ -41,7 +45,9 @@ function search($term) { // Thumbs $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::get()->query($query); + $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($thumbs===false) return false; // For each thumb $k = 0; From 861c010cb722e23846539819f4bd9922a592fa0a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 31 Jan 2016 19:19:03 +0100 Subject: [PATCH 067/183] Rebuild --- dist/main.js | Bin 192604 -> 192607 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index fb1b9858be5599778086302b0d507decbb98683a..ae6dcd81bebd31692233c09c4b8184c18d8fddcd 100644 GIT binary patch delta 77 zcmV-T0J8tw;0xd23xKo%@F5I&^(IVQ^_KaBp*TC?Y{@Vs&jg jI$>mFA}nv01I7Vgmu<}f2bZ7E0T+jb#sRm5#sb$V>Pa6u delta 74 zcmV-Q0JZ<$;0xT~3xKo%VQ^_KaBp*TC?Y{@Vs&jgI$>mFA}o7!X>@F5I&^)P g3&sIomk4(P440zM0T-9RbOHp2jK%@CjK%`fDR)L4l>h($ From c4c2e9169edd8820f101dfab3ed0b3a125d97a7a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 1 Feb 2016 09:44:23 +0100 Subject: [PATCH 068/183] Removed thumb quality setting --- docs/Settings.md | 6 ------ php/Modules/Photo.php | 9 ++++++--- php/Modules/Session.php | 1 - php/database/settings_content.sql | 1 - plugins/Diagnostics/index.php | 1 - 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/Settings.md b/docs/Settings.md index b91c0f4..6bcd95f 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -22,12 +22,6 @@ All settings are stored in the database. You can change the properties manually, Your photos and albums are protected by a username and password. If both rows are empty, Lychee will prompt you to set them. -#### Thumb Quality - - thumbQuality = [0-100] - -Less means an inferiority quality of your thumbs, but faster loading. More means a better quality of your thumbs, but slower loading. The default value is 90. The allowed values are between 0 and 100. - #### Check For Updates checkForUpdates = [0|1] diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index fbf7854..e47712b 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -285,6 +285,9 @@ final class Photo { // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); + // Quality of thumbnails + $thumbQuality = 90; + // Size of the thumbnail $newWidth = 200; $newHeight = 200; @@ -299,7 +302,7 @@ final class Photo { // Read image $thumb = new Imagick(); $thumb->readImage($url); - $thumb->setImageCompressionQuality(Settings::get()['thumbQuality']); + $thumb->setImageCompressionQuality($thumbQuality); $thumb->setImageFormat('jpeg'); // Copy image for 2nd thumb version @@ -346,12 +349,12 @@ final class Photo { // Create thumb fastImageCopyResampled($thumb, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth, $newHeight, $newSize, $newSize); - imagejpeg($thumb, $newUrl, Settings::get()['thumbQuality']); + imagejpeg($thumb, $newUrl, $thumbQuality); imagedestroy($thumb); // Create retina thumb fastImageCopyResampled($thumb2x, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth*2, $newHeight*2, $newSize, $newSize); - imagejpeg($thumb2x, $newUrl2x, Settings::get()['thumbQuality']); + imagejpeg($thumb2x, $newUrl2x, $thumbQuality); imagedestroy($thumb2x); // Free memory diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 94c4278..126fb28 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -42,7 +42,6 @@ final class Session { // Unset unused vars unset($return['config']['skipDuplicates']); - unset($return['config']['thumbQuality']); unset($return['config']['sortingAlbums']); unset($return['config']['sortingPhotos']); unset($return['config']['dropboxKey']); diff --git a/php/database/settings_content.sql b/php/database/settings_content.sql index 907e6c4..4074590 100644 --- a/php/database/settings_content.sql +++ b/php/database/settings_content.sql @@ -6,7 +6,6 @@ VALUES ('version',''), ('username',''), ('password',''), - ('thumbQuality','90'), ('checkForUpdates','1'), ('sortingPhotos','ORDER BY id DESC'), ('sortingAlbums','ORDER BY id DESC'), diff --git a/plugins/Diagnostics/index.php b/plugins/Diagnostics/index.php index 70a89ac..9369c4d 100644 --- a/plugins/Diagnostics/index.php +++ b/plugins/Diagnostics/index.php @@ -78,7 +78,6 @@ $settings = Settings::get(); # Settings if (!isset($settings['username'])||$settings['username']=='') $error .= ('Error: Username empty or not set in database' . PHP_EOL); if (!isset($settings['password'])||$settings['password']=='') $error .= ('Error: Password empty or not set in database' . PHP_EOL); -if (!isset($settings['thumbQuality'])||$settings['thumbQuality']=='') $error .= ('Error: No or wrong property for thumbQuality in database' . PHP_EOL); if (!isset($settings['sortingPhotos'])||$settings['sortingPhotos']=='') $error .= ('Error: Wrong property for sortingPhotos in database' . PHP_EOL); if (!isset($settings['sortingAlbums'])||$settings['sortingAlbums']=='') $error .= ('Error: Wrong property for sortingAlbums in database' . PHP_EOL); if (!isset($settings['plugins'])) $error .= ('Error: No property for plugins in database' . PHP_EOL); From 8d53d9e689c189e0eb33a840d84978c9af51d58f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 1 Feb 2016 09:49:05 +0100 Subject: [PATCH 069/183] Added "How to change the title of the site?" to the FAQ #455 --- docs/FAQ.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/FAQ.md b/docs/FAQ.md index d0764a4..5c1dadb 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -53,3 +53,6 @@ Yes. Lychee uses ImageMagick when available. #### Blank screen when viewing a photo using iOS There's a problem with images compressed by ImageOptim. [Read more.](https://github.com/electerious/Lychee/issues/175#issuecomment-47403992) + +#### How to change the title of the site? +[#455](https://github.com/electerious/Lychee/issues/455) \ No newline at end of file From 8edb9902131b67dd4575f1ece3f3e2151612e30a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 6 Feb 2016 23:23:10 +0100 Subject: [PATCH 070/183] Updated notice message --- php/Modules/Photo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index e47712b..6c0ac3c 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -422,7 +422,7 @@ final class Photo { // Save image try { $medium->writeImage($newUrl); } catch (ImagickException $err) { - Log::notice(Database::get(), __METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage()); + Log::notice(Database::get(), __METHOD__, __LINE__, 'Could not save medium-photo (' . $err->getMessage() . ')'); $error = true; } From be5bb7ee6efee2674c5dfcdbfc7c3dec45d5abd4 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 6 Feb 2016 23:23:25 +0100 Subject: [PATCH 071/183] Removed unused Log::warning --- php/Modules/Log.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/php/Modules/Log.php b/php/Modules/Log.php index 954e0ab..83408e7 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -10,12 +10,6 @@ final class Log { } - public static function warning($connection, $function, $line, $text = '') { - - return Log::text($connection, 'warning', $function, $line, $text); - - } - public static function error($connection, $function, $line, $text = '') { return Log::text($connection, 'error', $function, $line, $text); From 34f87367e369a362358561a6aa836deacb3330ad Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 6 Feb 2016 23:53:17 +0100 Subject: [PATCH 072/183] Updated code syntax of Log and Diagnostics --- plugins/Diagnostics/index.php | 135 +++++++++++++++++----------------- plugins/Log/index.php | 37 +++++----- 2 files changed, 85 insertions(+), 87 deletions(-) diff --git a/plugins/Diagnostics/index.php b/plugins/Diagnostics/index.php index 9369c4d..a17f428 100644 --- a/plugins/Diagnostics/index.php +++ b/plugins/Diagnostics/index.php @@ -1,11 +1,10 @@ server_version<50500) echo('Warning: Lychee uses the GBK charset to avoid sql injections on your MySQL version. Please update to MySQL 5.5 or higher to enable UTF-8 support.' . PHP_EOL); -# Output -if ($error==='') echo('No critical problems found. Lychee should work without problems!' . PHP_EOL); -else echo $error; +// Output +if ($error==='') echo('No critical problems found. Lychee should work without problems!' . PHP_EOL); +else echo $error; -# Show separator +// Show separator echo(PHP_EOL . PHP_EOL . 'System Information' . PHP_EOL); echo('------------------' . PHP_EOL); -# Ensure that user is logged in +// Ensure that user is logged in if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& (isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) { - # Load json + // Load json $json = file_get_contents(LYCHEE_SRC . 'package.json'); $json = json_decode($json, true); - # About imagick + // About imagick $imagick = extension_loaded('imagick'); - if ($imagick===true) $imagickVersion = @Imagick::getVersion(); - else $imagick = '-'; - if (!isset($imagickVersion, $imagickVersion['versionNumber'])||$imagickVersion==='') $imagickVersion = '-'; - else $imagickVersion = $imagickVersion['versionNumber']; + if ($imagick===true) $imagickVersion = @Imagick::getVersion(); + else $imagick = '-'; + if (!isset($imagickVersion, $imagickVersion['versionNumber'])||$imagickVersion==='') $imagickVersion = '-'; + else $imagickVersion = $imagickVersion['versionNumber']; - # Output system information + // Output system information echo('Lychee Version: ' . $json['version'] . PHP_EOL); echo('DB Version: ' . $settings['version'] . PHP_EOL); echo('System: ' . PHP_OS . PHP_EOL); @@ -133,10 +132,10 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& } else { - # Don't go further if the user is not logged in + // Don't go further if the user is not logged in echo('You have to be logged in to see more information.'); exit(); } -?> +?> \ No newline at end of file diff --git a/plugins/Log/index.php b/plugins/Log/index.php index 1ff92c6..b20da7e 100644 --- a/plugins/Log/index.php +++ b/plugins/Log/index.php @@ -1,11 +1,10 @@ query($query); + // Result + $query = Database::prepare(Database::get(), "SELECT FROM_UNIXTIME(time), type, function, line, text FROM ?", array(LYCHEE_TABLE_LOG)); + $result = Database::get()->query($query); - # Output + // Output if ($result->num_rows===0) { echo('Everything looks fine, Lychee has not reported any problems!'); @@ -45,11 +44,11 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& while($row = $result->fetch_row()) { - # Encode result before printing + // Encode result before printing $row = array_map('htmlentities', $row); - # Format: time TZ - type - function(line) - text - printf ("%s - %s - %s (%s) \t- %s\n", $row[0], $row[1], $row[2], $row[3], $row[4]); + // Format: time TZ - type - function(line) - text + printf("%s - %s - %s (%s) \t- %s\n", $row[0], $row[1], $row[2], $row[3], $row[4]); } @@ -57,10 +56,10 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& } else { - # Don't go further if the user is not logged in + // Don't go further if the user is not logged in echo('You have to be logged in to see the log.'); exit(); } -?> +?> \ No newline at end of file From 87350448e0c2e40c5d52f21899cc764e3bd3e9a2 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 6 Feb 2016 23:54:21 +0100 Subject: [PATCH 073/183] Updated plugin docs with namespaces --- docs/Plugins.md | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/docs/Plugins.md b/docs/Plugins.md index e47a7ce..046c2f4 100644 --- a/docs/Plugins.md +++ b/docs/Plugins.md @@ -17,31 +17,41 @@ The plugin-system of Lychee allows you to execute scripts, when a certain action ```php action!=='Photo::add:before') return false; - # Do something when Photo::add:before gets called - # Database::get() => Database connection of Lychee - # Settings::get() => Settings of Lychee - # $subject->action => Called hook - # $subject->args => Params passed to the original function + /** + * Do something when Photo::add:before gets called + * Database::get() => Database connection of Lychee + * Settings::get() => Settings of Lychee + * $subject->action => Called hook + * $subject->args => Params passed to the original function + */ return true; @@ -54,9 +64,9 @@ class ExamplePlugin implements SplObserver { 3. Add the class name to the database of Lychee -Select the table `lychee_settings` and add the name of the class to the value of `plugins` (e.g. `ExamplePlugin`). Please ensure that the folder has the same name as the class and as the file. +Select the table `lychee_settings` and add the [external fully qualified name](http://php.net/manual/en/language.namespaces.importing.php) to the value of `plugins` (e.g. `ExamplePlugin\ExamplePlugin`). Please ensure that the folder has the same name as the namespace and the file the same name as the class. -Divide multiple plugins with semicolons: `ExamplePlugin;ExampleTwoPlugin`. +Divide multiple plugins with semicolons: `ExamplePlugin\ExamplePlugin;ExampleTwoPlugin\ExampleTwoPlugin`. ### Available hooks From 64a7972cb5f8391416dd7f869e20273a2f504990 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 7 Feb 2016 00:12:28 +0100 Subject: [PATCH 074/183] Replaced echo with exit --- plugins/Diagnostics/index.php | 3 +-- plugins/Log/index.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/Diagnostics/index.php b/plugins/Diagnostics/index.php index a17f428..3e7124b 100644 --- a/plugins/Diagnostics/index.php +++ b/plugins/Diagnostics/index.php @@ -133,8 +133,7 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& } else { // Don't go further if the user is not logged in - echo('You have to be logged in to see more information.'); - exit(); + exit('You have to be logged in to see more information.'); } diff --git a/plugins/Log/index.php b/plugins/Log/index.php index b20da7e..4964eb5 100644 --- a/plugins/Log/index.php +++ b/plugins/Log/index.php @@ -57,8 +57,7 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&& } else { // Don't go further if the user is not logged in - echo('You have to be logged in to see the log.'); - exit(); + exit('You have to be logged in to see the log.'); } From f4e909895f6daa24bac9bf6695539c50dfe2c169 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 7 Feb 2016 00:16:48 +0100 Subject: [PATCH 075/183] Added Response class to handle exit() responses --- php/Modules/Album.php | 22 +++++++++++----------- php/Modules/Config.php | 2 +- php/Modules/Database.php | 10 +++++----- php/Modules/Photo.php | 36 ++++++++++++++++++------------------ php/Modules/Response.php | 25 +++++++++++++++++++++++++ php/Modules/Settings.php | 14 +++++++------- php/Modules/Validator.php | 2 +- php/index.php | 11 ++++++----- 8 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 php/Modules/Response.php diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 9007032..5537450 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -120,7 +120,7 @@ final class Album { $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $previousPhotoID = ''; - if ($photos===false) exit('Error: Could not get photos of album from database!'); + if ($photos===false) Response::error('Could not get photos of album from database!'); while ($photo = $photos->fetch_assoc()) { @@ -192,7 +192,7 @@ final class Album { // Execute query $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($albums===false) exit('Error: Could not get albums from database!'); + if ($albums===false) Response::error('Could not get albums from database!'); // For each album while ($album = $albums->fetch_assoc()) { @@ -208,7 +208,7 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($thumbs===false) exit('Error: Could not get thumbs of album from database!'); + if ($thumbs===false) Response::error('Could not get thumbs of album from database!'); // For each thumb $k = 0; @@ -252,7 +252,7 @@ final class Album { $unsorted = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($unsorted===false) exit('Error: Could not get unsorted photos from database!'); + if ($unsorted===false) Response::error('Could not get unsorted photos from database!'); $return['unsorted'] = array( 'thumbs' => array(), @@ -274,7 +274,7 @@ final class Album { $starred = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($starred===false) exit('Error: Could not get starred photos from database!'); + if ($starred===false) Response::error('Could not get starred photos from database!'); $return['starred'] = array( 'thumbs' => array(), @@ -296,7 +296,7 @@ final class Album { $public = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($public===false) exit('Error: Could not get public photos from database!'); + if ($public===false) Response::error('Could not get public photos from database!'); $return['public'] = array( 'thumbs' => array(), @@ -318,7 +318,7 @@ final class Album { $recent = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($recent===false) exit('Error: Could not get recent photos from database!'); + if ($recent===false) Response::error('Could not get recent photos from database!'); $return['recent'] = array( 'thumbs' => array(), @@ -376,7 +376,7 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); $album = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($album===false) exit('Error: Could not get album from database!'); + if ($album===false) Response::error('Could not get album from database!'); // Get album object $album = $album->fetch_object(); @@ -384,7 +384,7 @@ final class Album { // Photo not found if ($album===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); - exit('Error: Could not find specified album!'); + Response::error('Could not find specified album!'); } // Set title @@ -407,12 +407,12 @@ final class Album { // Execute query $photos = Database::execute(Database::get(), $photos, __METHOD__, __LINE__); - if ($album===null) exit('Error: Could not get photos from database!'); + if ($album===null) Response::error('Could not get photos from database!'); // Check if album empty if ($photos->num_rows==0) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive without images'); - exit('Error: Could not create ZipArchive without images!'); + Response::error('Could not create ZipArchive without images!'); } // Parse each path diff --git a/php/Modules/Config.php b/php/Modules/Config.php index 8ce5dc5..d7f3914 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -25,7 +25,7 @@ final class Config { // Save config.php $config = "connect_error); + if ($connection===false) Response::error('' . $connection->connect_error); - if (!self::setCharset($connection)) exit('Error: Could not set database charset!'); + if (!self::setCharset($connection)) Response::error('Could not set database charset!'); // Create database - if (!self::createDatabase($connection, $name)) exit('Error: Could not create database!'); + if (!self::createDatabase($connection, $name)) Response::error('Could not create database!'); // Create tables - if (!self::createTables($connection)) exit('Error: Could not create tables!'); + if (!self::createTables($connection)) Response::error('Could not create tables!'); // Update database - if (!self::update($connection, $name)) exit('Error: Could not update database and tables!'); + if (!self::update($connection, $name)) Response::error('Could not update database and tables!'); $this->connection = $connection; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 6c0ac3c..59d23e9 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -40,7 +40,7 @@ final class Photo { hasPermissions(LYCHEE_UPLOADS_BIG)===false|| hasPermissions(LYCHEE_UPLOADS_THUMB)===false) { Log::error(Database::get(), __METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); - exit('Error: An upload-folder is missing or not readable and writable!'); + Response::error('An upload-folder is missing or not readable and writable!'); } // Call plugins @@ -82,35 +82,35 @@ final class Photo { if ($file['error']===UPLOAD_ERR_INI_SIZE) { Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); if ($returnOnError===true) return false; - exit('Error: The uploaded file exceeds the upload_max_filesize directive in php.ini!'); + Response::error('The uploaded file exceeds the upload_max_filesize directive in php.ini!'); } // Check if file was only partially uploaded if ($file['error']===UPLOAD_ERR_PARTIAL) { Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); if ($returnOnError===true) return false; - exit('Error: The uploaded file was only partially uploaded!'); + Response::error('The uploaded file was only partially uploaded!'); } // Check if writing file to disk failed if ($file['error']===UPLOAD_ERR_CANT_WRITE) { Log::error(Database::get(), __METHOD__, __LINE__, 'Failed to write photo to disk'); if ($returnOnError===true) return false; - exit('Error: Failed to write photo to disk!'); + Response::error('Failed to write photo to disk!'); } // Check if a extension stopped the file upload if ($file['error']===UPLOAD_ERR_EXTENSION) { Log::error(Database::get(), __METHOD__, __LINE__, 'A PHP extension stopped the file upload'); if ($returnOnError===true) return false; - exit('Error: A PHP extension stopped the file upload!'); + Response::error('A PHP extension stopped the file upload!'); } // Check if the upload was successful if ($file['error']!==UPLOAD_ERR_OK) { Log::error(Database::get(), __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); if ($returnOnError===true) return false; - exit('Error: Upload failed!'); + Response::error('Upload failed!'); } // Verify extension @@ -118,7 +118,7 @@ final class Photo { if (!in_array(strtolower($extension), self::$validExtensions, true)) { Log::error(Database::get(), __METHOD__, __LINE__, 'Photo format not supported'); if ($returnOnError===true) return false; - exit('Error: Photo format not supported!'); + Response::error('Photo format not supported!'); } // Verify image @@ -126,7 +126,7 @@ final class Photo { if (!in_array($type, self::$validTypes, true)) { Log::error(Database::get(), __METHOD__, __LINE__, 'Photo type not supported'); if ($returnOnError===true) return false; - exit('Error: Photo type not supported!'); + Response::error('Photo type not supported!'); } // Generate id @@ -143,7 +143,7 @@ final class Photo { if ($checksum===false) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not calculate checksum for photo'); if ($returnOnError===true) return false; - exit('Error: Could not calculate checksum for photo!'); + Response::error('Could not calculate checksum for photo!'); } // Check if image exists based on checksum @@ -173,13 +173,13 @@ final class Photo { if (!@copy($tmp_name, $path)) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not copy photo to uploads'); if ($returnOnError===true) return false; - exit('Error: Could not copy photo to uploads!'); + Response::error('Could not copy photo to uploads!'); } else @unlink($tmp_name); } else { if (!@move_uploaded_file($tmp_name, $path)) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not move photo to uploads'); if ($returnOnError===true) return false; - exit('Error: Could not move photo to uploads!'); + Response::error('Could not move photo to uploads!'); } } @@ -190,7 +190,7 @@ final class Photo { if (Settings::get()['skipDuplicates']==='1') { Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); if ($returnOnError===true) return false; - exit('Warning: This photo has been skipped because it\'s already in your library.'); + Response::warning('This photo has been skipped because it\'s already in your library.'); } } @@ -220,7 +220,7 @@ final class Photo { if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create thumbnail for photo'); if ($returnOnError===true) return false; - exit('Error: Could not create thumbnail for photo!'); + Response::error('Could not create thumbnail for photo!'); } // Create Medium @@ -239,7 +239,7 @@ final class Photo { if ($result===false) { if ($returnOnError===true) return false; - exit('Error: Could not save photo in database!'); + Response::error('Could not save photo in database!'); } } @@ -637,7 +637,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) exit('Error: Could not get photo from database!'); + if ($photos===false) Response::error('Could not get photo from database!'); // Get photo object $photo = $photos->fetch_assoc(); @@ -664,7 +664,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($albums===false) exit('Error: Could not get album of photo from database!'); + if ($albums===false) Response::error('Could not get album of photo from database!'); // Get album object $album = $albums->fetch_assoc(); @@ -808,7 +808,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) exit('Error: Could not get photo from database!'); + if ($photos===false) Response::error('Could not get photo from database!'); // Get photo object $photo = $photos->fetch_object(); @@ -816,7 +816,7 @@ final class Photo { // Photo not found if ($photo===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); - exit('Error: Could not find specified photo!'); + Response::error('Could not find specified photo!'); } // Get extension diff --git a/php/Modules/Response.php b/php/Modules/Response.php new file mode 100644 index 0000000..01c4c10 --- /dev/null +++ b/php/Modules/Response.php @@ -0,0 +1,25 @@ + Date: Sun, 7 Feb 2016 14:32:46 +0100 Subject: [PATCH 076/183] Use Response in Access --- php/Access/Access.php | 4 +++- php/Access/Admin.php | 11 ++++++----- php/Access/Guest.php | 23 ++++++++++++----------- php/Access/Installation.php | 3 ++- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/php/Access/Access.php b/php/Access/Access.php index 6b471fe..43b8bab 100644 --- a/php/Access/Access.php +++ b/php/Access/Access.php @@ -2,11 +2,13 @@ namespace Lychee\Access; +use Lychee\Modules\Response; + abstract class Access { final protected static function fnNotFound() { - exit('Error: Function not found! Please check the spelling of the called function.'); + Response::error('Function not found! Please check the spelling of the called function.'); } diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 2a5b3f5..1de45a3 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -5,6 +5,7 @@ namespace Lychee\Access; use Lychee\Modules\Album; use Lychee\Modules\Import; use Lychee\Modules\Photo; +use Lychee\Modules\Response; use Lychee\Modules\Session; use Lychee\Modules\Settings; use Lychee\Modules\Validator; @@ -72,7 +73,7 @@ final class Admin extends Access { private static function getAlbumsAction() { $album = new Album(null); - echo json_encode($album->getAll(false)); + Response::json($album->getAll(false)); } @@ -81,7 +82,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumID']), __METHOD__); $album = new Album($_POST['albumID']); - echo json_encode($album->get()); + Response::json($album->get()); } @@ -145,7 +146,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoID'], $_POST['albumID']), __METHOD__); $photo = new Photo($_POST['photoID']); - echo json_encode($photo->get($_POST['albumID'])); + Response::json($photo->get($_POST['albumID'])); } @@ -256,7 +257,7 @@ final class Admin extends Access { Validator::required(isset($_POST['term']), __METHOD__); - echo json_encode(search($_POST['term'])); + Response::json(search($_POST['term'])); } @@ -265,7 +266,7 @@ final class Admin extends Access { private static function initAction() { $session = new Session(); - echo json_encode($session->init(false)); + Response::json($session->init(false)); } diff --git a/php/Access/Guest.php b/php/Access/Guest.php index de30713..88abf02 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -4,6 +4,7 @@ namespace Lychee\Access; use Lychee\Modules\Album; use Lychee\Modules\Photo; +use Lychee\Modules\Response; use Lychee\Modules\Session; use Lychee\Modules\Validator; @@ -44,7 +45,7 @@ final class Guest extends Access { private static function getAlbumsAction() { $album = new Album(null); - echo json_encode($album->getAll(true)); + Response::json($album->getAll(true)); } @@ -57,13 +58,13 @@ final class Guest extends Access { if ($album->getPublic()) { // Album public - if ($album->checkPassword($_POST['password'])) echo json_encode($album->get()); - else echo 'Warning: Wrong password!'; + if ($album->checkPassword($_POST['password'])) Response::json($album->get()); + else Response::warning('Wrong password!'); } else { // Album private - echo 'Warning: Album private!'; + Response::warning('Album private!'); } @@ -100,9 +101,9 @@ final class Guest extends Access { $pgP = $photo->getPublic($_POST['password']); - if ($pgP===2) echo json_encode($photo->get($_POST['albumID'])); - else if ($pgP===1) echo 'Warning: Wrong password!'; - else if ($pgP===0) echo 'Warning: Photo private!'; + if ($pgP===2) Response::json($photo->get($_POST['albumID'])); + else if ($pgP===1) Response::warning('Wrong password!'); + else if ($pgP===0) Response::warning('Photo private!'); } @@ -111,7 +112,7 @@ final class Guest extends Access { private static function initAction() { $session = new Session(); - echo json_encode($session->init(true)); + Response::json($session->init(true)); } @@ -143,12 +144,12 @@ final class Guest extends Access { // Album Public if ($album->checkPassword($_GET['password'])) $album->getArchive(); - else exit('Warning: Wrong password!'); + else Response::warning('Wrong password!'); } else { // Album Private - exit('Warning: Album private or not downloadable!'); + Response::warning('Album private or not downloadable!'); } @@ -171,7 +172,7 @@ final class Guest extends Access { } else { // Photo Private - exit('Warning: Photo private or password incorrect!'); + Response::warning('Photo private or password incorrect!'); } diff --git a/php/Access/Installation.php b/php/Access/Installation.php index 0a4a2e2..370d0d0 100644 --- a/php/Access/Installation.php +++ b/php/Access/Installation.php @@ -3,6 +3,7 @@ namespace Lychee\Access; use Lychee\Modules\Config; +use Lychee\Modules\Response; use Lychee\Modules\Validator; final class Installation extends Access { @@ -36,7 +37,7 @@ final class Installation extends Access { 'status' => LYCHEE_STATUS_NOCONFIG ); - echo json_encode($return); + Response::json($return); } From 9a1e51c8bd4c40965ce86446a7afcf15986be62a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 8 Feb 2016 22:11:39 +0100 Subject: [PATCH 077/183] Added partial php documentation to the Log class --- php/Modules/Log.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/php/Modules/Log.php b/php/Modules/Log.php index 83408e7..bd3fa65 100644 --- a/php/Modules/Log.php +++ b/php/Modules/Log.php @@ -4,18 +4,27 @@ namespace Lychee\Modules; final class Log { + /** + * @return boolean Returns true when successful. + */ public static function notice($connection, $function, $line, $text = '') { return Log::text($connection, 'notice', $function, $line, $text); } + /** + * @return boolean Returns true when successful. + */ public static function error($connection, $function, $line, $text = '') { return Log::text($connection, 'error', $function, $line, $text); } + /** + * @return boolean Returns true when successful. + */ private static function text($connection, $type, $function, $line, $text = '') { // Check dependencies From 66edea4d71c971f5db469b875214f927e0cf7260 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 8 Feb 2016 22:12:03 +0100 Subject: [PATCH 078/183] Added partial php documentation to the Config class --- php/Modules/Config.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/php/Modules/Config.php b/php/Modules/Config.php index d7f3914..4a00ce6 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -43,12 +43,18 @@ if(!defined('LYCHEE')) Response::error('Direct access is not allowed!'); } + /** + * @return boolean Returns true when the config exists. + */ public static function exists() { return file_exists(LYCHEE_CONFIG_FILE); } + /** + * @return array Returns the config. + */ public static function get() { require(LYCHEE_CONFIG_FILE); From aa00ebc77be0ed53e9faebbaad18c3b00ca8db6d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 8 Feb 2016 22:16:09 +0100 Subject: [PATCH 079/183] Removed unnecessary title trimming --- php/Modules/Album.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 5537450..5928df6 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -22,9 +22,6 @@ final class Album { // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - // Parse - if (strlen($title)>50) $title = substr($title, 0, 50); - // Properties $public = 0; $visible = 1; From 025f6e974b7107e454745e8e9a537ae3e4a1f73f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 17:32:44 +0100 Subject: [PATCH 080/183] Added phpDoc comments --- php/Modules/Album.php | 72 ++++++++++++++++--- php/Modules/Import.php | 12 +++- php/Modules/Photo.php | 149 ++++++++++++++++++++------------------- php/Modules/Session.php | 24 +++++-- php/Modules/Settings.php | 47 ++++++++++-- php/helpers/search.php | 3 + 6 files changed, 211 insertions(+), 96 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 5928df6..b678241 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -8,6 +8,9 @@ final class Album { private $albumIDs = null; + /** + * @return boolean Returns true when successful. + */ public function __construct($albumIDs) { // Init vars @@ -17,6 +20,9 @@ final class Album { } + /** + * @return integer|false ID of the created album. + */ public function add($title = 'Untitled') { // Call plugins @@ -39,6 +45,10 @@ final class Album { } + /** + * Rurns album-attributes into a front-end friendly format. Note that some attributes remain unchanged. + * @return array Returns album-attributes in a normalized structure. + */ public static function prepareData(array $data) { // This function requires the following album-attributes and turns them @@ -72,6 +82,9 @@ final class Album { } + /** + * @return array|false Returns an array of photos and album information or false on failure. + */ public function get() { // Check dependencies @@ -117,7 +130,7 @@ final class Album { $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $previousPhotoID = ''; - if ($photos===false) Response::error('Could not get photos of album from database!'); + if ($photos===false) return false; while ($photo = $photos->fetch_assoc()) { @@ -167,6 +180,9 @@ final class Album { } + /** + * @return array|false Returns an array of albums or false on failure. + */ public function getAll($public = true) { // Call plugins @@ -189,7 +205,7 @@ final class Album { // Execute query $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($albums===false) Response::error('Could not get albums from database!'); + if ($albums===false) return false; // For each album while ($album = $albums->fetch_assoc()) { @@ -205,7 +221,7 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($thumbs===false) Response::error('Could not get thumbs of album from database!'); + if ($thumbs===false) return false; // For each thumb $k = 0; @@ -231,6 +247,9 @@ final class Album { } + /** + * @return array|false Returns an array of smart albums or false on failure. + */ private function getSmartInfo() { // Initialize return var @@ -249,7 +268,7 @@ final class Album { $unsorted = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($unsorted===false) Response::error('Could not get unsorted photos from database!'); + if ($unsorted===false) return false; $return['unsorted'] = array( 'thumbs' => array(), @@ -271,7 +290,7 @@ final class Album { $starred = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($starred===false) Response::error('Could not get starred photos from database!'); + if ($starred===false) return false; $return['starred'] = array( 'thumbs' => array(), @@ -293,7 +312,7 @@ final class Album { $public = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($public===false) Response::error('Could not get public photos from database!'); + if ($public===false) return false; $return['public'] = array( 'thumbs' => array(), @@ -315,7 +334,7 @@ final class Album { $recent = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $i = 0; - if ($recent===false) Response::error('Could not get recent photos from database!'); + if ($recent===false) return false; $return['recent'] = array( 'thumbs' => array(), @@ -334,6 +353,10 @@ final class Album { } + /** + * Starts a download of an album. + * @return resource|boolean Sends a ZIP-file or returns false on failure. + */ public function getArchive() { // Check dependencies @@ -373,7 +396,7 @@ final class Album { $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); $album = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($album===false) Response::error('Could not get album from database!'); + if ($album===false) return false; // Get album object $album = $album->fetch_object(); @@ -381,7 +404,7 @@ final class Album { // Photo not found if ($album===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); - Response::error('Could not find specified album!'); + return false; } // Set title @@ -404,12 +427,12 @@ final class Album { // Execute query $photos = Database::execute(Database::get(), $photos, __METHOD__, __LINE__); - if ($album===null) Response::error('Could not get photos from database!'); + if ($album===null) return false; // Check if album empty if ($photos->num_rows==0) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive without images'); - Response::error('Could not create ZipArchive without images!'); + return false; } // Parse each path @@ -472,6 +495,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ public function setTitle($title = 'Untitled') { // Check dependencies @@ -492,6 +518,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ public function setDescription($description = '') { // Check dependencies @@ -512,6 +541,9 @@ final class Album { } + /** + * @return boolean Returns true when the album is public. + */ public function getPublic() { // Check dependencies @@ -539,6 +571,9 @@ final class Album { } + /** + * @return boolean Returns true when the album is downloadable. + */ public function getDownloadable() { // Check dependencies @@ -566,6 +601,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ public function setPublic($public, $password, $visible, $downloadable) { // Check dependencies @@ -604,6 +642,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ private function setPassword($password) { // Check dependencies @@ -640,6 +681,9 @@ final class Album { } + /** + * @return boolean Returns when album is public. + */ public function checkPassword($password) { // Check dependencies @@ -667,6 +711,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ public function merge() { // Check dependencies @@ -702,6 +749,9 @@ final class Album { } + /** + * @return boolean Returns true when successful. + */ public function delete() { // Check dependencies diff --git a/php/Modules/Import.php b/php/Modules/Import.php index 37838ab..e21b0ef 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -26,6 +26,9 @@ final class Import { } + /** + * @return boolean Returns true when successful. + */ public function url($urls, $albumID = 0) { // Call plugins @@ -85,6 +88,11 @@ final class Import { } + /** + * @return boolean|string Returns true when successful. + * Warning: Folder empty or no readable files to process! + * Notice: Import only contained albums! + */ public function server($path, $albumID = 0) { // Parse path @@ -93,7 +101,7 @@ final class Import { if (is_dir($path)===false) { Log::error(Database::get(), __METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')'); - return 'Error: Given path is not a directory!'; + return false; } // Skip folders of Lychee @@ -101,7 +109,7 @@ final class Import { $path===LYCHEE_UPLOADS_MEDIUM||($path . '/')===LYCHEE_UPLOADS_MEDIUM|| $path===LYCHEE_UPLOADS_THUMB||($path . '/')===LYCHEE_UPLOADS_THUMB) { Log::error(Database::get(), __METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')'); - return 'Error: Given path is a reserved path of Lychee!'; + return false; } $error = false; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 59d23e9..9403624 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -21,6 +21,9 @@ final class Photo { '.gif' ); + /** + * @return boolean Returns true when successful. + */ public function __construct($photoIDs) { // Init vars @@ -251,11 +254,14 @@ final class Photo { } + /** + * @return array|false Returns a subset of a photo when same photo exists or returns false on failure. + */ private function exists($checksum, $photoID = null) { // Exclude $photoID from select when $photoID is set if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID)); - else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); + else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum)); $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); @@ -280,6 +286,9 @@ final class Photo { } + /** + * @return boolean Returns true when successful. + */ private function createThumb($url, $filename, $type, $width, $height) { // Call plugins @@ -369,17 +378,18 @@ final class Photo { } + /** + * Creates a smaller version of a photo when its size is bigger than a preset size. + * Photo must be big enough, medium must be activated and Imagick must be installed and activated. + * @return boolean Returns true when successful. + */ private function createMedium($url, $filename, $width, $height) { - // Function creates a smaller version of a photo when its size is bigger than a preset size // Excepts the following: // (string) $url = Path to the photo-file // (string) $filename = Name of the photo-file // (int) $width = Width of the photo // (int) $height = Height of the photo - // Returns the following - // (boolean) true = Success - // (boolean) false = Failure // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -446,15 +456,15 @@ final class Photo { } + /** + * Rotates and flips a photo based on its EXIF orientation. + * @return array|false Returns an array with the new orientation, width, height or false on failure. + */ public function adjustFile($path, array $info) { - // Function rotates and flips a photo based on its EXIF orientation // Excepts the following: // (string) $path = Path to the photo-file // (array) $info = ['orientation', 'width', 'height'] - // Returns the following - // (array) $info = ['orientation', 'width', 'height'] = Success - // (boolean) false = Failure // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); @@ -577,13 +587,14 @@ final class Photo { } + /** + * Rurns photo-attributes into a front-end friendly format. Note that some attributes remain unchanged. + * @return array Returns photo-attributes in a normalized structure. + */ public static function prepareData(array $data) { - // Function turns photo-attributes into a front-end friendly format. Note that some attributes remain unchanged. // Excepts the following: // (array) $data = ['id', 'title', 'tags', 'public', 'star', 'album', 'thumbUrl', 'takestamp', 'url'] - // Returns the following: - // (array) $photo // Init $photo = null; @@ -619,13 +630,13 @@ final class Photo { } + /** + * @return array|false Returns an array with information about the photo or false on failure. + */ public function get($albumID) { - // Functions returns data of a photo // Excepts the following: // (string) $albumID = Album which is currently visible to the user - // Returns the following: - // (array) $photo // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -637,7 +648,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) Response::error('Could not get photo from database!'); + if ($photos===false) return false; // Get photo object $photo = $photos->fetch_assoc(); @@ -664,7 +675,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album'])); $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($albums===false) Response::error('Could not get album of photo from database!'); + if ($albums===false) return false; // Get album object $album = $albums->fetch_assoc(); @@ -686,6 +697,10 @@ final class Photo { } + /** + * Reads and parses information and metadata out of a photo. + * @return array Returns an array of photo information and metadata. + */ public function getInfo($url) { // Functions returns information and metadata of a photo @@ -791,13 +806,12 @@ final class Photo { } + /** + * Starts a download of a photo. + * @return resource|boolean Sends a ZIP-file or returns false on failure. + */ public function getArchive() { - // Functions starts a download of a photo - // Returns the following: - // (boolean + output) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -808,7 +822,7 @@ final class Photo { $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - if ($photos===false) Response::error('Could not get photo from database!'); + if ($photos===false) return false; // Get photo object $photo = $photos->fetch_object(); @@ -816,7 +830,7 @@ final class Photo { // Photo not found if ($photo===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); - Response::error('Could not find specified photo!'); + return false; } // Get extension @@ -853,15 +867,12 @@ final class Photo { } + /** + * Sets the title of a photo. + * @return boolean Returns true when successful. + */ public function setTitle($title) { - // Functions sets the title of a photo - // Excepts the following: - // (string) $title = Title with a maximum length of 50 chars - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -880,15 +891,12 @@ final class Photo { } + /** + * Sets the description of a photo. + * @return boolean Returns true when successful. + */ public function setDescription($description) { - // Functions sets the description of a photo - // Excepts the following: - // (string) $description = Description with a maximum length of 1000 chars - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -907,13 +915,12 @@ final class Photo { } + /** + * Toggles the star property of a photo. + * @return boolean Returns true when successful. + */ public function setStar() { - // Functions stars a photo - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -951,14 +958,14 @@ final class Photo { } + /** + * Checks if photo or parent album is public. + * @return integer 0 = Photo private and parent album private + * 1 = Album public, but password incorrect + * 2 = Photo public or album public and password correct + */ public function getPublic($password) { - // Functions checks if photo or parent album is public - // Returns the following: - // (int) 0 = Photo private and parent album private - // (int) 1 = Album public, but password incorrect - // (int) 2 = Photo public or album public and password correct - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -1003,13 +1010,12 @@ final class Photo { } + /** + * Toggles the public property of a photo. + * @return boolean Returns true when successful. + */ public function setPublic() { - // Functions toggles the public property of a photo - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -1040,13 +1046,12 @@ final class Photo { } + /** + * Sets the parent album of a photo. + * @return boolean Returns true when successful. + */ function setAlbum($albumID) { - // Functions sets the parent album of a photo - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -1065,14 +1070,14 @@ final class Photo { } + /** + * Sets the tags of a photo. + * @return boolean Returns true when successful. + */ public function setTags($tags) { - // Functions sets the tags of a photo // Excepts the following: // (string) $tags = Comma separated list of tags with a maximum length of 1000 chars - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -1096,13 +1101,12 @@ final class Photo { } + /** + * Duplicates a photo. + * @return boolean Returns true when successful. + */ public function duplicate() { - // Functions duplicates a photo - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -1139,13 +1143,12 @@ final class Photo { } + /** + * Deletes a photo with all its data and files. + * @return boolean Returns true when successful. + */ public function delete() { - // Functions deletes a photo with all its data and files - // Returns the following: - // (boolean) true = Success - // (boolean) false = Failure - // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 126fb28..7b6d105 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -4,6 +4,10 @@ namespace Lychee\Modules; final class Session { + /** + * Reads and returns information about the Lychee installation. + * @return array Returns an array with the login status and configuration. + */ public function init($public = true) { // Call plugins @@ -15,11 +19,9 @@ final class Session { // Path to Lychee for the server-import dialog $return['config']['location'] = LYCHEE; - // Remove username and password from response + // Remove sensitive from response unset($return['config']['username']); unset($return['config']['password']); - - // Remove identifier from response unset($return['config']['identifier']); // Check if login credentials exist and login if they don't @@ -60,6 +62,10 @@ final class Session { } + /** + * Sets the session values when username and password correct. + * @return boolean Returns true when login was successful. + */ public function login($username, $password) { // Call plugins @@ -86,6 +92,10 @@ final class Session { } + /** + * Sets the session values when no there is no username and password in the database. + * @return boolean Returns true when no login was found. + */ private function noLogin() { // Check if login credentials exist and login if they don't @@ -100,14 +110,16 @@ final class Session { } + /** + * Unsets the session values. + * @return boolean Returns true when logout was successful. + */ public function logout() { // Call plugins Plugins::get()->activate(__METHOD__, 0, func_get_args()); - $_SESSION['login'] = null; - $_SESSION['identifier'] = null; - + session_unset(); session_destroy(); // Call plugins diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index acdfa55..3f07e12 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -6,6 +6,9 @@ final class Settings { private static $cache = null; + /** + * @return array Returns the settings of Lychee. + */ public static function get() { if (self::$cache) return self::$cache; @@ -26,6 +29,9 @@ final class Settings { } + /** + * @return boolean Returns true when successful. + */ private static function set($key, $value, $row = false) { if ($row===false) { @@ -50,6 +56,11 @@ final class Settings { } + /** + * Sets the username and password when current password is correct. + * Exits on error. + * @return true Returns true when successful. + */ public static function setLogin($oldPassword = '', $username, $password) { if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) { @@ -68,6 +79,10 @@ final class Settings { } + /** + * Sets a new username. + * @return boolean Returns true when successful. + */ private static function setUsername($username) { // Check dependencies @@ -84,6 +99,10 @@ final class Settings { } + /** + * Sets a new username. + * @return boolean Returns true when successful. + */ private static function setPassword($password) { // Check dependencies @@ -99,6 +118,10 @@ final class Settings { } + /** + * Sets a new dropboxKey. + * @return boolean Returns true when successful. + */ public static function setDropboxKey($dropboxKey) { if (strlen($dropboxKey)<1||strlen($dropboxKey)>50) { @@ -111,6 +134,10 @@ final class Settings { } + /** + * Sets a new sorting for the photos. + * @return boolean Returns true when successful. + */ public static function setSortingPhotos($type, $order) { $sorting = 'ORDER BY '; @@ -125,7 +152,9 @@ final class Settings { case 'type': $sorting .= 'type'; break; case 'star': $sorting .= 'star'; break; case 'takestamp': $sorting .= 'takestamp'; break; - default: Response::error('Unknown type for sorting!'); + default: Log::error(Database::get(), __METHOD__, __LINE__, 'Could not update settings. Unknown type for sorting.'); + return false; + break; } @@ -136,7 +165,9 @@ final class Settings { case 'ASC': $sorting .= 'ASC'; break; case 'DESC': $sorting .= 'DESC'; break; - default: Response::error('Unknown order for sorting!'); + default: Log::error(Database::get(), __METHOD__, __LINE__, 'Could not update settings. Unknown order for sorting.'); + return false; + break; } @@ -148,6 +179,10 @@ final class Settings { } + /** + * Sets a new sorting for the albums. + * @return boolean Returns true when successful. + */ public static function setSortingAlbums($type, $order) { $sorting = 'ORDER BY '; @@ -159,7 +194,9 @@ final class Settings { case 'title': $sorting .= 'title'; break; case 'description': $sorting .= 'description'; break; case 'public': $sorting .= 'public'; break; - default: Response::error('Unknown type for sorting!'); + default: Log::error(Database::get(), __METHOD__, __LINE__, 'Could not update settings. Unknown type for sorting.'); + return false; + break; } @@ -170,7 +207,9 @@ final class Settings { case 'ASC': $sorting .= 'ASC'; break; case 'DESC': $sorting .= 'DESC'; break; - default: Response::error('Unknown order for sorting!'); + default: Log::error(Database::get(), __METHOD__, __LINE__, 'Could not update settings. Unknown order for sorting.'); + return false; + break; } diff --git a/php/helpers/search.php b/php/helpers/search.php index 75b46b0..50638f9 100755 --- a/php/helpers/search.php +++ b/php/helpers/search.php @@ -4,6 +4,9 @@ use Lychee\Modules\Album; use Lychee\Modules\Database; use Lychee\Modules\Photo; +/** + * @return array|false Returns an array with albums and photos. + */ function search($term) { // Initialize return var From 4e1e3cb2ee7068b14237617aa71dd3f8fbe634b3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:31:51 +0100 Subject: [PATCH 081/183] Removed debug mode --- src/scripts/api.js | 3 --- src/scripts/lychee.js | 1 - 2 files changed, 4 deletions(-) diff --git a/src/scripts/api.js b/src/scripts/api.js index 1979d22..85de71c 100644 --- a/src/scripts/api.js +++ b/src/scripts/api.js @@ -35,9 +35,6 @@ api.post = function(fn, params, callback) { data = $.parseJSON(data) } - // Output response when debug mode is enabled - if (lychee.debugMode) console.log(data) - callback(data) } diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 1f88917..c92699e 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -15,7 +15,6 @@ lychee = { publicMode : false, viewMode : false, - debugMode : false, checkForUpdates : '1', sortingPhotos : '', From 60e4a06df887fbca7a5cc3eca141c10be6dac1a6 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:32:13 +0100 Subject: [PATCH 082/183] Removed unnecessary anonymous function --- src/scripts/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/api.js b/src/scripts/api.js index 85de71c..6ed4d2b 100644 --- a/src/scripts/api.js +++ b/src/scripts/api.js @@ -18,7 +18,7 @@ api.post = function(fn, params, callback) { const success = (data) => { - setTimeout(() => loadingBar.hide(), 100) + setTimeout(loadingBar.hide, 100) // Catch errors if (typeof data==='string' && data.substring(0, 7)==='Error: ') { From 36f43c3e2722e93d1c10dcbe062b463ca267306a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:33:39 +0100 Subject: [PATCH 083/183] Strict if condition --- php/Access/Guest.php | 4 ++-- php/Modules/Config.php | 2 +- php/Modules/Database.php | 8 ++++---- php/Modules/Settings.php | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 88abf02..a4a0d48 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -55,7 +55,7 @@ final class Guest extends Access { $album = new Album($_POST['albumID']); - if ($album->getPublic()) { + if ($album->getPublic()===true) { // Album public if ($album->checkPassword($_POST['password'])) Response::json($album->get()); @@ -76,7 +76,7 @@ final class Guest extends Access { $album = new Album($_POST['albumID']); - if ($album->getPublic()) { + if ($album->getPublic()===true) { // Album public if ($album->checkPassword($_POST['password'])) echo true; diff --git a/php/Modules/Config.php b/php/Modules/Config.php index 4a00ce6..d68a257 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -13,7 +13,7 @@ final class Config { if ($connection===false) return 'Warning: Connection failed!'; // Check if user can create the database before saving the configuration - if (!Database::createDatabase($connection, $name)) return 'Warning: Creation failed!'; + if (Database::createDatabase($connection, $name)===false) return 'Warning: Creation failed!'; // Escape data $host = mysqli_real_escape_string($connection, $host); diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 9c4e711..1a2a3c8 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -50,16 +50,16 @@ final class Database { // Check if the connection was successful if ($connection===false) Response::error('' . $connection->connect_error); - if (!self::setCharset($connection)) Response::error('Could not set database charset!'); + if (self::setCharset($connection)===false) Response::error('Could not set database charset!'); // Create database - if (!self::createDatabase($connection, $name)) Response::error('Could not create database!'); + if (self::createDatabase($connection, $name)===false) Response::error('Could not create database!'); // Create tables - if (!self::createTables($connection)) Response::error('Could not create tables!'); + if (self::createTables($connection)===false) Response::error('Could not create tables!'); // Update database - if (!self::update($connection, $name)) Response::error('Could not update database and tables!'); + if (self::update($connection, $name)===false) Response::error('Could not update database and tables!'); $this->connection = $connection; diff --git a/php/Modules/Settings.php b/php/Modules/Settings.php index 3f07e12..018dc7c 100755 --- a/php/Modules/Settings.php +++ b/php/Modules/Settings.php @@ -66,10 +66,10 @@ final class Settings { if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) { // Save username - if (self::setUsername($username)!==true) Response::error('Updating username failed!'); + if (self::setUsername($username)===false) Response::error('Updating username failed!'); // Save password - if (self::setPassword($password)!==true) Response::error('Updating password failed!'); + if (self::setPassword($password)===false) Response::error('Updating password failed!'); return true; From fcb80c9f322b0d06982d537be510e248799f94c7 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:34:24 +0100 Subject: [PATCH 084/183] Run self::fnNotFound() when no match found in access class --- php/Access/Admin.php | 5 +---- php/Access/Guest.php | 5 +---- php/Access/Installation.php | 3 +-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 1de45a3..ea54194 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -59,12 +59,9 @@ final class Admin extends Access { case 'Album::getArchive': self::getAlbumArchiveAction(); break; case 'Photo::getArchive': self::getPhotoArchiveAction(); break; - // Error - default: self::fnNotFound(); break; - } - return true; + self::fnNotFound(); } diff --git a/php/Access/Guest.php b/php/Access/Guest.php index a4a0d48..269fef3 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -31,12 +31,9 @@ final class Guest extends Access { case 'Album::getArchive': self::getAlbumArchiveAction(); break; case 'Photo::getArchive': self::getPhotoArchiveAction(); break; - // Error - default: self::fnNotFound(); break; - } - return true; + self::fnNotFound(); } diff --git a/php/Access/Installation.php b/php/Access/Installation.php index 370d0d0..ce3863c 100644 --- a/php/Access/Installation.php +++ b/php/Access/Installation.php @@ -14,12 +14,11 @@ final class Installation extends Access { case 'Config::create': self::configCreateAction(); break; - // Error default: self::initAction(); break; } - return true; + self::fnNotFound(); } From 3c45bbf4d14dd84196c3007711666a3ab7b9950a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:35:13 +0100 Subject: [PATCH 085/183] Added phpDoc comments --- php/Modules/Config.php | 9 +++++++-- php/Modules/Database.php | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/php/Modules/Config.php b/php/Modules/Config.php index d68a257..60276ff 100644 --- a/php/Modules/Config.php +++ b/php/Modules/Config.php @@ -4,6 +4,13 @@ namespace Lychee\Modules; final class Config { + /** + * Creates the configuration file. + * @return true|string Returns true when successful. + * Warning: Connection failed! + * Warning: Creation failed! + * Warning: Could not create file! + */ public static function create($host, $user, $password, $name = 'lychee', $prefix = '') { // Open a new connection to the MySQL server @@ -25,8 +32,6 @@ final class Config { // Save config.php $config = "connection = $connection; + return true; + } + /** + * @return object|false Returns the connection when successful. + */ public static function connect($host = 'localhost', $user, $password) { // Open a new connection to the MySQL server @@ -77,6 +89,9 @@ final class Database { } + /** + * @return boolean Returns true when successful. + */ private static function setCharset($connection) { // Check dependencies @@ -95,6 +110,9 @@ final class Database { } + /** + * @return boolean Returns true when successful. + */ public static function createDatabase($connection, $name = 'lychee') { // Check dependencies @@ -113,6 +131,9 @@ final class Database { } + /** + * @return boolean Returns true when successful. + */ private static function createTables($connection) { // Check dependencies @@ -238,6 +259,10 @@ final class Database { } + /** + * Exits when an update fails. + * @return boolean Returns true when successful. + */ private static function update($connection, $dbName) { // Check dependencies @@ -267,6 +292,9 @@ final class Database { } + /** + * @return boolean Returns true when successful. + */ public static function setVersion($connection, $version) { // Check dependencies @@ -276,9 +304,13 @@ final class Database { $result = self::execute($connection, $query, __METHOD__, __LINE__); if ($result===false) return false; + return true; } + /** + * @return string Returns a escaped query. + */ public static function prepare($connection, $query, array $data) { // Check dependencies @@ -345,6 +377,9 @@ final class Database { } + /** + * @return object|false Returns the results on success. + */ public static function execute($connection, $query, $function, $line) { // Check dependencies From 109880475adf2b7c94337c118ba20404dd1d162c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:36:34 +0100 Subject: [PATCH 086/183] Photo add function only adds the first file in the array --- php/Modules/Import.php | 10 +- php/Modules/Photo.php | 300 ++++++++++++++++++++--------------------- 2 files changed, 155 insertions(+), 155 deletions(-) diff --git a/php/Modules/Import.php b/php/Modules/Import.php index e21b0ef..3bf0df1 100644 --- a/php/Modules/Import.php +++ b/php/Modules/Import.php @@ -4,7 +4,11 @@ namespace Lychee\Modules; final class Import { - private function photo($path, $albumID = 0, $description = '', $tags = '') { + /** + * Creates an array similar to a file upload array and adds the photo to Lychee. + * @return boolean Returns true when photo import was successful. + */ + private function photo($path, $albumID = 0) { // No need to validate photo type and extension in this function. // $photo->add will take care of it. @@ -21,7 +25,7 @@ final class Import { $nameFile[0]['size'] = $size; $nameFile[0]['error'] = UPLOAD_ERR_OK; - if (!$photo->add($nameFile, $albumID, $description, $tags, true)) return false; + if ($photo->add($nameFile, $albumID, true)===false) return false; return true; } @@ -140,7 +144,7 @@ final class Import { $contains['photos'] = true; - if (!$this->photo($file, $albumID)) { + if ($this->photo($file, $albumID)===false) { $error = true; Log::error(Database::get(), __METHOD__, __LINE__, 'Could not import file (' . $file . ')'); continue; diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 9403624..d3b0016 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -79,174 +79,170 @@ final class Photo { } - foreach ($files as $file) { + // Only process the first photo in the array + $file = $files[0]; - // Check if file exceeds the upload_max_filesize directive - if ($file['error']===UPLOAD_ERR_INI_SIZE) { - Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); - if ($returnOnError===true) return false; - Response::error('The uploaded file exceeds the upload_max_filesize directive in php.ini!'); + // Check if file exceeds the upload_max_filesize directive + if ($file['error']===UPLOAD_ERR_INI_SIZE) { + Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'); + if ($returnOnError===true) return false; + Response::error('The uploaded file exceeds the upload_max_filesize directive in php.ini!'); + } + + // Check if file was only partially uploaded + if ($file['error']===UPLOAD_ERR_PARTIAL) { + Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); + if ($returnOnError===true) return false; + Response::error('The uploaded file was only partially uploaded!'); + } + + // Check if writing file to disk failed + if ($file['error']===UPLOAD_ERR_CANT_WRITE) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Failed to write photo to disk'); + if ($returnOnError===true) return false; + Response::error('Failed to write photo to disk!'); + } + + // Check if a extension stopped the file upload + if ($file['error']===UPLOAD_ERR_EXTENSION) { + Log::error(Database::get(), __METHOD__, __LINE__, 'A PHP extension stopped the file upload'); + if ($returnOnError===true) return false; + Response::error('A PHP extension stopped the file upload!'); + } + + // Check if the upload was successful + if ($file['error']!==UPLOAD_ERR_OK) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); + if ($returnOnError===true) return false; + Response::error('Upload failed!'); + } + + // Verify extension + $extension = getExtension($file['name']); + if (!in_array(strtolower($extension), self::$validExtensions, true)) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo format not supported'); + if ($returnOnError===true) return false; + Response::error('Photo format not supported!'); + } + + // Verify image + $type = @exif_imagetype($file['tmp_name']); + if (!in_array($type, self::$validTypes, true)) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Photo type not supported'); + if ($returnOnError===true) return false; + Response::error('Photo type not supported!'); + } + + // Generate id + $id = str_replace('.', '', microtime(true)); + while(strlen($id)<14) $id .= 0; + + // Set paths + $tmp_name = $file['tmp_name']; + $photo_name = md5($id) . $extension; + $path = LYCHEE_UPLOADS_BIG . $photo_name; + + // Calculate checksum + $checksum = sha1_file($tmp_name); + if ($checksum===false) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not calculate checksum for photo'); + if ($returnOnError===true) return false; + Response::error('Could not calculate checksum for photo!'); + } + + // Check if image exists based on checksum + if ($checksum===false) { + + $checksum = ''; + $exists = false; + + } else { + + $exists = $this->exists($checksum); + + if ($exists!==false) { + $photo_name = $exists['photo_name']; + $path = $exists['path']; + $path_thumb = $exists['path_thumb']; + $medium = ($exists['medium']==='1' ? 1 : 0); + $exists = true; } - // Check if file was only partially uploaded - if ($file['error']===UPLOAD_ERR_PARTIAL) { - Log::error(Database::get(), __METHOD__, __LINE__, 'The uploaded file was only partially uploaded'); - if ($returnOnError===true) return false; - Response::error('The uploaded file was only partially uploaded!'); - } + } - // Check if writing file to disk failed - if ($file['error']===UPLOAD_ERR_CANT_WRITE) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Failed to write photo to disk'); - if ($returnOnError===true) return false; - Response::error('Failed to write photo to disk!'); - } + if ($exists===false) { - // Check if a extension stopped the file upload - if ($file['error']===UPLOAD_ERR_EXTENSION) { - Log::error(Database::get(), __METHOD__, __LINE__, 'A PHP extension stopped the file upload'); - if ($returnOnError===true) return false; - Response::error('A PHP extension stopped the file upload!'); - } - - // Check if the upload was successful - if ($file['error']!==UPLOAD_ERR_OK) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')'); - if ($returnOnError===true) return false; - Response::error('Upload failed!'); - } - - // Verify extension - $extension = getExtension($file['name']); - if (!in_array(strtolower($extension), self::$validExtensions, true)) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Photo format not supported'); - if ($returnOnError===true) return false; - Response::error('Photo format not supported!'); - } - - // Verify image - $type = @exif_imagetype($file['tmp_name']); - if (!in_array($type, self::$validTypes, true)) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Photo type not supported'); - if ($returnOnError===true) return false; - Response::error('Photo type not supported!'); - } - - // Generate id - $id = str_replace('.', '', microtime(true)); - while(strlen($id)<14) $id .= 0; - - // Set paths - $tmp_name = $file['tmp_name']; - $photo_name = md5($id) . $extension; - $path = LYCHEE_UPLOADS_BIG . $photo_name; - - // Calculate checksum - $checksum = sha1_file($tmp_name); - if ($checksum===false) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not calculate checksum for photo'); - if ($returnOnError===true) return false; - Response::error('Could not calculate checksum for photo!'); - } - - // Check if image exists based on checksum - if ($checksum===false) { - - $checksum = ''; - $exists = false; - - } else { - - $exists = $this->exists($checksum); - - if ($exists!==false) { - $photo_name = $exists['photo_name']; - $path = $exists['path']; - $path_thumb = $exists['path_thumb']; - $medium = ($exists['medium']==='1' ? 1 : 0); - $exists = true; - } - - } - - if ($exists===false) { - - // Import if not uploaded via web - if (!is_uploaded_file($tmp_name)) { - if (!@copy($tmp_name, $path)) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not copy photo to uploads'); - if ($returnOnError===true) return false; - Response::error('Could not copy photo to uploads!'); - } else @unlink($tmp_name); - } else { - if (!@move_uploaded_file($tmp_name, $path)) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not move photo to uploads'); - if ($returnOnError===true) return false; - Response::error('Could not move photo to uploads!'); - } - } - - } else { - - // Photo already exists - // Check if the user wants to skip duplicates - if (Settings::get()['skipDuplicates']==='1') { - Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); + // Import if not uploaded via web + if (!is_uploaded_file($tmp_name)) { + if (!@copy($tmp_name, $path)) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not copy photo to uploads'); if ($returnOnError===true) return false; - Response::warning('This photo has been skipped because it\'s already in your library.'); - } - - } - - // Read infos - $info = $this->getInfo($path); - - // Use title of file if IPTC title missing - if ($info['title']==='') $info['title'] = substr(basename($file['name'], $extension), 0, 30); - - // Use description parameter if set - if ($description==='') $description = $info['description']; - - if ($exists===false) { - - // Set orientation based on EXIF data - if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') { - $adjustFile = $this->adjustFile($path, $info); - if ($adjustFile!==false) $info = $adjustFile; - else Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); - } - - // Set original date - if ($info['takestamp']!==''&&$info['takestamp']!==0) @touch($path, $info['takestamp']); - - // Create Thumb - if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create thumbnail for photo'); + Response::error('Could not copy photo to uploads!'); + } else @unlink($tmp_name); + } else { + if (!@move_uploaded_file($tmp_name, $path)) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not move photo to uploads'); if ($returnOnError===true) return false; - Response::error('Could not create thumbnail for photo!'); + Response::error('Could not move photo to uploads!'); } - - // Create Medium - if ($this->createMedium($path, $photo_name, $info['width'], $info['height'])) $medium = 1; - else $medium = 0; - - // Set thumb url - $path_thumb = md5($id) . '.jpeg'; - } - // Save to DB - $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); - $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); - $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + } else { - if ($result===false) { + // Photo already exists + // Check if the user wants to skip duplicates + if (Settings::get()['skipDuplicates']==='1') { + Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated'); if ($returnOnError===true) return false; - Response::error('Could not save photo in database!'); + Response::warning('This photo has been skipped because it\'s already in your library.'); } } + // Read infos + $info = $this->getInfo($path); + + // Use title of file if IPTC title missing + if ($info['title']==='') $info['title'] = substr(basename($file['name'], $extension), 0, 30); + + if ($exists===false) { + + // Set orientation based on EXIF data + if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') { + $adjustFile = $this->adjustFile($path, $info); + if ($adjustFile!==false) $info = $adjustFile; + else Log::notice(Database::get(), __METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')'); + } + + // Set original date + if ($info['takestamp']!==''&&$info['takestamp']!==0) @touch($path, $info['takestamp']); + + // Create Thumb + if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create thumbnail for photo'); + if ($returnOnError===true) return false; + Response::error('Could not create thumbnail for photo!'); + } + + // Create Medium + if ($this->createMedium($path, $photo_name, $info['width'], $info['height'])) $medium = 1; + else $medium = 0; + + // Set thumb url + $path_thumb = md5($id) . '.jpeg'; + + } + + // Save to DB + $values = array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $info['description'], '', $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium); + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($result===false) { + if ($returnOnError===true) return false; + Response::error('Could not save photo in database!'); + } + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); From a02ba0143f0f695c8b29420b7495210c78b10d9f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:37:25 +0100 Subject: [PATCH 087/183] Improved error handling when album/photo not found --- php/Modules/Album.php | 20 +++++++++++++++++++- php/Modules/Photo.php | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index b678241..ebeeb50 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -401,7 +401,7 @@ final class Album { // Get album object $album = $album->fetch_object(); - // Photo not found + // Album not found? if ($album===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); return false; @@ -563,6 +563,12 @@ final class Album { // Get album object $album = $albums->fetch_object(); + // Album not found? + if ($album===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); + return false; + } + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); @@ -593,6 +599,12 @@ final class Album { // Get album object $album = $albums->fetch_object(); + // Album not found? + if ($album===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); + return false; + } + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); @@ -701,6 +713,12 @@ final class Album { // Get album object $album = $albums->fetch_object(); + // Album not found? + if ($album===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); + return false; + } + // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index d3b0016..5ecf2b3 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -33,16 +33,20 @@ final class Photo { } - public function add(array $files, $albumID = 0, $description = '', $tags = '', $returnOnError = false) { - - // Use $returnOnError if you want to handle errors by your own - // e.g. when calling this functions inside an if-condition + /** + * Creats new photo(s). + * Exits on error. + * Use $returnOnError if you want to handle errors by your own. + * @return boolean Returns true when successful. + */ + public function add(array $files, $albumID = 0, $returnOnError = false) { // Check permissions if (hasPermissions(LYCHEE_UPLOADS)===false|| hasPermissions(LYCHEE_UPLOADS_BIG)===false|| hasPermissions(LYCHEE_UPLOADS_THUMB)===false) { Log::error(Database::get(), __METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable'); + if ($returnOnError===true) return false; Response::error('An upload-folder is missing or not readable and writable!'); } @@ -649,6 +653,12 @@ final class Photo { // Get photo object $photo = $photos->fetch_assoc(); + // Photo not found? + if ($photo===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); + return false; + } + // Parse photo $photo['sysdate'] = date('d M. Y', substr($photo['id'], 0, -4)); if (strlen($photo['takestamp'])>1) $photo['takedate'] = date('d M. Y', $photo['takestamp']); @@ -676,6 +686,12 @@ final class Photo { // Get album object $album = $albums->fetch_assoc(); + // Photo not found? + if ($photo===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); + return false; + } + // Parse album $photo['public'] = ($album['public']==='1' ? '2' : $photo['public']); @@ -823,7 +839,7 @@ final class Photo { // Get photo object $photo = $photos->fetch_object(); - // Photo not found + // Photo not found? if ($photo===null) { Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); return false; @@ -977,6 +993,12 @@ final class Photo { // Get photo object $photo = $photos->fetch_object(); + // Photo not found? + if ($photo===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); + return false; + } + // Check if public if ($photo->public==='1') { @@ -1027,6 +1049,12 @@ final class Photo { // Get photo object $photo = $photos->fetch_object(); + // Photo not found? + if ($photo===null) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); + return false; + } + // Invert public $public = ($photo->public==0 ? 1 : 0); From 72b4321c0c019a7641e9b65d4fb2e1000301d637 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:38:04 +0100 Subject: [PATCH 088/183] Always response with Response::() --- php/Access/Admin.php | 46 +++++++++++++++++++++---------------------- php/Access/Guest.php | 14 ++++++------- src/scripts/api.js | 4 ++-- src/scripts/upload.js | 3 +-- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/php/Access/Admin.php b/php/Access/Admin.php index ea54194..99bbb35 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -88,7 +88,7 @@ final class Admin extends Access { Validator::required(isset($_POST['title']), __METHOD__); $album = new Album(null); - echo $album->add($_POST['title']); + Response::json($album->add($_POST['title'])); } @@ -97,7 +97,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumIDs'], $_POST['title']), __METHOD__); $album = new Album($_POST['albumIDs']); - echo $album->setTitle($_POST['title']); + Response::json($album->setTitle($_POST['title'])); } @@ -106,7 +106,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumID'], $_POST['description']), __METHOD__); $album = new Album($_POST['albumID']); - echo $album->setDescription($_POST['description']); + Response::json($album->setDescription($_POST['description'])); } @@ -115,7 +115,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumID'], $_POST['password'], $_POST['visible'], $_POST['downloadable']), __METHOD__); $album = new Album($_POST['albumID']); - echo $album->setPublic($_POST['public'], $_POST['password'], $_POST['visible'], $_POST['downloadable']); + Response::json($album->setPublic($_POST['public'], $_POST['password'], $_POST['visible'], $_POST['downloadable'])); } @@ -124,7 +124,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumIDs']), __METHOD__); $album = new Album($_POST['albumIDs']); - echo $album->delete(); + Response::json($album->delete()); } @@ -132,7 +132,7 @@ final class Admin extends Access { Validator::required(isset($_POST['albumIDs']), __METHOD__); $album = new Album($_POST['albumIDs']); - echo $album->merge(); + Response::json($album->merge()); } @@ -152,7 +152,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs'], $_POST['title']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->setTitle($_POST['title']); + Response::json($photo->setTitle($_POST['title'])); } @@ -161,7 +161,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoID'], $_POST['description']), __METHOD__); $photo = new Photo($_POST['photoID']); - echo $photo->setDescription($_POST['description']); + Response::json($photo->setDescription($_POST['description'])); } @@ -170,7 +170,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->setStar(); + Response::json($photo->setStar()); } @@ -179,7 +179,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoID']), __METHOD__); $photo = new Photo($_POST['photoID']); - echo $photo->setPublic(); + Response::json($photo->setPublic()); } @@ -188,7 +188,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs'], $_POST['albumID']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->setAlbum($_POST['albumID']); + Response::json($photo->setAlbum($_POST['albumID'])); } @@ -197,7 +197,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs'], $_POST['tags']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->setTags($_POST['tags']); + Response::json($photo->setTags($_POST['tags'])); } @@ -206,7 +206,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->duplicate(); + Response::json($photo->duplicate()); } @@ -215,7 +215,7 @@ final class Admin extends Access { Validator::required(isset($_POST['photoIDs']), __METHOD__); $photo = new Photo($_POST['photoIDs']); - echo $photo->delete(); + Response::json($photo->delete()); } @@ -223,10 +223,10 @@ final class Admin extends Access { private static function uploadAction() { - Validator::required(isset($_FILES, $_POST['albumID'], $_POST['tags']), __METHOD__); + Validator::required(isset($_FILES, $_POST['albumID']), __METHOD__); $photo = new Photo(null); - echo $photo->add($_FILES, $_POST['albumID'], '', $_POST['tags']); + Response::json($photo->add($_FILES, $_POST['albumID'])); } @@ -235,7 +235,7 @@ final class Admin extends Access { Validator::required(isset($_POST['url'], $_POST['albumID']), __METHOD__); $import = new Import(); - echo $import->url($_POST['url'], $_POST['albumID']); + Response::json($import->url($_POST['url'], $_POST['albumID'])); } @@ -272,14 +272,14 @@ final class Admin extends Access { Validator::required(isset($_POST['user'], $_POST['password']), __METHOD__); $session = new Session(); - echo $session->login($_POST['user'], $_POST['password']); + Response::json($session->login($_POST['user'], $_POST['password'])); } private static function logoutAction() { $session = new Session(); - echo $session->logout(); + Response::json($session->logout()); } @@ -290,7 +290,7 @@ final class Admin extends Access { Validator::required(isset($_POST['username'], $_POST['password']), __METHOD__); if (isset($_POST['oldPassword'])===false) $_POST['oldPassword'] = ''; - echo Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); + Response::json(Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password'])); } @@ -301,8 +301,8 @@ final class Admin extends Access { $sA = Settings::setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']); $sP = Settings::setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']); - if ($sA===true&&$sP===true) echo true; - else echo false; + if ($sA===true&&$sP===true) Response::json(true); + else Response::json(false); } @@ -310,7 +310,7 @@ final class Admin extends Access { Validator::required(isset($_POST['key']), __METHOD__); - echo Settings::setDropboxKey($_POST['key']); + Response::json(Settings::setDropboxKey($_POST['key'])); } diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 269fef3..64a764b 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -55,8 +55,8 @@ final class Guest extends Access { if ($album->getPublic()===true) { // Album public - if ($album->checkPassword($_POST['password'])) Response::json($album->get()); - else Response::warning('Wrong password!'); + if ($album->checkPassword($_POST['password'])===true) Response::json($album->get()); + else Response::warning('Wrong password!'); } else { @@ -76,13 +76,13 @@ final class Guest extends Access { if ($album->getPublic()===true) { // Album public - if ($album->checkPassword($_POST['password'])) echo true; - else echo false; + if ($album->checkPassword($_POST['password'])===true) Response::json(true); + else Response::json(false); } else { // Album private - echo false; + Response::json(false); } @@ -118,14 +118,14 @@ final class Guest extends Access { Validator::required(isset($_POST['user'], $_POST['password']), __METHOD__); $session = new Session(); - echo $session->login($_POST['user'], $_POST['password']); + Response::json($session->login($_POST['user'], $_POST['password'])); } private static function logoutAction() { $session = new Session(); - echo $session->logout(); + Response::json($session->logout()); } diff --git a/src/scripts/api.js b/src/scripts/api.js index 6ed4d2b..d45a007 100644 --- a/src/scripts/api.js +++ b/src/scripts/api.js @@ -27,8 +27,8 @@ api.post = function(fn, params, callback) { } // Convert 1 to true and an empty string to false - if (data==='1') data = true - else if (data==='') data = false + if (data==='true') data = true + else if (data==='false') data = false // Convert to JSON if string start with '{' and ends with '}' if (typeof data==='string' && data.substring(0, 1)==='{' && data.substring(data.length - 1, data.length)==='}') { diff --git a/src/scripts/upload.js b/src/scripts/upload.js index 9f546e7..45eb106 100755 --- a/src/scripts/upload.js +++ b/src/scripts/upload.js @@ -115,7 +115,6 @@ upload.start = { formData.append('function', 'Photo::add') formData.append('albumID', albumID) - formData.append('tags', '') formData.append(0, file) xhr.open('POST', api.path) @@ -128,7 +127,7 @@ upload.start = { file.ready = true // Set status - if (xhr.status===200 && xhr.responseText==='1') { + if (xhr.status===200 && xhr.responseText==='true') { // Success $('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status') From f00a3ddf92fe56b85343cb36f52963447541b35f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:38:09 +0100 Subject: [PATCH 089/183] Rebuild --- dist/main.js | Bin 192607 -> 192577 bytes dist/view.js | Bin 107011 -> 106998 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dist/main.js diff --git a/dist/main.js b/dist/main.js old mode 100644 new mode 100755 index ae6dcd81bebd31692233c09c4b8184c18d8fddcd..3938a3c038e9374fcf9c5236849cdba0082ace70 GIT binary patch delta 97 zcmccrfcxMB?uIRlzhCj^6;0xd23xKo%`|6jhX95zJYB&N52WV+zWhg0qmkR3vXALnTJv}{TKV>~3 zFghZ)hU)?LO#v~teK`V1gb5;aVP|t9EFvP8y1fEs0Wr5Ez5+Zj0ScF3?gAQV!Z delta 82 zcmex%n63E;Tf-K{h+>Vj(!Au7%=|nJ&FZ4mlG36)g`E7vl+3(zr^F(?jLei&4b55| mLj!~9?~575r#BTd`tTYm+1lEs+Nato8dxc9e_YHctOo!Sg&eQ| From c065d6100124e16e13b74c877d03bc8fe64bd00a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:47:30 +0100 Subject: [PATCH 090/183] Updated deps --- src/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/package.json b/src/package.json index fecdb82..2a8a0aa 100644 --- a/src/package.json +++ b/src/package.json @@ -14,19 +14,19 @@ "watch": "gulp watch" }, "devDependencies": { - "babel-preset-es2015": "^6.3.13", + "babel-preset-es2015": "^6.5.0", "basiccontext": "^3.5.1", - "basicmodal": "^3.3.2", - "gulp": "^3.9.0", + "basicmodal": "^3.3.3", + "gulp": "^3.9.1", "gulp-autoprefixer": "3.1.0", - "gulp-babel": "^6.1.1", + "gulp-babel": "^6.1.2", "gulp-concat": "^2.6.0", "gulp-inject": "^3.0.0", "gulp-load-plugins": "^1.2.0", "gulp-minify-css": "^1.2.3", "gulp-rimraf": "^0.2.0", - "gulp-sass": "^2.1.1", - "gulp-uglify": "^1.5.1", + "gulp-sass": "^2.2.0", + "gulp-uglify": "^1.5.2", "jquery": "^2.2.0", "mousetrap": "^1.5.3" } From 5aecee48738cd75f6374fec7710ed191ccabeee1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 13 Feb 2016 23:47:35 +0100 Subject: [PATCH 091/183] Rebuild --- dist/main.js | Bin 192577 -> 192532 bytes dist/view.js | Bin 106998 -> 106965 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 dist/main.js diff --git a/dist/main.js b/dist/main.js old mode 100755 new mode 100644 index 3938a3c038e9374fcf9c5236849cdba0082ace70..e7d74292cd8ae463b81fc72de8a01a2fb7753e0a GIT binary patch delta 72 zcmV-O0Js0a;0u)C3xKo%`|GzH>;Xmymww;@2$yU00c8OSx6t$fp+vWSIRf!FmvC_c eZvhIo-*Ez)e3QK13zvrO0%8I?3b*L)0$BmFfFGU! delta 107 zcmbR8fcxMB?uIRlzhBGeR3>Mnrs}1nCY7f9=BK2psU_#<73b%q>gD98You=f`I^y# zgOO{x;}^!>41)=N(h-_TBH8A{hZ# CRVtDI diff --git a/dist/view.js b/dist/view.js index c90f9b18ee606692552e94189d1d3058cd821c2f..8ecd07366b8e27e34a630a8a01aa963e8341c36f 100644 GIT binary patch delta 201 zcmex%nCSoS2iNk*cGVl3AvtsS_}HUeXkxTH|D6CPv@M>8YwfPH(Ck z6Hxt?^u0jNqzpqJplwICOkxD`!nf)11F5#7y*g|Gu{s4ssgoNHi!Rpt6bN*RzB8je scR-0|QEEwPQJzA;_DW~QY+gp+=}!X~GZ}ri`v)>|DsQhWVXV~!09vd=X#fBK delta 233 zcmcb5nC;tPwhePQ8GSd;8YwfPH(Ck z6Hxt?^u0jNqzpqJplwICOkxD`!nf)11F5#7y*g~Zu{s4ssgoNHi!Rpt6bN*RzB8je zw{MANQEEwPQJ#YD_DW~QY+lBI=}!X~GZ_Q6`v)>|D$D0oCTFCk>ZPP6m8SdVr=+T> YCFkcA=jWvA<>aSpq;3x@VXW5$0D%8a*8l(j From 46f520e1fe3d6b05f87c935d79b36859cde78af0 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 14 Feb 2016 14:09:49 +0100 Subject: [PATCH 092/183] Removed medium option Lychee will automatically create medium-sized photos when the photo ist big enough and Imagick installed and activated. It's no longer possible to deactivate it. --- docs/Settings.md | 6 ------ php/Modules/Photo.php | 4 +--- php/Modules/Session.php | 1 - php/database/settings_content.sql | 1 - php/database/update_020700.php | 13 ------------- 5 files changed, 1 insertion(+), 24 deletions(-) diff --git a/docs/Settings.md b/docs/Settings.md index 6bcd95f..c762708 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -52,12 +52,6 @@ This key is required to use the Dropbox import feature from your server. Lychee If `1`, Lychee will use Imagick when available. Disable [Imagick](http://www.imagemagick.org) if you have problems or if you are using an outdated version. Lychee will use [GD](http://php.net/manual/en/book.image.php) when Imagick is disabled or not available. -#### Medium - - medium = [0|1] - -If `1`, Lychee will create a second, smaller version of your photo. This feature requires [Imagick](http://www.imagemagick.org) on your server and an activated `imagick` option the the settings table. - #### Skip Duplicates on Upload skipDuplicates = [0|1] diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 5ecf2b3..a39202c 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -380,7 +380,7 @@ final class Photo { /** * Creates a smaller version of a photo when its size is bigger than a preset size. - * Photo must be big enough, medium must be activated and Imagick must be installed and activated. + * Photo must be big enough and Imagick must be installed and activated. * @return boolean Returns true when successful. */ private function createMedium($url, $filename, $width, $height) { @@ -413,11 +413,9 @@ final class Photo { } // Is photo big enough? - // Is medium activated? // Is Imagick installed and activated? if (($error===false)&& ($width>$newWidth||$height>$newHeight)&& - (Settings::get()['medium']==='1')&& (extension_loaded('imagick')&&Settings::get()['imagick']==='1')) { $newUrl = LYCHEE_UPLOADS_MEDIUM . $filename; diff --git a/php/Modules/Session.php b/php/Modules/Session.php index 7b6d105..0b846ad 100755 --- a/php/Modules/Session.php +++ b/php/Modules/Session.php @@ -50,7 +50,6 @@ final class Session { unset($return['config']['login']); unset($return['config']['location']); unset($return['config']['imagick']); - unset($return['config']['medium']); unset($return['config']['plugins']); } diff --git a/php/database/settings_content.sql b/php/database/settings_content.sql index 4074590..18067ff 100644 --- a/php/database/settings_content.sql +++ b/php/database/settings_content.sql @@ -9,7 +9,6 @@ VALUES ('checkForUpdates','1'), ('sortingPhotos','ORDER BY id DESC'), ('sortingAlbums','ORDER BY id DESC'), - ('medium','1'), ('imagick','1'), ('dropboxKey',''), ('identifier',''), diff --git a/php/database/update_020700.php b/php/database/update_020700.php index d59ea7f..eed5fd7 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -31,19 +31,6 @@ if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) { } -// Add medium to settings -$query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); -$result = Database::execute($connection, $query, 'update_020700', __LINE__); - -if ($result->num_rows===0) { - - $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS)); - $result = Database::execute($connection, $query, 'update_020700', __LINE__); - - if ($result===false) return false; - -} - // Set version if (Database::setVersion($connection, '020700')===false) return false; From 4c130211b1579a65ca406b31dd29601291c84903 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 14 Feb 2016 14:26:05 +0100 Subject: [PATCH 093/183] Replaced return false in database updates with error messages --- php/database/update_020700.php | 8 ++++---- php/database/update_030000.php | 11 +++++------ php/database/update_030001.php | 19 +++++++++---------- php/database/update_030003.php | 9 ++++----- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/php/database/update_020700.php b/php/database/update_020700.php index eed5fd7..5575d46 100644 --- a/php/database/update_020700.php +++ b/php/database/update_020700.php @@ -5,8 +5,7 @@ */ use Lychee\Modules\Database; - -if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); +use Lychee\Modules\Response; // Add medium to photos $query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS)); @@ -17,7 +16,7 @@ if ($result===false) { $query = Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS)); $result = Database::execute($connection, $query, 'update_020700', __LINE__); - if ($result===false) return false; + if ($result===false) Response::error('Could not add medium-field to database!'); } @@ -27,11 +26,12 @@ if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) { // Only create the folder when it is missing if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false) { Log::error($connection, 'update_020700', __LINE__, 'Could not create medium-folder'); + Response::error('Could not create medium-folder!'); } } // Set version -if (Database::setVersion($connection, '020700')===false) return false; +if (Database::setVersion($connection, '020700')===false) Response::error('Could not update version of database!'); ?> \ No newline at end of file diff --git a/php/database/update_030000.php b/php/database/update_030000.php index 3557be3..1832627 100644 --- a/php/database/update_030000.php +++ b/php/database/update_030000.php @@ -5,29 +5,28 @@ */ use Lychee\Modules\Database; - -if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); +use Lychee\Modules\Response; // Remove login // Login now saved as crypt without md5. Legacy code has been removed. $query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030000', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not reset username in database!'); $query = Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030000', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not reset password in database!'); // Make public albums private and reset password // Password now saved as crypt without md5. Legacy code has been removed. $query = Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS)); $result = Database::execute($connection, $query, 'update_030000', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not reset publicity of photos in database!'); // Set version -if (Database::setVersion($connection, '030000')===false) return false; +if (Database::setVersion($connection, '030000')===false) Response::error('Could not update version of database!'); ?> \ No newline at end of file diff --git a/php/database/update_030001.php b/php/database/update_030001.php index 9193fef..b3a0e25 100644 --- a/php/database/update_030001.php +++ b/php/database/update_030001.php @@ -5,33 +5,32 @@ */ use Lychee\Modules\Database; - -if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); +use Lychee\Modules\Response; // Change length of photo title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not change length of photo title in database!'); // Change length of album title $query = Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not change length of album title in database!'); // Add album sorting to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not get current album sorting from database!'); if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); - if ($result===false) return false; + if ($result===false) Response::error('Could not add album sorting to database!'); } @@ -39,13 +38,13 @@ if ($result->num_rows===0) { $query = Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not rename photo sorting row in database!'); // Add identifier to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not get current identifier from database!'); if ($result->num_rows===0) { @@ -53,11 +52,11 @@ if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier)); $result = Database::execute($connection, $query, 'update_030001', __LINE__); - if ($result===false) return false; + if ($result===false) Response::error('Could not add identifier to database!'); } // Set version -if (Database::setVersion($connection, '030001')===false) return false; +if (Database::setVersion($connection, '030001')===false) Response::error('Could not update version of database!'); ?> \ No newline at end of file diff --git a/php/database/update_030003.php b/php/database/update_030003.php index 95876d1..4e73862 100644 --- a/php/database/update_030003.php +++ b/php/database/update_030003.php @@ -5,25 +5,24 @@ */ use Lychee\Modules\Database; - -if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); +use Lychee\Modules\Response; // Add skipDuplicates to settings $query = Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030003', __LINE__); -if ($result===false) return false; +if ($result===false) Response::error('Could not get current skipDuplicates from database!'); if ($result->num_rows===0) { $query = Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS)); $result = Database::execute($connection, $query, 'update_030003', __LINE__); - if ($result===false) return false; + if ($result===false) Response::error('Could not add skipDuplicates to database!'); } // Set version -if (Database::setVersion($connection, '030003')===false) return false; +if (Database::setVersion($connection, '030003')===false) Response::error('Could not update version of database!'); ?> \ No newline at end of file From bad7819ff6b27575b3fa742a4f5abb69595e235f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 14 Feb 2016 14:49:51 +0100 Subject: [PATCH 094/183] Moved Album::getAll into a separated file --- php/Access/Admin.php | 13 ++- php/Access/Guest.php | 13 ++- php/Modules/Album.php | 173 --------------------------------- php/Modules/Albums.php | 191 +++++++++++++++++++++++++++++++++++++ src/scripts/albums.js | 2 +- src/scripts/contextMenu.js | 6 +- 6 files changed, 213 insertions(+), 185 deletions(-) create mode 100644 php/Modules/Albums.php diff --git a/php/Access/Admin.php b/php/Access/Admin.php index 99bbb35..927198b 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -3,6 +3,7 @@ namespace Lychee\Access; use Lychee\Modules\Album; +use Lychee\Modules\Albums; use Lychee\Modules\Import; use Lychee\Modules\Photo; use Lychee\Modules\Response; @@ -16,8 +17,10 @@ final class Admin extends Access { switch ($fn) { + // Albums functions + case 'Albums::get': self::getAlbumsAction(); break; + // Album functions - case 'Album::getAll': self::getAlbumsAction(); break; case 'Album::get': self::getAlbumAction(); break; case 'Album::add': self::addAlbumAction(); break; case 'Album::setTitle': self::setAlbumTitleAction(); break; @@ -65,15 +68,17 @@ final class Admin extends Access { } - // Album functions + // Albums functions private static function getAlbumsAction() { - $album = new Album(null); - Response::json($album->getAll(false)); + $albums = new Albums(); + Response::json($albums->get(false)); } + // Album functions + private static function getAlbumAction() { Validator::required(isset($_POST['albumID']), __METHOD__); diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 64a764b..84e3f69 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -3,6 +3,7 @@ namespace Lychee\Access; use Lychee\Modules\Album; +use Lychee\Modules\Albums; use Lychee\Modules\Photo; use Lychee\Modules\Response; use Lychee\Modules\Session; @@ -14,8 +15,10 @@ final class Guest extends Access { switch ($fn) { + // Albums functions + case 'Albums::get': self::getAlbumsAction(); break; + // Album functions - case 'Album::getAll': self::getAlbumsAction(); break; case 'Album::get': self::getAlbumAction(); break; case 'Album::getPublic': self::checkAlbumAccessAction(); break; @@ -37,15 +40,17 @@ final class Guest extends Access { } - // Album functions + // Albums functions private static function getAlbumsAction() { - $album = new Album(null); - Response::json($album->getAll(true)); + $albums = new Albums(); + Response::json($albums->get(true)); } + // Album functions + private static function getAlbumAction() { Validator::required(isset($_POST['albumID'], $_POST['password']), __METHOD__); diff --git a/php/Modules/Album.php b/php/Modules/Album.php index ebeeb50..e4915a1 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -180,179 +180,6 @@ final class Album { } - /** - * @return array|false Returns an array of albums or false on failure. - */ - public function getAll($public = true) { - - // Call plugins - Plugins::get()->activate(__METHOD__, 0, func_get_args()); - - // Initialize return var - $return = array( - 'smartalbums' => null, - 'albums' => null, - 'num' => 0 - ); - - // Get SmartAlbums - if ($public===false) $return['smartalbums'] = $this->getSmartInfo(); - - // Albums query - if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); - else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); - - // Execute query - $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - - if ($albums===false) return false; - - // For each album - while ($album = $albums->fetch_assoc()) { - - // Turn data from the database into a front-end friendly format - $album = Album::prepareData($album); - - // Thumbs - if (($public===true&&$album['password']==='0')|| - ($public===false)) { - - // Execute query - $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); - $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - - if ($thumbs===false) return false; - - // For each thumb - $k = 0; - while ($thumb = $thumbs->fetch_object()) { - $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; - $k++; - } - - } - - // Add to return - $return['albums'][] = $album; - - } - - // Num of albums - $return['num'] = $albums->num_rows; - - // Call plugins - Plugins::get()->activate(__METHOD__, 1, func_get_args()); - - return $return; - - } - - /** - * @return array|false Returns an array of smart albums or false on failure. - */ - private function getSmartInfo() { - - // Initialize return var - $return = array( - 'unsorted' => null, - 'public' => null, - 'starred' => null, - 'recent' => null - ); - - /** - * Unsorted - */ - - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $unsorted = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - $i = 0; - - if ($unsorted===false) return false; - - $return['unsorted'] = array( - 'thumbs' => array(), - 'num' => $unsorted->num_rows - ); - - while($row = $unsorted->fetch_object()) { - if ($i<3) { - $return['unsorted']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row->thumbUrl; - $i++; - } else break; - } - - /** - * Starred - */ - - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $starred = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - $i = 0; - - if ($starred===false) return false; - - $return['starred'] = array( - 'thumbs' => array(), - 'num' => $starred->num_rows - ); - - while($row3 = $starred->fetch_object()) { - if ($i<3) { - $return['starred']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row3->thumbUrl; - $i++; - } else break; - } - - /** - * Public - */ - - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $public = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - $i = 0; - - if ($public===false) return false; - - $return['public'] = array( - 'thumbs' => array(), - 'num' => $public->num_rows - ); - - while($row2 = $public->fetch_object()) { - if ($i<3) { - $return['public']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row2->thumbUrl; - $i++; - } else break; - } - - /** - * Recent - */ - - $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); - $recent = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - $i = 0; - - if ($recent===false) return false; - - $return['recent'] = array( - 'thumbs' => array(), - 'num' => $recent->num_rows - ); - - while($row3 = $recent->fetch_object()) { - if ($i<3) { - $return['recent']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row3->thumbUrl; - $i++; - } else break; - } - - // Return SmartAlbums - return $return; - - } - /** * Starts a download of an album. * @return resource|boolean Sends a ZIP-file or returns false on failure. diff --git a/php/Modules/Albums.php b/php/Modules/Albums.php new file mode 100644 index 0000000..e57ee84 --- /dev/null +++ b/php/Modules/Albums.php @@ -0,0 +1,191 @@ +activate(__METHOD__, 0, func_get_args()); + + // Initialize return var + $return = array( + 'smartalbums' => null, + 'albums' => null, + 'num' => 0 + ); + + // Get SmartAlbums + if ($public===false) $return['smartalbums'] = $this->getSmartAlbums(); + + // Albums query + if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); + + // Execute query + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) return false; + + // For each album + while ($album = $albums->fetch_assoc()) { + + // Turn data from the database into a front-end friendly format + $album = Album::prepareData($album); + + // Thumbs + if (($public===true&&$album['password']==='0')|| + ($public===false)) { + + // Execute query + $query = Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id'])); + $thumbs = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($thumbs===false) return false; + + // For each thumb + $k = 0; + while ($thumb = $thumbs->fetch_object()) { + $album['thumbs'][$k] = LYCHEE_URL_UPLOADS_THUMB . $thumb->thumbUrl; + $k++; + } + + } + + // Add to return + $return['albums'][] = $album; + + } + + // Num of albums + $return['num'] = $albums->num_rows; + + // Call plugins + Plugins::get()->activate(__METHOD__, 1, func_get_args()); + + return $return; + + } + + /** + * @return array|false Returns an array of smart albums or false on failure. + */ + private function getSmartAlbums() { + + // Initialize return var + $return = array( + 'unsorted' => null, + 'public' => null, + 'starred' => null, + 'recent' => null + ); + + /** + * Unsorted + */ + + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $unsorted = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $i = 0; + + if ($unsorted===false) return false; + + $return['unsorted'] = array( + 'thumbs' => array(), + 'num' => $unsorted->num_rows + ); + + while($row = $unsorted->fetch_object()) { + if ($i<3) { + $return['unsorted']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row->thumbUrl; + $i++; + } else break; + } + + /** + * Starred + */ + + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $starred = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $i = 0; + + if ($starred===false) return false; + + $return['starred'] = array( + 'thumbs' => array(), + 'num' => $starred->num_rows + ); + + while($row3 = $starred->fetch_object()) { + if ($i<3) { + $return['starred']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row3->thumbUrl; + $i++; + } else break; + } + + /** + * Public + */ + + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $public = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $i = 0; + + if ($public===false) return false; + + $return['public'] = array( + 'thumbs' => array(), + 'num' => $public->num_rows + ); + + while($row2 = $public->fetch_object()) { + if ($i<3) { + $return['public']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row2->thumbUrl; + $i++; + } else break; + } + + /** + * Recent + */ + + $query = Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS)); + $recent = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $i = 0; + + if ($recent===false) return false; + + $return['recent'] = array( + 'thumbs' => array(), + 'num' => $recent->num_rows + ); + + while($row3 = $recent->fetch_object()) { + if ($i<3) { + $return['recent']['thumbs'][$i] = LYCHEE_URL_UPLOADS_THUMB . $row3->thumbUrl; + $i++; + } else break; + } + + // Return SmartAlbums + return $return; + + } + +} + +?> \ No newline at end of file diff --git a/src/scripts/albums.js b/src/scripts/albums.js index 846046c..26f8ea7 100644 --- a/src/scripts/albums.js +++ b/src/scripts/albums.js @@ -17,7 +17,7 @@ albums.load = function() { if (albums.json===null) { - api.post('Album::getAll', {}, function(data) { + api.post('Albums::get', {}, function(data) { let waitTime = 0 diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index dab6918..fc1f245 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -90,7 +90,7 @@ contextMenu.albumMulti = function(albumIDs, e) { contextMenu.albumTitle = function(albumID, e) { - api.post('Album::getAll', {}, function(data) { + api.post('Albums::get', {}, function(data) { let items = [] @@ -121,7 +121,7 @@ contextMenu.albumTitle = function(albumID, e) { contextMenu.mergeAlbum = function(albumID, e) { - api.post('Album::getAll', {}, function(data) { + api.post('Albums::get', {}, function(data) { let items = [] @@ -238,7 +238,7 @@ contextMenu.move = function(photoIDs, e) { let items = [] - api.post('Album::getAll', {}, function(data) { + api.post('Albums::get', {}, function(data) { if (data.num===0) { From 78b42d0182e27f99a0d412757ac475acc0f72628 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 14 Feb 2016 18:33:55 +0100 Subject: [PATCH 095/183] Rebuild --- dist/main.js | Bin 192532 -> 192523 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index e7d74292cd8ae463b81fc72de8a01a2fb7753e0a..afaa59ea6c77080a4bd7eebf12f5d44596da6dd1 100644 GIT binary patch delta 94 zcmbR8fV=wvcf%IO^2cn&R#xe$CEM#CGhUE|al#pyJ~P5NLCj2VIAI(&UZ$*+=^G1~ hWEr`(pDSc~T{C_6J0@jDuIYtZOyb+WzGISS1OT+bBHI7} delta 118 zcmeBvz&+&wcf%IO^2Z!jR_UoFjyXBoYacUSkcD%n`!F*}ZO>(7y2%I^+YS_a!-?S9 z@iJwlFmg>lo5kcmJ-?WVb^G5!rY$v0)?Cv!zGG6J9xKblKD|JTNnrb%cTDn(0Qbo$ AV*mgE From c662e56ed9c2d281ea4f2e6dafc09df506c27100 Mon Sep 17 00:00:00 2001 From: klikini Date: Thu, 25 Feb 2016 19:44:45 -0600 Subject: [PATCH 096/183] Use a
for the login window --- src/scripts/lychee.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index c92699e..39b4f75 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -115,10 +115,10 @@ lychee.login = function(data) { lychee.loginDialog = function() { let msg = lychee.html` - +

Lychee $${ lychee.version }Update available!

` From dd5e2128d925773b04401e23ac15c0a5b20876d6 Mon Sep 17 00:00:00 2001 From: klikini Date: Thu, 25 Feb 2016 19:53:41 -0600 Subject: [PATCH 097/183] Add form attributes --- src/scripts/lychee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 39b4f75..31e27fe 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -115,7 +115,7 @@ lychee.login = function(data) { lychee.loginDialog = function() { let msg = lychee.html` - From 180b1397738988618fc615cf02e8b26399f3468d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 28 Feb 2016 12:10:29 +0100 Subject: [PATCH 098/183] Updated deps and build commands --- docs/Build.md | 6 +++--- src/package.json | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/Build.md b/docs/Build.md index acb0a09..678f2a6 100644 --- a/docs/Build.md +++ b/docs/Build.md @@ -2,7 +2,7 @@ First you have to install the following dependencies: -- `node` [Node.js](http://nodejs.org) v0.10 or later +- `node` [Node.js](http://nodejs.org) v5.7.0 or later - `npm` [Node Packaged Modules](https://www.npmjs.org) After [installing Node.js](http://nodejs.org) you can use the included `npm` package manager to download all dependencies: @@ -12,10 +12,10 @@ After [installing Node.js](http://nodejs.org) you can use the included `npm` pac ### Build -The Gulpfile is located in `src/` and can be executed using the `npm start` command. +The Gulpfile is located in `src/` and can be executed using the `npm run compile` command. ### Watch for changes While developing, you might want to use the following command to automatically build Lychee everytime you save a file: - npm run watch + npm start \ No newline at end of file diff --git a/src/package.json b/src/package.json index 2a8a0aa..0030bd2 100644 --- a/src/package.json +++ b/src/package.json @@ -10,8 +10,8 @@ "url": "https://github.com/electerious/Lychee.git" }, "scripts": { - "start": "gulp", - "watch": "gulp watch" + "start": "gulp watch", + "compile": "gulp" }, "devDependencies": { "babel-preset-es2015": "^6.5.0", @@ -23,11 +23,11 @@ "gulp-concat": "^2.6.0", "gulp-inject": "^3.0.0", "gulp-load-plugins": "^1.2.0", - "gulp-minify-css": "^1.2.3", + "gulp-minify-css": "^1.2.4", "gulp-rimraf": "^0.2.0", "gulp-sass": "^2.2.0", - "gulp-uglify": "^1.5.2", - "jquery": "^2.2.0", + "gulp-uglify": "^1.5.3", + "jquery": "^2.2.1", "mousetrap": "^1.5.3" } } From d90707c49fa0e08724b9b94ee46d18468f232ada Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 28 Feb 2016 12:14:44 +0100 Subject: [PATCH 099/183] Reverted #462 --- src/scripts/lychee.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 31e27fe..c92699e 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -115,10 +115,10 @@ lychee.login = function(data) { lychee.loginDialog = function() { let msg = lychee.html` - +

Lychee $${ lychee.version }Update available!

` From e8ebf13d091f42a2b3a0174c571ce5d2f2b53c81 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 4 Mar 2016 23:03:35 +0100 Subject: [PATCH 100/183] Fixed incorrect Imagick namespace #471 --- php/Modules/Photo.php | 1 + plugins/Diagnostics/index.php | 1 + 2 files changed, 2 insertions(+) diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index a39202c..9fabc8d 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -3,6 +3,7 @@ namespace Lychee\Modules; use ZipArchive; +use Imagick; final class Photo { diff --git a/plugins/Diagnostics/index.php b/plugins/Diagnostics/index.php index 3e7124b..307a774 100644 --- a/plugins/Diagnostics/index.php +++ b/plugins/Diagnostics/index.php @@ -9,6 +9,7 @@ namespace Diagnostics; use Mysqli; +use Imagick; use Lychee\Modules\Settings; $lychee = __DIR__ . '/../../'; From 2fb8ace3343cf8d29498915509b02e94de88fa52 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 5 Mar 2016 11:54:55 +0100 Subject: [PATCH 101/183] Updated PHP version in main readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77886e4..e7d1b2a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Lychee is a free photo-management tool, which runs on your server or web-space. ## Installation -To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. Follow the instructions to install Lychee on your server. [Installation »](docs/Installation.md) +To run Lychee, everything you need is a web-server with PHP 5.5 or later and a MySQL-Database. Follow the instructions to install Lychee on your server. [Installation »](docs/Installation.md) ## How to use From c7751f02310eececfeaa086ed43998b3d9eca4af Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 16:36:22 +0100 Subject: [PATCH 102/183] Move to next photo after after moving a picture #437 --- src/scripts/photo.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index a636938..92bd026 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -335,14 +335,12 @@ photo.setTitle = function(photoIDs) { photo.setAlbum = function(photoIDs, albumID) { - let nextPhoto - let previousPhoto + let nextPhoto = null + let previousPhoto = null if (!photoIDs) return false if (photoIDs instanceof Array===false) photoIDs = [ photoIDs ] - if (visible.photo) lychee.goto(album.getID()) - photoIDs.forEach(function(id, index, array) { // Change reference for the next and previous photo @@ -363,6 +361,11 @@ photo.setAlbum = function(photoIDs, albumID) { albums.refresh() + // Go to next photo if there is a next photo and + // next photo is not the current one. Show album otherwise. + if (visible.photo() && nextPhoto!=null && nextPhoto!==photo.getID()) lychee.goto(album.getID() + '/' + nextPhoto) + else if (!visible.albums()) lychee.goto(album.getID()) + let params = { photoIDs: photoIDs.join(), albumID From 84c37b9b35ddeed9d30653eae87cfaab40b26ef4 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 16:40:40 +0100 Subject: [PATCH 103/183] Fixed error when deleting last open photo in album --- src/scripts/photo.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index 92bd026..34e4d1c 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -192,8 +192,8 @@ photo.delete = function(photoIDs) { action.fn = function() { - let nextPhoto - let previousPhoto + let nextPhoto = null + let previousPhoto = null basicModal.close() @@ -219,8 +219,8 @@ photo.delete = function(photoIDs) { // Go to next photo if there is a next photo and // next photo is not the current one. Show album otherwise. - if (visible.photo() && nextPhoto!=='' && nextPhoto!==photo.getID()) lychee.goto(album.getID() + '/' + nextPhoto) - else if (!visible.albums()) lychee.goto(album.getID()) + if (visible.photo() && nextPhoto!=null && nextPhoto!==photo.getID()) lychee.goto(album.getID() + '/' + nextPhoto) + else if (!visible.albums()) lychee.goto(album.getID()) let params = { photoIDs: photoIDs.join() From b6b568b1467d2193bf4283b0fecfe91ee178f307 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 16:40:46 +0100 Subject: [PATCH 104/183] Rebuild --- dist/main.js | Bin 192523 -> 192553 bytes dist/view.js | Bin 106965 -> 106957 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index afaa59ea6c77080a4bd7eebf12f5d44596da6dd1..732153168dd81d8d0fbfa702a225897f262dc9c2 100644 GIT binary patch delta 11329 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 delta 11433 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 diff --git a/dist/view.js b/dist/view.js index 8ecd07366b8e27e34a630a8a01aa963e8341c36f..321d6b1b15b841469e83780e1f3c7431a7267f29 100644 GIT binary patch delta 337 zcmcb5nC-9F%}vcK(Mv8$ zO)N=u%}E9EG?Yq`@>436G&MJi^5wC!B--ZLPwo_z7PBhL&rDG;&{0xSw6#rCQ-g3P zFBi37&QnvHd|!0&=4P>GDON)zo&40v4^N0~Ry2IXCZL$AmzbPxNBc+CIyR@u1H1m~zH6CTp(g`zsm6x8E#hyvfI;s5pH= z3!~ih3vGz2F delta 390 zcmX?mnCA0TZ1#$VR*D9j+b#MQZI-xQlh3Q0s#ly`l%JCml3$=P zeXgy-@#}J z6FAwy=*4MkYpZAga`kkvPR1sv)b<&jj4G_c8hNETIkvVXH8n~~Ky@XWYHHih_A&0@ ll+geS Date: Sun, 6 Mar 2016 16:50:56 +0100 Subject: [PATCH 105/183] Default photo title now "Untitled" --- php/Modules/Photo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 9fabc8d..deb5953 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -882,7 +882,7 @@ final class Photo { * Sets the title of a photo. * @return boolean Returns true when successful. */ - public function setTitle($title) { + public function setTitle($title = 'Untitled') { // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); From e1dca6205aa2cae654e9cb5b3e5b58afe1ca6301 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 16:51:12 +0100 Subject: [PATCH 106/183] Removed Untitled fallback for empty album titles --- src/scripts/album.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 0eeb637..74eb318 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -110,8 +110,6 @@ album.add = function() { basicModal.close() - if (title.length===0) title = 'Untitled' - let params = { title } From e69c9acd1862a448021105c6c8a3597e8c7bc16f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 16:51:17 +0100 Subject: [PATCH 107/183] Rebuild --- dist/main.js | Bin 192553 -> 192524 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index 732153168dd81d8d0fbfa702a225897f262dc9c2..7654f70c8606ddf4baaa96718cf127a386842b61 100644 GIT binary patch delta 5626 zcmai24RjR8eSdS35R!#KNJ0|glNvQuLr_FN zjdsMOj7;<0l|SMOm{!$Y%iLPpZHhyJDlsW7>5>^``FpF5xSUz1&phvE@=i6N#N#Ss zf+|W>hG}(|siqUc*to<*39p%I3MN+h@yv_PxL0Q>WWe%QU%7+HMu4j6K{FLjbtS^^ zgh*vgN_b>B>GKJWwK&z&sz4=AJAR_Xd_GJuq#A>&U`SbkTI*&vR!}J+hP9-?tfASR z?QF`H5lzITJJo=xGE<-db2Ovoa$c|K^LhHF)=jMovloOY8qtLr@dzf^t_~}7z@W}- zlMlt$VhHaCslG#@tI~DII zC!s2cV>ia+a#Rq&8(4jD~KH# zNaHA0;+WQnrD#l=9K$1_I0mZ#s<}bSbF{&_w0I^W^q&?7P}cc-0PuVL&)mvSBd(_r z4Q(Y9tD2|4uw4^C$Vt9w4Dm%x~lMh8e zrbR`D8>Pm%ydjr!rWjTY1Tw7ny>73cS|3RPXDXkMS}kq2If1vm?J!nX8t8~1vLr>$ z28wftd>P)wURjnEZab_}rn-x52t@<|#h)UMp~;ZrQEFua&7Dlv0xUx{Q^1UHI*5fE z0G6CS&N>(th!w`8-o;oIv;H=)XcljivQrym*7d-CoYMX!3td%Am6v>}ZHTokk!b#} zfe`V=z0! zy$|C0+0s>|HB6Pfu+V7FdTO2~bj7!^4&fpi2{W`dBI z81XKGTSDHbmXKRf^Ltxk-mucv78VmxC5B@j?%oHpzw7Pikb^?D4f#vKlK_3&EpjKm4JXTkY0L&3R| zTCetg+RB{ppX3n4TG5r}ly?P1MpRh;dZ&nWeYvsD64&-QGmoxa65tV;Q2Rl%5kyXi zNl}F3u(TXme{=eLB{*y=(pQI74D|U??(3^-Vlfb{8BeLmJn3j}48aa# zy6gw`j`jKXu&$ubmlU#qE3ah)WGAWt1nq!OP~@>1S4;tzjVSJS4BS}Ka+K^d+S$M2eeAGMTC9dN}rH$70+jYAvA z*WC34hhTMoo%Pa|#duZSKPO+-ADUgx^h8YloEpniQ zMcwb8#JCpay|8=En4 z!dQp;QDZ?FxWmJ&Ul@TB7Rgu_SJmg6*ky>8iHE9e319N8kvm#$PFx)Sz?lII@vO{Q zSoR29e2k8~QH}uvdpOTNxJPxo`EPsLHe)y<3o#j&w+AwY+T#eDFbj)gf=AEg1Wl$~ zny7J*zR0a=JnJFR6#<|jNG2jw%;f+dYVF+1`QYKboiq3$gX56Ccx=DA7r|(KzPHzj z^xl1~O_NzH#3E)uH4I=*6+>I$9BO@S-{on*IM!v|-&K=;;42F8a^1u66ce3ehtS!M zOq)(j>{mzJFWEmoKlj1vnrS#Yesn>*Wy$0;VJZWx9NB5UekV_eVZWcQn37YX0hWHq z7U88I*wI_*l+bDmg0&jHT|??w{KeBQA9f z50q9iC|EhIj<{KV;}N$Di7NA48&?&FzUL`}f6gBJb`=0MwcdQ>QdNvIW4;C|#QdQFt+gw{b zbarJGR|gzHz$LXVo^8C9pK~z{AjYWmyR+>uDW2=cT)WTBMfv!-j(Q5br4tmQC8Upw z;}a=~S?`_;0CCmlkIXA-fYf(15 z`6$XGZ+?n0`1u0sLd7)emA4x3^v+v0%F(w|*y_7)tF9UZ7j&F5q|)0JrV1t}pl#O{ zG;!4<@K=m&GV}~|OiXSDg@L22)cbB2dH&imc=X?|J;DvX*Ms`m_m-pl^gRhJt?&E( ze;fIS-#>5*R?_sF%fNL0KR=Pm0R{K(Ee`bOuQvhqg$soAlyP9&jpgK9gxW_z#Iv1c zn}#+d=*V@z0kc1bUTb=nV4CqFHA-(-Kcf-L{P#}q0n$+@x!PxhKWh&V0Y z4RO%zU0Q^N&>U(Hvo0E@6EaWMqckQ7Y1}a>s6$PFE((>i$SaO0v;Sc>Q3)%AYe0 z3=_u@a`x7Gaz`a1PTZETH3JVQ2}p4-4d8gNU@BTSj)FNAq&hy#PJZR96y6M2JnE z`kb1wLpLz7{or!ag09alCqDdLTu$nHd9WyE7NUKk(vJ@YxKs=4k>Dqq0Q$-5A9Rzv zCOUh8GlALdAtDYs*TjsTW-2!m8QYd>$!aL#~5de*?qI9#$oZ-Ey zk^mP85C`M@?Zmdyf+*?O$k`B?U(Z{eokgZ zNkcXAj8qho6Oy&iatDbP;jzERIkn3@1c}W4q=$SFe{E~XHvD~c4S`~@UtEKC%zk4H zKav9JB?l4n_LE!4zjQkJGa<6BLy7NX(4>>M zf9P|rf2sUO?=h7mK)reJVMe__mm7*Y6=+t9p~EWwXp_Z*z4vZ{FJ$)VyGf+U=_1R} z-4mT~E0rJu@oYD2CB7L<3W`#^c(0>{bz8{~!E-jbhuk-vhVU_rhdaB6d=uW8zKuX+ z7sA^}7pW<3PZtqV2tfYffZ1P<4~5U8_1OC zXLvD9z67J~I(fNdKE6c2X`Xb{z(t4GOsD32(QwqJ-O5Pa4A2vuyz$Y(os9hHG#EVa zGN~ziI7(hCg}uMoP5z#f{3H9wR)`KkwVzItC577kgsebna(1VfO1c9Xlj|>AI0H6h zcJ>Sz4pP}m)uibSWxM2HCjivZv9wFh;v<9C&<0b^i!X3obuR77azS9vJImo&*m9OU zR95)-$D{&ZYwYV+$Yc0(?{c-mF(kR6EHVKA+b#vMRs9F*|(Pl|%m*PP-uK?MtU!zrf$KXZTa$ zl{2n?CgA%bEBU=1FYcxY_;aqU=+toDrIdiD?R_u1=GwnM;}Y#N=UqsT_RHs8=P~?i kKXSc+1>48su3Gzn4_(!G#p`H#`a>5Iap8>*T^maO2N|4*_W%F@ delta 5637 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 From 93a006600ca49672fb2e1eef32ed24452bc32858 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 17:38:13 +0100 Subject: [PATCH 108/183] Removed unused animation --- src/styles/_animations.scss | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/styles/_animations.scss b/src/styles/_animations.scss index d104dd9..7f8b3d5 100755 --- a/src/styles/_animations.scss +++ b/src/styles/_animations.scss @@ -65,18 +65,6 @@ } } -// PopIn -------------------------------------------------------------- // -@keyframes popIn { - 0% { - opacity: 0; - transform: scale(0); - } - 100% { - opacity: 1; - transform: scale(1); - } -} - // Pulse -------------------------------------------------------------- // @keyframes pulse { 0% { From 2bf985cd790570f9c3a92543f2071d38feff5f14 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 17:38:34 +0100 Subject: [PATCH 109/183] Code style adjustment --- src/scripts/password.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripts/password.js b/src/scripts/password.js index 6b28601..e3bf696 100644 --- a/src/scripts/password.js +++ b/src/scripts/password.js @@ -23,6 +23,7 @@ password.get = function(albumID, callback, passwd) { } else if (passwd==null) { // Request password + password.getDialog(albumID, callback) } else { From a0fdea6c4baaec5348fc13e715f823c49d63d461 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 17:38:50 +0100 Subject: [PATCH 110/183] Removed unused transitions --- src/styles/_imageview.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/_imageview.scss b/src/styles/_imageview.scss index 31ccd57..b376386 100644 --- a/src/styles/_imageview.scss +++ b/src/styles/_imageview.scss @@ -21,7 +21,7 @@ right: 30px; bottom: 30px; left: 30px; - transition: top .3s, right .3s, bottom .3s, left .3s, opacity .2s, transform .2s; + transition: top .3s, right .3s, bottom .3s, left .3s; will-change: transform; display: flex; From 48931fde5b41ea933b7cde877c6e20c8b79002c1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 17:48:40 +0100 Subject: [PATCH 111/183] Unnamed albums/photos now named "Untitled" in move album, merge album and switch album/photo menus --- src/scripts/contextMenu.js | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index fc1f245..1782cc0 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -100,10 +100,14 @@ contextMenu.albumTitle = function(albumID, e) { $.each(data.albums, function() { if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg' + if (this.title==='') this.title = 'Untitled' - let title = lychee.html`
$${ this.title }
` + let html = lychee.html`
$${ this.title }
` - if (this.id!=albumID) items.push({ title, fn: () => lychee.goto(this.id) }) + if (this.id!=albumID) items.push({ + title: html, + fn: () => lychee.goto(this.id) + }) }) @@ -130,10 +134,14 @@ contextMenu.mergeAlbum = function(albumID, e) { $.each(data.albums, function() { if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg' + if (this.title==='') this.title = 'Untitled' - let title = lychee.html`
$${ this.title }
` + let html = lychee.html`
$${ this.title }
` - if (this.id!=albumID) items.push({ title, fn: () => album.merge([ albumID, this.id ]) }) + if (this.id!=albumID) items.push({ + title: html, + fn: () => album.merge([ albumID, this.id ]) + }) }) @@ -206,9 +214,14 @@ contextMenu.photoTitle = function(albumID, photoID, e) { // Generate list of albums $.each(data.content, function(index) { - let title = lychee.html`
$${ this.title }
` + if (this.title==='') this.title = 'Untitled' - if (this.id!=photoID) items.push({ title, fn: () => lychee.goto(albumID + '/' + this.id) }) + let html = lychee.html`
$${ this.title }
` + + if (this.id!=photoID) items.push({ + title: html, + fn: () => lychee.goto(albumID + '/' + this.id) + }) }) @@ -253,10 +266,14 @@ contextMenu.move = function(photoIDs, e) { $.each(data.albums, function() { if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg' + if (this.title==='') this.title = 'Untitled' - let title = lychee.html`
$${ this.title }
` + let html = lychee.html`
$${ this.title }
` - if (this.id!=album.getID()) items.push({ title, fn: () => photo.setAlbum(photoIDs, this.id) }) + if (this.id!=album.getID()) items.push({ + title: html, + fn: () => photo.setAlbum(photoIDs, this.id) + }) }) From c59421057957e9e803d31b9b29e38b3890ce6468 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 17:57:41 +0100 Subject: [PATCH 112/183] Albums with empty titles are now allowed --- src/scripts/album.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 74eb318..e33e19a 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -206,6 +206,9 @@ album.delete = function(albumIDs) { if (album.json) albumTitle = album.json.title else if (albums.json) albumTitle = albums.getByID(albumIDs).title + // Fallback for album without a title + if (albumTitle==='') albumTitle = 'Untitled' + msg = lychee.html`

Are you sure you want to delete the album '$${ albumTitle }' and all of the photos it contains? This action can't be undone!

` } else { @@ -248,18 +251,13 @@ album.setTitle = function(albumIDs) { if (album.json) oldTitle = album.json.title else if (albums.json) oldTitle = albums.getByID(albumIDs).title - if (!oldTitle) oldTitle = '' - } const action = function(data) { - let newTitle = data.title - basicModal.close() - // Set title to Untitled when empty - newTitle = (newTitle==='') ? 'Untitled' : newTitle + let newTitle = data.title if (visible.album()) { @@ -317,7 +315,7 @@ album.setTitle = function(albumIDs) { album.setDescription = function(albumID) { - let oldDescription = album.json.description.replace(/'/g, ''') + let oldDescription = album.json.description const action = function(data) { @@ -564,17 +562,17 @@ album.merge = function(albumIDs) { // Get title of first album if (albums.json) title = albums.getByID(albumIDs[0]).title - if (!title) title = '' - title = title.replace(/'/g, ''') + // Fallback for first album without a title + if (title==='') title = 'Untitled' if (albumIDs.length===2) { // Get title of second album if (albums.json) sTitle = albums.getByID(albumIDs[1]).title - if (!sTitle) sTitle = '' - sTitle = sTitle.replace(/'/g, ''') + // Fallback for second album without a title + if (sTitle==='') sTitle = 'Untitled' msg = lychee.html`

Are you sure you want to merge the album '$${ sTitle }' into the album '$${ title }'?

` From 20963ac46316de7f7266d685d3d0879931e02d11 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:19:27 +0100 Subject: [PATCH 113/183] Replaced lychee.goto('') with lychee.goto() --- src/scripts/album.js | 4 ++-- src/scripts/header.js | 2 +- src/scripts/init.js | 2 +- src/scripts/lychee.js | 5 ++--- src/scripts/upload.js | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index e33e19a..15df334 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -55,7 +55,7 @@ album.load = function(albumID, refresh = false) { } else { // Album not public lychee.content.show() - lychee.goto('') + lychee.goto() } return false } @@ -178,7 +178,7 @@ album.delete = function(albumIDs) { } else { albums.refresh() - lychee.goto('') + lychee.goto() } diff --git a/src/scripts/header.js b/src/scripts/header.js index c8a9672..6c4b81c 100644 --- a/src/scripts/header.js +++ b/src/scripts/header.js @@ -52,7 +52,7 @@ header.bind = function() { header.dom('#button_trash') .on(eventName, function() { photo.delete([ photo.getID() ]) }) header.dom('#button_archive') .on(eventName, function() { album.getArchive(album.getID()) }) header.dom('#button_star') .on(eventName, function() { photo.setStar([ photo.getID() ]) }) - header.dom('#button_back_home') .on(eventName, function() { lychee.goto('') }) + header.dom('#button_back_home') .on(eventName, function() { lychee.goto() }) header.dom('#button_back') .on(eventName, function() { lychee.goto(album.getID()) }) header.dom('.header__search').on('keyup click', function() { search.find($(this).val()) }) diff --git a/src/scripts/init.js b/src/scripts/init.js index 612eeff..71520e5 100755 --- a/src/scripts/init.js +++ b/src/scripts/init.js @@ -68,7 +68,7 @@ $(document).ready(function() { if (basicModal.visible()===true) basicModal.cancel() else if (visible.contextMenu()) contextMenu.close() else if (visible.photo()) lychee.goto(album.getID()) - else if (visible.album()) lychee.goto('') + else if (visible.album()) lychee.goto() else if (visible.albums() && header.dom('.header__search').val().length!==0) search.reset() return false }) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index c92699e..78c4c53 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -156,10 +156,9 @@ lychee.logout = function() { } -lychee.goto = function(url) { +lychee.goto = function(url = '') { - if (url===undefined) url = '#' - else url = '#' + url + url = '#' + url history.pushState(null, null, url) lychee.load() diff --git a/src/scripts/upload.js b/src/scripts/upload.js index 45eb106..d99d6c1 100755 --- a/src/scripts/upload.js +++ b/src/scripts/upload.js @@ -386,7 +386,7 @@ upload.start = { // Go back to the album overview to show the imported albums if (visible.albums()) lychee.load() - else lychee.goto('') + else lychee.goto() basicModal.close() From 827f48c5a7047bef9f9f3b9d04cdf01a432459ce Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:19:35 +0100 Subject: [PATCH 114/183] Code style adjustment --- src/scripts/album.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 15df334..78650ad 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -157,11 +157,9 @@ album.delete = function(albumIDs) { action.fn = function() { - let params - basicModal.close() - params = { + let params = { albumIDs: albumIDs.join() } From b63c47cf9283f2b0ec94fecc1d01343d65c2aac3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:19:41 +0100 Subject: [PATCH 115/183] Updated deps --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 0030bd2..fd19306 100644 --- a/src/package.json +++ b/src/package.json @@ -14,7 +14,7 @@ "compile": "gulp" }, "devDependencies": { - "babel-preset-es2015": "^6.5.0", + "babel-preset-es2015": "^6.6.0", "basiccontext": "^3.5.1", "basicmodal": "^3.3.3", "gulp": "^3.9.1", From 45f8ff053e8af28c2d2e172712ea384d152ab6c3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:26:23 +0100 Subject: [PATCH 116/183] Replaced albums.load() with lychee.goto() --- src/scripts/album.js | 2 +- src/scripts/search.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 78650ad..60c503a 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -594,7 +594,7 @@ album.merge = function(albumIDs) { lychee.error(null, params, data) } else { albums.refresh() - albums.load() + lychee.goto() } }) diff --git a/src/scripts/search.js b/src/scripts/search.js index a723a1c..a75e613 100755 --- a/src/scripts/search.js +++ b/src/scripts/search.js @@ -94,7 +94,7 @@ search.reset = function() { search.hash = null lychee.animate('.divider', 'fadeOut') - albums.load() + lychee.goto() } From d31bbefbdc48ae866255ca6eda7cefeecfd44c67 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:32:03 +0100 Subject: [PATCH 117/183] Replaced lychee.goto('') with lychee.goto() --- src/scripts/photo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index 34e4d1c..5c54fb9 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -39,7 +39,7 @@ photo.load = function(photoID, albumID) { if (data==='Warning: Photo private!') { lychee.content.show() - lychee.goto('') + lychee.goto() return false } From 0096e2769f69bda37025932409e7a3943dde79dc Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 18:32:20 +0100 Subject: [PATCH 118/183] Wait for content to be loaded before showing photo --- src/scripts/photo.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/scripts/photo.js b/src/scripts/photo.js index 5c54fb9..a758948 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -24,6 +24,21 @@ photo.getID = function() { photo.load = function(photoID, albumID) { + const checkContent = function() { + if (album.json!=null) photo.load(photoID, albumID) + else setTimeout(checkContent, 100) + } + + const checkPasswd = function() { + if (password.value!=='') photo.load(photoID, albumID) + else setTimeout(checkPasswd, 200) + } + + if (album.json==null) { + checkContent() + return false + } + let params = { photoID, albumID, @@ -32,11 +47,6 @@ photo.load = function(photoID, albumID) { api.post('Photo::get', params, function(data) { - const checkPasswd = function() { - if (password.value!=='') photo.load(photoID, albumID) - else setTimeout(checkPasswd, 250) - } - if (data==='Warning: Photo private!') { lychee.content.show() lychee.goto() From a60b4cc45435e95a9c0b9aa8f42600e3af85fdf1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 20:34:44 +0100 Subject: [PATCH 119/183] Updated password functions. Returns to albums when pressing cancel. --- src/scripts/password.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/scripts/password.js b/src/scripts/password.js index e3bf696..4fc110a 100644 --- a/src/scripts/password.js +++ b/src/scripts/password.js @@ -9,7 +9,7 @@ password = { } -password.get = function(albumID, callback, passwd) { +password.get = function(albumID, callback) { if (lychee.publicMode===false) callback() else if (album.json && album.json.password==='0') callback() @@ -17,18 +17,25 @@ password.get = function(albumID, callback, passwd) { else if (!albums.json && !album.json) { // Continue without password + album.json = { password: true } callback('') - } else if (passwd==null) { + } else { // Request password password.getDialog(albumID, callback) - } else { + } - // Check password +} + +password.getDialog = function(albumID, callback) { + + const action = (data) => { + + let passwd = data.password let params = { albumID, @@ -49,16 +56,10 @@ password.get = function(albumID, callback, passwd) { } -} - -password.getDialog = function(albumID, callback) { - - const action = (data) => password.get(albumID, callback, data.password) - const cancel = () => { basicModal.close() - if (visible.albums()===false) lychee.goto() + if (!visible.albums()) lychee.goto() } From 2fed632b5cd2c2419e5ae1d5943d9f966b2be38c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 20:35:00 +0100 Subject: [PATCH 120/183] Show content when navigation to albums --- src/scripts/lychee.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 78c4c53..0deb8e7 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -217,6 +217,7 @@ lychee.load = function() { // Show Albums if (visible.photo()) view.photo.hide() + lychee.content.show() albums.load() } From 9117402035de99c2f0e4d4aaf7cb3670e7152e38 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 21:01:51 +0100 Subject: [PATCH 121/183] Return the correct insert_id when adding a new album --- php/Modules/Album.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/php/Modules/Album.php b/php/Modules/Album.php index e4915a1..d95e18b 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -33,15 +33,16 @@ final class Album { $visible = 1; // Database - $sysstamp = time(); - $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); - $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $sysstamp = time(); + $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + $insertID = Database::get()->insert_id; // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($result===false) return false; - return Database::get()->insert_id; + return $insertID; } From 0fc97da5666243d9d3b7bccafc740f9c62daf001 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 21:04:45 +0100 Subject: [PATCH 122/183] Rebuild --- dist/main.css | Bin 32019 -> 31529 bytes dist/main.js | Bin 192524 -> 192713 bytes dist/view.js | Bin 106957 -> 106955 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.css b/dist/main.css index 7edc009c68d977ae6e352ed9e987e1b4388a9587..3001289e740613b741e40c191a830ea570935131 100755 GIT binary patch delta 19 bcmbRIi*e;Q#tn;$jm;;OmTBhd=ouAHZU_}&0#bI~hEmAlIweJkdBth@MY&*A1f+q6FdA*n^WLow0JBXpZ~y=R diff --git a/dist/main.js b/dist/main.js index 7654f70c8606ddf4baaa96718cf127a386842b61..7f60134a246daca88f1a3a5367b4a40952e7f6af 100644 GIT binary patch delta 6452 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 delta 6412 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 Date: Sun, 6 Mar 2016 21:45:52 +0100 Subject: [PATCH 123/183] Updated version --- dist/main.js | Bin 192713 -> 192713 bytes src/package.json | 2 +- src/scripts/lychee.js | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/main.js b/dist/main.js index 7f60134a246daca88f1a3a5367b4a40952e7f6af..6dc76b63c56c05997ac6ed5d687ca0619450dddc 100644 GIT binary patch delta 44 zcmX^4ko)9A?uHh|Elk%eBnj13G847R_sV7k2>0D}?` An*aa+ delta 44 zcmX^4ko)9A?uHh|Elk%eBnj13G7EVsY2V7k2>0E8wG As{jB1 diff --git a/src/package.json b/src/package.json index fd19306..b69a91b 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "Lychee", - "version": "3.0.9", + "version": "3.1.0", "description": "Self-hosted photo-management done right.", "authors": "Tobias Reich ", "license": "MIT", diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 0deb8e7..30aca55 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -6,8 +6,8 @@ lychee = { title : document.title, - version : '3.0.9', - versionCode : '030009', + version : '3.1.0', + versionCode : '030100', updatePath : '//update.electerious.com/index.json', updateURL : 'https://github.com/electerious/Lychee', From d68d84e4e51892d3996814de4f3d1a1d8c2770b1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 6 Mar 2016 21:46:04 +0100 Subject: [PATCH 124/183] Added v3.1.0 to the changelog --- docs/Changelog.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 2ad8e32..058ab82 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,3 +1,29 @@ +## v3.1.0 + +Released March ??, 2016 + +**Warning**: It's no longer possible to update from Lychee versions older than 2.7. + +**Warning**: Plugin which use the plugin API of Lychee must be updated to work with the new back-end. + +**Notice**: It's no longer possible to edit the thumb quality in the database. + +**Notice**: It's no longer possible to disable the creation of medium-sized photos when Imagick is installed on the system. + +This updates includes a huge rewrite of the back-end. We are now using namespaces and the singleton pattern for Settings::get(), Database::get() and Plugins::get(). Everything is way better documented thanks to PHPDoc comments. Ugly `#` comments have been replaced with the more known `//`. Unused functions are gone and returns are more strict. We also added a handy module to output messages. Failed database updates and invalid queries will be saved to the log. + +- `New` Empty titles for albums +- `Improved` Error messages and log output +- `Improved` Back-end modules and plugins +- `Improved` Database connect function and update mechanism +- `Improved` Default photo title now "Untitled" +- `Improved` Move to next photo after after moving a picture (#437) +- `Improved` Return to album overview when canceling album password input +- `Fixed` session_start() after sending headers (#433) +- `Fixed` error when deleting last open photo in album +- `Fixed` Photo sometimes not loading when visiting directly +- `Fixed` Move album, merge album and switch album/photo menus no longer show empty titles for untitled albums/photos + ## v3.0.9 Released January 10, 2016 From b5e69ec7548d2ea728d20de150d67cc31d9cb1a3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Thu, 10 Mar 2016 23:10:06 +0100 Subject: [PATCH 125/183] New way to center the image in the imageview --- src/scripts/build.js | 4 ++-- src/styles/_imageview.scss | 26 +++++++++----------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/scripts/build.js b/src/scripts/build.js index 4b1f020..620d36f 100644 --- a/src/scripts/build.js +++ b/src/scripts/build.js @@ -120,11 +120,11 @@ build.imageview = function(data, visibleControls) { if (hasMedium===false) { - html += lychee.html`
` + html += lychee.html`` } else { - html += lychee.html`
` + html += lychee.html`` } diff --git a/src/styles/_imageview.scss b/src/styles/_imageview.scss index b376386..d50dc57 100644 --- a/src/styles/_imageview.scss +++ b/src/styles/_imageview.scss @@ -21,21 +21,25 @@ right: 30px; bottom: 30px; left: 30px; - transition: top .3s, right .3s, bottom .3s, left .3s; + margin: auto; + max-width: calc(100% - 60px); + max-height: calc(100% - 90px); + width: auto; + height: auto; + transition: top .3s, right .3s, bottom .3s, left .3s, max-width .3s, max-height .3s; will-change: transform; - display: flex; - justify-content: center; - align-items: center; - animation-name: zoomIn; animation-duration: .3s; animation-timing-function: $timingBounce; @media (max-width: 640px) { + top: 60px; right: 20px; bottom: 20px; left: 20px; + max-width: calc(100% - 40px); + max-height: calc(100% - 80px); } } @@ -44,20 +48,8 @@ right: 0; bottom: 0; left: 0; - } - - #image > div { - width: 0; - height: 0; - } - - #image img { - position: absolute; max-width: 100%; max-height: 100%; - width: auto; - height: auto; - transform: translate(-50%, -50%); } // Previous/Next Buttons -------------------------------------------------------------- // From d02b081fc7c20cc0a7937ef245d06f1b4ee89e5c Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Thu, 10 Mar 2016 23:10:20 +0100 Subject: [PATCH 126/183] Updated changelog text --- docs/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 058ab82..4e0d377 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,7 +4,7 @@ Released March ??, 2016 **Warning**: It's no longer possible to update from Lychee versions older than 2.7. -**Warning**: Plugin which use the plugin API of Lychee must be updated to work with the new back-end. +**Warning**: Plugins which use the plugin API of Lychee must be updated to work with the new back-end. **Notice**: It's no longer possible to edit the thumb quality in the database. From 029e0e9c43ea1759f4c42a72e19f9fadac9c3620 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Thu, 10 Mar 2016 23:10:28 +0100 Subject: [PATCH 127/183] Rebuild --- dist/main.css | Bin 31529 -> 31312 bytes dist/main.js | Bin 192713 -> 192625 bytes dist/view.js | Bin 106955 -> 106866 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.css b/dist/main.css index 3001289e740613b741e40c191a830ea570935131..ae100499cdb938d4d8042f3d85a5d3d3b89e5224 100755 GIT binary patch delta 190 zcmZ4ajq$=4#trt~I=P8O>6v*}iKQj^*13rly5*TEB^g%9i8;v{h6VmIK#trt~lV^JyOfCozW3-;Ume*|ZQBLp4jhsG{f0gl1_ED9YEaSsH+16*% z6WCTIIP+tw;)<|d}6mSv`vD?pfbDVb%}<(VlZ8CC|?8L64+86{Q*n939~ zbJHganh8%{?<*&64N;$1T9Oab0%A{g43y!}&^0ws)zLMboERvL;4}n^bHQW`R3``c L%4~k&o1p^$3w}lP diff --git a/dist/main.js b/dist/main.js index 6dc76b63c56c05997ac6ed5d687ca0619450dddc..b9ae00be300212076fdf323f877ab1a8162524ea 100644 GIT binary patch delta 157 zcmX^4ko)5U?uIRlS@W1PbJM3g&S#XE-an5~j#DXCCtAq{MQpm#0!ESPO7j_I5NbD0 zW|W#Y4WwPelZu*{S3L^k9Yc|aQ delta 241 zcmezPfcxY_?uIRlS@W1vGRvmt&SR9|v$Fv*?QAl0(-n$~lBe5FW0VrL(FcoxNu^kw zXeE#uoXT0j%BL$%WR#lzbsnQE+-x?8+0*Y&Wt5xlKA%wqkHHvfkxbowcRpi!2qV{Y zmoJPd+gE;JTwTM&l|P-aib;HWP9anHbg68n^zGV3Ox86_)?Cxm-Z7PKzx$493L^j+ C(o)U< diff --git a/dist/view.js b/dist/view.js index d0bb3d90804bb1856ad73c66c01c8e662c454716..c1dacec39ab05ff7c514806fa229f8273e47e55c 100644 GIT binary patch delta 128 zcmX?onC;UcwuUW?-{P4wbJM5$B```%FGygN<5Y^(iB_^f5u2`%!YDF*T>_&FLak#c qqtx`eL`D^K4R8stuI+~s8I{GRJ5@4@PybiWsKm&%U7><;wI%?YWheCj delta 218 zcmex#i0$-YwuUW?-{P55GRvkfOkkAYva&VjH1(<5*TIRCbL0Io}M4hC^!9b0;38ZqcPNCn7utKkx^NU$(n2W$1+BV V=}XHQ6{kP0WE9zcyPR>lCIFQdMz{a~ From 976635254e3eb8d2333e9e66760234ea24571b80 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 12 Mar 2016 23:51:33 +0100 Subject: [PATCH 128/183] Album id now based on the current microtime #27 --- php/Modules/Album.php | 14 +++++++------- php/Modules/Database.php | 3 ++- php/Modules/Photo.php | 6 ++---- php/database/albums_table.sql | 2 +- php/database/update_030100.php | 19 +++++++++++++++++++ php/helpers/generateID.php | 16 ++++++++++++++++ php/index.php | 1 + 7 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 php/database/update_030100.php create mode 100644 php/helpers/generateID.php diff --git a/php/Modules/Album.php b/php/Modules/Album.php index d95e18b..feb97ed 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -29,20 +29,20 @@ final class Album { Plugins::get()->activate(__METHOD__, 0, func_get_args()); // Properties - $public = 0; - $visible = 1; + $id = generateID(); + $sysstamp = time(); + $public = 0; + $visible = 1; // Database - $sysstamp = time(); - $query = Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible)); - $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - $insertID = Database::get()->insert_id; + $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, sysstamp, public, visible) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $id, $title, $sysstamp, $public, $visible)); + $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); if ($result===false) return false; - return $insertID; + return $id; } diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 91d9df7..60ee093 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -13,7 +13,8 @@ final class Database { '020700', // 2.7.0 '030000', // 3.0.0 '030001', // 3.0.1 - '030003' // 3.0.3 + '030003', // 3.0.3 + '030100' // 3.1.0 ); /** diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index deb5953..c7d20f3 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -139,8 +139,7 @@ final class Photo { } // Generate id - $id = str_replace('.', '', microtime(true)); - while(strlen($id)<14) $id .= 0; + $id = generateID(); // Set paths $tmp_name = $file['tmp_name']; @@ -1149,8 +1148,7 @@ final class Photo { while ($photo = $photos->fetch_object()) { // Generate id - $id = str_replace('.', '', microtime(true)); - while(strlen($id)<14) $id .= 0; + $id = generateID(); // Duplicate entry $values = array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id); diff --git a/php/database/albums_table.sql b/php/database/albums_table.sql index 8303b88..ea94d41 100644 --- a/php/database/albums_table.sql +++ b/php/database/albums_table.sql @@ -2,7 +2,7 @@ # ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS `?` ( - `id` int(11) NOT NULL AUTO_INCREMENT, + `id` bigint(14) NOT NULL, `title` varchar(100) NOT NULL DEFAULT '', `description` varchar(1000) DEFAULT '', `sysstamp` int(11) NOT NULL, diff --git a/php/database/update_030100.php b/php/database/update_030100.php new file mode 100644 index 0000000..428ba92 --- /dev/null +++ b/php/database/update_030100.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/php/helpers/generateID.php b/php/helpers/generateID.php new file mode 100644 index 0000000..80f42c1 --- /dev/null +++ b/php/helpers/generateID.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/php/index.php b/php/index.php index be39f8f..4bacbd7 100755 --- a/php/index.php +++ b/php/index.php @@ -20,6 +20,7 @@ require(__DIR__ . '/define.php'); require(__DIR__ . '/autoload.php'); require(__DIR__ . '/helpers/fastImageCopyResampled.php'); +require(__DIR__ . '/helpers/generateID.php'); require(__DIR__ . '/helpers/getExtension.php'); require(__DIR__ . '/helpers/getGraphHeader.php'); require(__DIR__ . '/helpers/getHashedString.php'); From 63d6ad2c6639832fba89a57bf567024cbdcbcadf Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 13 Mar 2016 00:27:17 +0100 Subject: [PATCH 129/183] Renamed visible to hidden #27 --- src/scripts/album.js | 21 ++++++++++----------- src/scripts/sidebar.js | 12 ++++++------ src/scripts/view.js | 6 +++--- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 60c503a..78be78d 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -391,11 +391,11 @@ album.setPublic = function(albumID, modal, e) {
-

Listed to visitors of your Lychee.

+

Only people with the direct link can view the album.

-

Only accessible with a valid password.

+

Album only accessible with a valid password.

@@ -431,9 +431,8 @@ album.setPublic = function(albumID, modal, e) { } }) - // Active visible by default (public = 0) - if ((album.json.public==='1' && album.json.visible==='1') || (album.json.public==='0')) $('.basicModal .choice input[name="visible"]').click() - if (album.json.downloadable==='1') $('.basicModal .choice input[name="downloadable"]').click() + if (album.json.public==='1' && album.json.visible==='0') $('.basicModal .choice input[name="hidden"]').click() + if (album.json.downloadable==='1') $('.basicModal .choice input[name="downloadable"]').click() $('.basicModal .choice input[name="password"]').on('change', function() { @@ -453,8 +452,8 @@ album.setPublic = function(albumID, modal, e) { album.json.public = '1' // Set visible - if ($('.basicModal .choice input[name="visible"]:checked').length===1) album.json.visible = '1' - else album.json.visible = '0' + if ($('.basicModal .choice input[name="hidden"]:checked').length===1) album.json.visible = '0' + else album.json.visible = '1' // Set downloadable if ($('.basicModal .choice input[name="downloadable"]:checked').length===1) album.json.downloadable = '1' @@ -482,12 +481,12 @@ album.setPublic = function(albumID, modal, e) { // Set data and refresh view if (visible.album()) { - album.json.visible = (album.json.public==='0') ? '0' : album.json.visible + album.json.visible = (album.json.public==='0') ? '1' : album.json.visible album.json.downloadable = (album.json.public==='0') ? '0' : album.json.downloadable album.json.password = (album.json.public==='0') ? '0' : album.json.password view.album.public() - view.album.visible() + view.album.hidden() view.album.downloadable() view.album.password() diff --git a/src/scripts/sidebar.js b/src/scripts/sidebar.js index 8f1770b..48fb2a9 100644 --- a/src/scripts/sidebar.js +++ b/src/scripts/sidebar.js @@ -223,7 +223,7 @@ sidebar.createStructure.album = function(data) { let editable = false let structure = {} let _public = '' - let visible = '' + let hidden = '' let downloadable = '' let password = '' @@ -242,14 +242,14 @@ sidebar.createStructure.album = function(data) { } - // Set value for visible + // Set value for hidden switch (data.visible) { - case '0' : visible = 'No' + case '0' : hidden = 'Yes' break - case '1' : visible = 'Yes' + case '1' : hidden = 'No' break - default : visible = '-' + default : hidden = '-' break } @@ -301,7 +301,7 @@ sidebar.createStructure.album = function(data) { type : sidebar.types.DEFAULT, rows : [ { title: 'Public', value: _public }, - { title: 'Visible', value: visible }, + { title: 'Hidden', value: hidden }, { title: 'Downloadable', value: downloadable }, { title: 'Password', value: password } ] diff --git a/src/scripts/view.js b/src/scripts/view.js index 02cc498..198a4fd 100644 --- a/src/scripts/view.js +++ b/src/scripts/view.js @@ -246,10 +246,10 @@ view.album = { }, - visible: function() { + hidden: function() { - if (album.json.visible==='1') sidebar.changeAttr('visible', 'Yes') - else sidebar.changeAttr('visible', 'No') + if (album.json.visible==='1') sidebar.changeAttr('hidden', 'No') + else sidebar.changeAttr('hidden', 'Yes') }, From 667f33c3a5ca75c145bb6945faa2c46181508670 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 13 Mar 2016 00:27:50 +0100 Subject: [PATCH 130/183] Rebuild --- dist/main.js | Bin 192625 -> 192610 bytes dist/view.js | Bin 106866 -> 106865 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/main.js b/dist/main.js index b9ae00be300212076fdf323f877ab1a8162524ea..db535973dee28bc7f45d5fa23b5ceefd80a21769 100644 GIT binary patch delta 1424 zcmX|BU2GIp6waBJVriiip)>;Rc3P)1bUJLsK-kH&6hxp%TLg(@*^;@lce`Wf&a6AL zTTB;;MjuQthRnm57=wxiBgSf$WE2YFNqrEbm`V_g3u2In4}DOg59*oHnoREb|IWGh zoHH|(x|@}{kBe2n%Hvh%7ql`hE)$I^7PUvctV(*B%DTEFGb8F6O|tUd+5*&~ld5Z( zB=f&rbQhR^q3#hN{!HBnkn(W-@#+?)dC7PRfpn^v?&Ag9@Jz=RnWQ2R@&8@gyqXC@ zn?n^NOO3IumSa;v*g_SLx}M1V^^I#65kU|m6pfWf8@DgU0w-Ipb0RC1ijJ9%#WhW1 zNhc*4j_sLtfvOp;Eq)}2Dh;ujUvBd>*2ibfbeh_{X~$42W;CYU*GLJb?WT%u7}Rw| zD)X7cZq^y+<%uJbtfMRQ)BGDvQHn%dcI31qJFy6*R1#TvMf;1Z@#3%dZCr}5o7%7z zLFnm;sQ**n4m63I+p**)Hje_5GyNL@-{$U?LJgY8&TaTy@9(^a{96NE$bU7^i)Y=g zJLvSsuG<`j{5V*Hk^ZfrIG!tpTVpJlNtH^Yv!@slZM$OVmLgID-#5G;<4zCX zTdZQV%rV7gz{*1TEU*)!9pz6j&qGZgx>ut@NRysixOP}LY za$XRM^8iHly9*oq6JD$Tt6RT@VE@s7&`DD_nN1;jS65aLa`@qJHF{qnc%%1V`FC&c zLcCjli9~bo?kg1z3w`<67~W&%*mV@jU%#ezE@L=x*waz!iF9t%`orDbM4?4$d#;47 zbG3O%iyAHFQO@di+M+GIc2f;sh z?lf`_Ox?t4ew*U4j3wu9*P`mr&$AeP=!?BIXenRnM$3&$?qCD+qSbN?Jz58ugvM&9 z#byVr1-2n6w*U_;{JsSSs!?ofhh`*+cE|t;-foA#8d+`M@}&(oSKFK2;$$sL)C)7 z$AhC4t||EF3OqblO!(3jcn{_)i(dt?InF0$Qz*~4j;$0;*CZCz_?|F#6;1*41kKmr z(tP;cYfv-Ye1N*VO7c`6Qw`mvd=H;6HGa?uhCbw)!q_KV12=c!a6_4Uw0l0^vlVXB clDYqojQ+fo2r9pD%j^HwA#(Ubg$o+~1H$U^TmS$7 delta 1354 zcmX|BU2GIp6waBJma_e!Xlq0NcDHpp(@uv)jg8$*e?UY^DXYb**>0P?vv<1__U>$E zX19lArLmR@rmRGe^^qXy>JqiM5LIZHq9^ISNQuZi?Q3q)RbT(!DN9E+>$DUEAwTc=6NyJ=+oX zDIeCt^SgJu)V|&SESiLYHY|B~U<#0YG1vq6Huv{r%Fsj(?8E2!Aw;FQAbBcU;j zn+>gQsUlR_HIW#PweQj-mOnp6OA)v(yi|f@bz-kef@BAlWRIvFz|LjW8q6|nAa9>B zly)Z0xE&W~;<_OONpPJ>D^@VAq{Ac<#DTC^tVX-hY{kH!84#Ep*9_Czo6wT6UM44_ z8+=4Ecs{!cz$Cjn^Q3*oYPEkeE1MbiAN@!47&XI*2%>j&C3rrK9}ZWo^(}(eS`X#_ zutv-AZi6}E&cTOo6*(;Q&67v*9xEqrp^*RKRJ3CU!HL73PEkvs8>2Q@IMmH#nx!er z6tQ)tvMDKUqXh%yL^KskQrC)-eW@^qS&x1B9%icl>SHKDRQt-s=5lu+G2C9h_}rQU zZ;xM^MQ-cd9jxZwoFB`mzI?X=Reyb*!05?uM$6EWzuJwKrK{#h4YAzS($%QD4iYP< zO;CZ&c32DSLy~U+Kaj#tEihDyqOT1ako2}e9GG*q4gRhr?nXULSfNSFTgySv@wWr^(;&ylA5GZC>?XTd)HymH>{Z!jd?BI>sl?{Fui)*dtA>L-r?i;51@tlYfx1J zhYQzkzz~4o_-=DMIi7dYMXrI%<(!qDVJC=A=q5Z`?qZN6EzI16k6=CD=>_mR;|t(% zLJLsmEH6N3;nV`W0?vzzQ0+7>!j%VMON&r;!>Rs^^Ez`ExUGen&$&9T+%47x?aXse jbZ`1PlS^E)^IDN>dZ0Orn#zp|{E~k}FMLhm8>#tmHhIzcT8baWn%NlOi4-2 L+rDKQ<326`U859w delta 41 zcmV+^0M`HU!Upof27t5yaFmyqj{zW;ER_KWx0sXx6#@rVX>(~}Y-P8zmI1yBbc+y$ From 5262a23ebbdae0d6fe5b16a24d95495ca1660897 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 13 Mar 2016 00:29:56 +0100 Subject: [PATCH 131/183] Updated description of hidden option #24 --- src/scripts/album.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/album.js b/src/scripts/album.js index 78be78d..109405f 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -395,7 +395,7 @@ album.setPublic = function(albumID, modal, e) { ${ build.iconic('check') } Hidden -

Only people with the direct link can view the album.

+

Only people with the direct link can view this album.