diff --git a/app/Services/GiteaService.php b/app/Services/GiteaService.php index e37b7da..bd40125 100644 --- a/app/Services/GiteaService.php +++ b/app/Services/GiteaService.php @@ -6,11 +6,34 @@ class GiteaService { private $cacheFile = null; private $config = []; + private $currentVersionNumber; - public function __construct() + public function __construct(array $config = null, $currentVersionNumber = null) { - $this->config = config('services.gitea'); - $this->cacheFile = storage_path('app/gitea_cache.txt'); + // This class is used in the Bootstrapper to fetch release information, therefore + // we need to check if the Laravel helper functions are loaded before we use them + if (is_null($config) && function_exists('config')) + { + $this->config = config('services.gitea'); + } + else + { + $this->config = $config; + } + + if (is_null($currentVersionNumber) && function_exists('config')) + { + $this->currentVersionNumber = config('app.version'); + } + else + { + $this->currentVersionNumber = $currentVersionNumber; + } + + if (function_exists('storage_path')) + { + $this->cacheFile = storage_path('app/gitea_cache.txt'); + } } public function checkForLatestRelease() @@ -26,7 +49,7 @@ class GiteaService { // Lookup and store the version information $statusCode = -1; - $result = $this->getLatestReleaseFromGitea($statusCode); + $result = $this->getReleasesFromGitea($statusCode); if ($statusCode == 200) { @@ -51,6 +74,31 @@ class GiteaService return $cacheData; } + public function getSpecificRelease($versionNumber) + { + $cacheData = null; + + // Lookup and store the version information + $statusCode = -1; + $result = $this->getReleasesFromGitea($statusCode); + + if ($statusCode == 200) + { + $releases = json_decode($result[1]); + + $foundRelease = null; + foreach ($releases as $release) + { + if (version_compare($release->tag_name, $versionNumber) === 0) + { + return $release; + } + } + } + + return null; + } + private function doesCacheExist() { $exists = file_exists($this->cacheFile); @@ -75,10 +123,10 @@ class GiteaService return json_decode(file_get_contents($this->cacheFile)); } - private function getLatestReleaseFromGitea(&$statusCode) + private function getReleasesFromGitea(&$statusCode) { $httpHeaders = [ - sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', config('app.version')) + sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', $this->currentVersionNumber) ]; if (isset($this->config['api_key']) && !empty($this->config['api_key'])) @@ -106,7 +154,11 @@ class GiteaService private function setCacheData($data) { - file_put_contents($this->cacheFile, json_encode(get_object_vars($data))); + if (!is_null($this->cacheFile)) + { + file_put_contents($this->cacheFile, json_encode(get_object_vars($data))); + } + return $data; } } \ No newline at end of file diff --git a/config/app.php b/config/app.php index 1f0f69e..62c7e52 100644 --- a/config/app.php +++ b/config/app.php @@ -2,7 +2,7 @@ return [ // Version number of Blue Twilight - 'version' => '2.2.0-beta.2', + 'version' => '2.1.2', /* |-------------------------------------------------------------------------- diff --git a/public/b2_test.php b/public/b2_test.php deleted file mode 100644 index a741604..0000000 --- a/public/b2_test.php +++ /dev/null @@ -1,143 +0,0 @@ -' . $uri . '

'; - - $server_output = curl_exec($session); // Let's do this! - - if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200) - { - echo '

' . $server_output . '

'; - } - else - { - echo '

' . (strlen($server_output) . ' bytes received') . '

'; // Tell me about the rabbits, George! - } - - curl_close ($session); // Clean up - - //$download_url = ""; // From b2_authorize_account call - $file_id = "4_z731245f41efc196b6dda0018_f116729ca6de74b38_d20190910_m132847_c002_v0001127_t0021"; // The ID of the file you want to download - $uri = $download_url . "/b2api/v2/b2_download_file_by_id?fileId=" . $file_id . '&Authorization=' . $auth_token; - - $session = curl_init($uri); - - curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET - curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response - - echo '

' . $uri . '

'; - - $server_output = curl_exec($session); // Let's do this! - - if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200) - { - echo '

' . $server_output . '

'; - } - else - { - echo '

' . (strlen($server_output) . ' bytes received') . '

'; // Tell me about the rabbits, George! - } - - curl_close ($session); // Clean up -} - -function b2_download_file_by_name($download_url, $auth_token) -{ - //$download_url = ""; // From b2_authorize_account call - $bucket_name = "andysh-bt-test"; // The NAME of the bucket you want to download from - $file_name = "B2-Test-Album/preview/7tgoy55do1vjv180ytlp.jpeg"; // The name of the file you want to download - $uri = $download_url . "/file/" . $bucket_name . "/" . $file_name; - - $session = curl_init($uri); - - curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET - curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response - - echo '

' . $uri . '

'; - - $server_output = curl_exec($session); // Let's do this! - - if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200) - { - echo '

' . $server_output . '

'; - } - else - { - echo '

' . (strlen($server_output) . ' bytes received') . '

'; // Tell me about the rabbits, George! - } - - curl_close ($session); // Clean up - - // You will need to use the account authorization token if your bucket's type is allPrivate. - - //$download_url = ""; // From b2_authorize_account call - $bucket_name = "andysh-bt-test"; // The NAME of the bucket you want to download from - $file_name = "B2-Test-Album/preview/7tgoy55do1vjv180ytlp.jpeg"; // The name of the file you want to download - //$auth_token = ""; // From b2_authorize_account call - $uri = $download_url . "/file/" . $bucket_name . "/" . $file_name . '?Authorization=' . $auth_token; - - $session = curl_init($uri); - - curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP POST - curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response - - echo '

' . $uri . '

'; - - $server_output = curl_exec($session); // Let's do this! - - if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200) - { - echo '

' . $server_output . '

'; - } - else - { - echo '

' . (strlen($server_output) . ' bytes received') . '

'; // Tell me about the rabbits, George! - } - - curl_close ($session); // Clean up -} - -?> -

b2_authorize_account

- - -

b2_download_file_by_name

-downloadUrl, $authorize_account_result->authorizationToken); ?> - -

b2_download_file_by_id

-downloadUrl, $authorize_account_result->authorizationToken); ?> diff --git a/public/bootstrap/composer.json b/public/bootstrap/composer.json new file mode 100644 index 0000000..27c2f40 --- /dev/null +++ b/public/bootstrap/composer.json @@ -0,0 +1,26 @@ +{ + "name": "aheathershaw/blue-twilight-bootstrapper", + "description": "Bootstrapper component for Blue Twilight - self-hosted photo gallery software.", + "keywords": [ + "blue", + "twilight", + "photo", + "photograph", + "portfolio", + "gallery", + "self-hosted" + ], + "license": "MIT", + "type": "project", + "require": { + "php": ">=7.2.0", + "ext-curl": "*", + "ext-json": "*" + }, + "autoload": { + "psr-4": { + "App\\": "../../app/", + "AppBootstrap\\": "src/" + } + } +} \ No newline at end of file diff --git a/public/bootstrap/helpers.php b/public/bootstrap/helpers.php new file mode 100644 index 0000000..867f9fc --- /dev/null +++ b/public/bootstrap/helpers.php @@ -0,0 +1,12 @@ += strlen($stringToFind) && + substr(strtolower($stringToCheck), strlen($stringToCheck) - strlen($stringToFind), strlen($stringToFind)) == strtolower($stringToFind); +} + +function starts_with($stringToCheck, $stringToFind) +{ + return strlen($stringToCheck) >= strlen($stringToFind) && + substr(strtolower($stringToCheck), 0, strlen($stringToFind)) == strtolower($stringToFind); +} \ No newline at end of file diff --git a/public/bootstrap/images/completed.svg b/public/bootstrap/images/completed.svg new file mode 100644 index 0000000..517ce74 --- /dev/null +++ b/public/bootstrap/images/completed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/bootstrap/images/loading.svg b/public/bootstrap/images/loading.svg new file mode 100644 index 0000000..c0f8953 --- /dev/null +++ b/public/bootstrap/images/loading.svg @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/public/bootstrap/images/waiting.svg b/public/bootstrap/images/waiting.svg new file mode 100644 index 0000000..f93f32a --- /dev/null +++ b/public/bootstrap/images/waiting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/bootstrap/index.php b/public/bootstrap/index.php new file mode 100644 index 0000000..da5781b --- /dev/null +++ b/public/bootstrap/index.php @@ -0,0 +1,25 @@ +handleRequest(); +} +catch (\Exception $ex) +{ + echo sprintf('ERROR: %s', $ex); +} \ No newline at end of file diff --git a/public/bootstrap/src/Bootstrapper.php b/public/bootstrap/src/Bootstrapper.php new file mode 100644 index 0000000..36f9e7e --- /dev/null +++ b/public/bootstrap/src/Bootstrapper.php @@ -0,0 +1,136 @@ +rootDir = dirname(__DIR__); + $this->configDir = sprintf('%s/config', dirname(dirname($this->rootDir))); + $this->tempDir = sprintf('%s/temp', $this->rootDir); + $this->viewsDir = sprintf('%s/views', $this->rootDir); + } + + public function handleRequest() + { + if (!isset($_GET['act'])) + { + $this->view('index', ['appName' => 'Blue Twilight Bootstrapper']); + } + else + { + switch (trim($_GET['act'])) + { + case 'download': + $this->download(); + return; + + default: + throw new \Exception(sprintf('ERROR: Action \'%s\' was not recognised.', $_GET['act'])); + } + } + } + + private function download() + { + $appConfig = require_once sprintf('%s/app.php', $this->configDir); + $servicesConfig = require_once sprintf('%s/services.php', $this->configDir); + + $versionNumber = sprintf('v%s', $appConfig['version']); + + $gitea = new GiteaService($servicesConfig['gitea'], $versionNumber); + $releaseInfo = $gitea->getSpecificRelease($versionNumber); + + if (is_null($releaseInfo)) + { + throw new \Exception(sprintf('No release info found in Gitea for Blue Twilight version \'%\'', $versionNumber)); + } + else if (!isset($releaseInfo->assets)) + { + throw new \Exception(sprintf('No assets found in Gitea for Blue Twilight version \'%\'', $versionNumber)); + } + + $vendorsPrefix = 'vendors'; + $vendorsSuffix = '.tar.gz'; + $selectedAsset = null; + foreach ($releaseInfo->assets as $asset) + { + /* + Ignore anything that is not "vendors.tar.gz" were the is also optional - e.g. + vendors_2.1.2.tar.gz + vendors.tar.gz + but NOT 2.1.2_vendors.zip + */ + if (!starts_with($asset->name, $vendorsPrefix) || !ends_with($asset->name, $vendorsSuffix)) + { + continue; + } + + $selectedAsset = $asset; + break; + } + + if (is_null($selectedAsset)) + { + throw new \Exception('No vendors.tar.gz found in Gitea for Blue Twilight version \'%\'', $versionNumber); + } + + $targetFileName = sprintf('%s/vendors.tar.gz', $this->tempDir); + + $this->downloadFile($selectedAsset->browser_download_url, $targetFileName); + var_dump('done'); + } + + private function downloadFile($sourceURL, $targetFilename) + { + $urlHandle = @fopen($sourceURL, 'r'); + $tempFilename = @fopen($targetFilename, 'w'); + + if ($urlHandle === false) + { + throw new \Exception(sprintf('Failed downloading the file from %s', $sourceURL)); + } + else if ($tempFilename === false) + { + throw new \Exception(sprintf('Failed opening the file \'%s\' for writing', $targetFilename)); + } + + while (!feof($urlHandle)) + { + $buffer = fread($urlHandle, 8192); + fwrite($tempFilename, $buffer); + } + + @fclose($urlHandle); + @fclose($tempFilename); + } + + private function view($name, array $viewData = []) + { + $viewFile = sprintf('%s/%s.php', $this->viewsDir, $name); + if (!file_exists($viewFile) || !is_readable($viewFile)) + { + throw new \Exception(sprintf('ERROR: View file \'%s\' does not exist.', $viewFile)); + } + + // Provide keys as variables - e.g. $viewData['something'] becomes accessible via $something + extract($viewData); + + require_once $viewFile; + } +} \ No newline at end of file diff --git a/public/bootstrap/temp/.gitignore b/public/bootstrap/temp/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/public/bootstrap/vendor/autoload.php b/public/bootstrap/vendor/autoload.php new file mode 100644 index 0000000..400d928 --- /dev/null +++ b/public/bootstrap/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath.'\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/public/bootstrap/vendor/composer/LICENSE b/public/bootstrap/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/public/bootstrap/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/public/bootstrap/vendor/composer/autoload_classmap.php b/public/bootstrap/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/public/bootstrap/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + array($baseDir . '/../../app'), + 'AppBootstrap\\' => array($baseDir . '/src'), +); diff --git a/public/bootstrap/vendor/composer/autoload_real.php b/public/bootstrap/vendor/composer/autoload_real.php new file mode 100644 index 0000000..60669ec --- /dev/null +++ b/public/bootstrap/vendor/composer/autoload_real.php @@ -0,0 +1,52 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/public/bootstrap/vendor/composer/autoload_static.php b/public/bootstrap/vendor/composer/autoload_static.php new file mode 100644 index 0000000..23bfb55 --- /dev/null +++ b/public/bootstrap/vendor/composer/autoload_static.php @@ -0,0 +1,36 @@ + + array ( + 'App\\' => 4, + 'AppBootstrap\\' => 13, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'App\\' => + array ( + 0 => __DIR__ . '/../..' . '/../../app', + ), + 'AppBootstrap\\' => + array ( + 0 => __DIR__ . '/../..' . '/src', + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::$prefixDirsPsr4; + + }, null, ClassLoader::class); + } +} diff --git a/public/bootstrap/views/index.php b/public/bootstrap/views/index.php new file mode 100644 index 0000000..641ab83 --- /dev/null +++ b/public/bootstrap/views/index.php @@ -0,0 +1,57 @@ + + + + + + + <?php echo $appName; ?> + + + +
+
+
+
+
+

+
+
+

Welcome to Blue Twilight - the self-hosted PHP photo gallery.

+ +
+

We need to download and install a few more files before you get started.

+

Click the "Let's Go" button below to begin.

+

+
+
+
    +
  • +
    + + + +
    + +
  • +
+
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/public/index.php b/public/index.php index 82fa173..7708cc8 100644 --- a/public/index.php +++ b/public/index.php @@ -10,7 +10,7 @@ /* Added by Andy - check to see if Composer/vendors are installed */ if (!file_exists(__DIR__.'/../vendor/autoload.php')) { - header('Location: install.php'); + header('Location: bootstrap/'); exit(); } /* End Added by Andy */ diff --git a/public/install.php b/public/install.php deleted file mode 100644 index 0e6de00..0000000 --- a/public/install.php +++ /dev/null @@ -1,256 +0,0 @@ -baseDirectory = dirname(__DIR__); - chdir($this->baseDirectory); - putenv('HOME=' . $this->baseDirectory); - - // Display errors so installer never gets a WSOD! - ini_set('display_errors', true); - } - - public function run() - { - if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') - { - // Handle post - $this->runInstall(); - exit(); - } -?> - - - Blue Twilight Setup - - -

Blue Twilight Setup

-

We need to download a few things - namely Composer and related packages - before we can kick off the Blue Twilight installer.

-

We can do this for you - simply click the button below.

-

This can take a few minutes so please be patient, and only click the button once!

-
- -
- -
-

Got Composer?

- -

If you already have Composer installed, however, you may want to use that instead. Just run the below commands on your server, changing the path to Composer as appropriate:

-

Please note: "composer.phar" may actually be "composer" on your system.

-
cd baseDirectory; ?>
/path/to/composer.phar install
- - - -

Installing Blue Twilight Setup Files

- -
    -%s...%s", $step[0], PHP_EOL); - $result = call_user_func([$this, $step[1]]); - - if (!$result) - { - $successful = false; - break; - } - } - - if ($successful) - { - header('Location: install/check'); - exit(); - } - -?> -
- 0) - { - $this->echoError(sprintf('The following PHP modules are missing and need to be installed to continue: %s', join(', ', $invalidModules))); - return false; - } - - return true; - } - - private function echoError($message) - { - echo sprintf("%s.%s", $message, PHP_EOL); - } - - private function echoOK($message = '') - { - echo "OK"; - - if (strlen($message) > 0) - { - echo sprintf('... %s', $message); - } - - echo '' . PHP_EOL; - } - - private function fetchComposerSignature() - { - if (!boolval(ini_get('allow_url_fopen'))) - { - $this->echoError('allow_url_fopen is disabled so we cannot use Composer'); - echo '
'; - $this->echoError('You will need to install the vendor libraries manually - see this page for more details'); - return false; - } - - $signatureUrl = 'https://composer.github.io/installer.sig'; - $this->composerSignature = trim(file_get_contents($signatureUrl)); - if (strlen($this->composerSignature) == 0) - { - $this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl)); - return false; - } - else - { - $this->echoOK($this->composerSignature); - } - - return true; - } - - private function generateAppKey() - { - if (!file_exists('.env') && file_exists('.env.example')) - { - copy('.env.example', '.env'); - } - - ob_start(); - system('touch .env', $rc); - $result = ob_get_clean(); - echo nl2br($result); - - ob_start(); - system('php artisan key:generate', $rc); - $result = ob_get_clean(); - echo nl2br($result); - - if ($rc != 0) - { - $this->echoError('Failed to generate application key'); - return false; - } - - $this->echoOK(); - return true; - } - - private function installComposer() - { - $rc = -1; - - ob_start(); - system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc); - $result = ob_get_clean(); - echo nl2br($result); - - if ($rc != 0) - { - $this->echoError('Failed to fetch Composer'); - return false; - } - - ob_start(); - system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Composer verification failed'); - return false; - } - - ob_start(); - system('php composer-setup.php', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Failed to install Composer'); - return false; - } - - ob_start(); - system('php -r "unlink(\'composer-setup.php\');"', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Failed to remove Composer setup file'); - return false; - } - - $this->echoOK(); - return true; - } - - private function runComposer() - { - ob_start(); - system('php composer.phar install', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Installing Composer packages failed'); - return false; - } - - $this->echoOK(); - return true; - } -} - -$installer = new BlueTwilightInstaller(); -$installer->run(); \ No newline at end of file diff --git a/public/update.php b/public/update.php deleted file mode 100644 index afcbd4c..0000000 --- a/public/update.php +++ /dev/null @@ -1,255 +0,0 @@ -baseDirectory = dirname(__DIR__); - chdir($this->baseDirectory); - putenv('HOME=' . $this->baseDirectory); - - // Display errors so installer never gets a WSOD! - ini_set('display_errors', true); - } - - public function run() - { - if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') - { - // Handle post - $this->runUpdate(); - exit(); - } - ?> - - - Blue Twilight Update - - -

Blue Twilight Update

-

This update routine ensures your Blue Twilight Composer packages are up-to-date.

-

To get started, simply click the button below.

-

This can take a few minutes so please be patient, and only click the button once!

-
- -
- -
-

Got Composer?

- -

If you already have Composer installed, however, you may want to use that instead. Just run the below commands on your server, changing the path to Composer as appropriate:

-

Please note: "composer.phar" may actually be "composer" on your system.

-
-cd baseDirectory; ?>
-
-php artisan clear-compiled
-php artisan cache:clear
-php artisan config:clear
-php artisan view:clear
-/path/to/composer.phar install
-        
- - - -

Updating Blue Twilight Composer packages

- -
    - %s...%s", $step[0], PHP_EOL); - $result = call_user_func([$this, $step[1]]); - - if (!$result) - { - $successful = false; - break; - } - } - - if ($successful) - { - header('Location: admin'); - exit(); - } - - ?> -
- echoError('allow_url_fopen is disabled so we cannot use Composer'); - echo '
'; - $this->echoError('You will need to install the vendor libraries manually - see this page for more details'); - return false; - } - - $signatureUrl = 'https://composer.github.io/installer.sig'; - $this->composerSignature = trim(file_get_contents($signatureUrl)); - if (strlen($this->composerSignature) == 0) - { - $this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl)); - return false; - } - else - { - $this->echoOK($this->composerSignature); - } - - return true; - } - - private function removeCompiledCached() - { - ob_start(); - system('php artisan clear-compiled', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('clear-compiled command failed'); - return false; - } - - ob_start(); - system('php artisan cache:clear', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('cache:clear command failed'); - return false; - } - - ob_start(); - system('php artisan config:clear', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('config:clear command failed'); - return false; - } - - ob_start(); - system('php artisan view:clear', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('view:clear command failed'); - return false; - } - - $this->echoOK(); - return true; - } - - private function echoError($message) - { - echo sprintf("%s.%s", $message, PHP_EOL); - } - - private function echoOK($message = '') - { - echo "OK"; - - if (strlen($message) > 0) - { - echo sprintf('... %s', $message); - } - - echo '' . PHP_EOL; - } - - private function installComposer() - { - $rc = -1; - - ob_start(); - system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc); - $result = ob_get_clean(); - echo nl2br($result); - - if ($rc != 0) - { - $this->echoError('Failed to fetch Composer'); - return false; - } - - ob_start(); - system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Composer verification failed'); - return false; - } - - ob_start(); - system('php composer-setup.php', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Failed to install Composer'); - return false; - } - - ob_start(); - system('php -r "unlink(\'composer-setup.php\');"', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Failed to remove Composer setup file'); - return false; - } - - $this->echoOK(); - return true; - } - - private function runComposer() - { - ob_start(); - system('php composer.phar --no-interaction install', $rc); - $result = ob_get_clean(); - echo nl2br($result); - if ($rc != 0) - { - $this->echoError('Updating Composer packages failed'); - return false; - } - - $this->echoOK(); - return true; - } -} - -$installer = new BlueTwilightUpdater(); -$installer->run(); \ No newline at end of file diff --git a/resources/js/bootstrapper.js b/resources/js/bootstrapper.js new file mode 100644 index 0000000..6a39dba --- /dev/null +++ b/resources/js/bootstrapper.js @@ -0,0 +1,71 @@ +/** + * This model is used by the system bootstrapper in public/bootstrap. + * @constructor + */ +function BootstrapperViewModel() { + this.el = '#bootstrapper'; + this.data = { + isCompleted: false, + isRunning: false, + operations: [] + } + this.methods = { + bootstrap() + { + this.operations.push({ + 'isCompleted': false, + 'isRunning': false, + 'name': 'Removing any previous versions', + 'url': '?act=removePrevious' + }); + + this.operations.push({ + 'isCompleted': false, + 'isRunning': false, + 'name': 'Downloading new files', + 'url': '?act=download' + }); + + this.operations.push({ + 'isCompleted': false, + 'isRunning': false, + 'name': 'Extracting new files', + 'url': '?act=extract' + }); + + this.operations.push({ + 'isCompleted': false, + 'isRunning': false, + 'name': 'Cleaning up', + 'url': '?act=cleanup' + }); + + this.isRunning = true; + + this.runOperation(this.operations[0], 0); + }, + runOperation(operation, index) + { + var self = this; + operation.isRunning = true; + + $.post(operation.url) + .done(function(result) + { + operation.isRunning = false; + operation.isCompleted = true; + + index++; + if (index < self.operations.length) + { + self.runOperation(self.operations[index], index); + } + else + { + //self.isRunning = false; + self.isCompleted = true; + } + }) + } + } +} \ No newline at end of file diff --git a/resources/sass/bootstrapper.scss b/resources/sass/bootstrapper.scss new file mode 100644 index 0000000..d0ff4d4 --- /dev/null +++ b/resources/sass/bootstrapper.scss @@ -0,0 +1,33 @@ +#bootstrapper +{ + .operation + { + .status + { + display: inline-block; + height: 32px; + width: 32px; + + i, + img + { + height: 100%; + width: 100%; + } + + span + { + display: inline-block; + height: 100%; + vertical-align: middle; + } + } + } + + ul + { + list-style-type: none; + margin: 0; + padding: 0; + } +} \ No newline at end of file