diff --git a/admin/debug/index.php b/admin/debug/index.php index 4b583a9d6..9241926b2 100644 --- a/admin/debug/index.php +++ b/admin/debug/index.php @@ -60,6 +60,7 @@ echo getNavItemDebug('myconfig'); echo getNavItemDebug('remotebuzzerlog'); echo getNavItemDebug('synctodrivelog'); +echo getNavItemDebug('remotestoragelog'); echo getNavItemDebug('devlog'); if (Environment::isLinux()) { echo getNavItemDebug('serverprocesses'); diff --git a/api/applyEffects.php b/api/applyEffects.php index 13a6893ef..c66ab727b 100644 --- a/api/applyEffects.php +++ b/api/applyEffects.php @@ -5,13 +5,13 @@ require_once '../lib/boot.php'; use Photobooth\Image; -use Photobooth\Helper; use Photobooth\Collage; use Photobooth\Enum\FolderEnum; use Photobooth\Enum\ImageFilterEnum; use Photobooth\Processor\ImageProcessor; use Photobooth\Service\DatabaseManagerService; use Photobooth\Service\LoggerService; +use Photobooth\Service\RemoteStorageService; use Photobooth\Utility\ImageUtility; use Photobooth\Utility\PathUtility; @@ -21,6 +21,7 @@ $logger->debug(basename($_SERVER['PHP_SELF'])); $database = DatabaseManagerService::getInstance(); +$remoteStorage = RemoteStorageService::getInstance(); $processor = null; @@ -279,106 +280,13 @@ } } - // send to ftp server + // Store images on remote storage if ($config['ftp']['enabled']) { - // init connection to ftp server - $ftp = ftp_ssl_connect($config['ftp']['baseURL'], $config['ftp']['port']); - - if ($ftp === false) { - $message = 'Failed to connect to FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); + $remoteStorage->write($remoteStorage->getStorageFolder() . '/images/' . $vars['singleImageFile'], (string) file_get_contents($vars['resultFile'])); + $remoteStorage->write($remoteStorage->getStorageFolder() . '/thumbs/' . $vars['singleImageFile'], (string) file_get_contents($vars['thumbFile'])); + if ($config['ftp']['create_webpage']) { + $remoteStorage->createWebpage(); } - ftp_set_option($ftp, FTP_TIMEOUT_SEC, 10); - - // login to ftp server - $login_result = ftp_login($ftp, $config['ftp']['username'], $config['ftp']['password']); - - if (!$login_result) { - $message = 'Can\'t connect to FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - // turn passive mode on to enable creation of folder and upload of files - ftp_pasv($ftp, true); - - $destination = empty($config['ftp']['baseFolder']) ? '' : DIRECTORY_SEPARATOR . $config['ftp']['baseFolder'] . DIRECTORY_SEPARATOR; - - $destination .= $config['ftp']['folder'] . DIRECTORY_SEPARATOR . Helper::slugify($config['ftp']['title']); - if ($config['ftp']['appendDate']) { - $destination .= DIRECTORY_SEPARATOR . date('Y/m/d'); - } - - // navigate trough folder on the server to the destination - @Helper::cdFTPTree($ftp, $destination); - - // upload processed picture into destination folder - $put_result = @ftp_put($ftp, $vars['singleImageFile'], $vars['resultFile'], FTP_BINARY); - - if (!$put_result) { - $message = 'Unable to save file on FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - // upload the thumbnail if enabled - if ($config['ftp']['upload_thumb']) { - $thumb_result = ftp_put($ftp, 'tmb_' . $vars['singleImageFile'], $vars['thumbFile'], FTP_BINARY); - if (!$thumb_result) { - $logger->error('Unable to load the thumbnail', $config['ftp']); - } - } - - // check if the webpage is enabled and is not already loaded on the ftp server - if ($config['ftp']['create_webpage'] && (!isset($_SESSION['ftpWebpageLoaded']) || $_SESSION['ftpWebpageLoaded'] != $config['ftp']['title'])) { - // if the date folder structure is appended, return to the main folder - if ($config['ftp']['appendDate']) { - @Helper::cdFTPTree($ftp, '../../../'); - } - - // another security check on the file in the server (e.g. 2-day event with the same ftp folder location) - $webpage_exist = ftp_size($ftp, 'index.php'); - if ($webpage_exist == -1) { - // get the index.php template file from the configured location - $webpage_template = file_get_contents($config['ftp']['template_location']); - - if ($webpage_template === false) { - throw new \Exception('File could not be read: ' . $config['ftp']['template_location']); - } - // set the {title} variable - $final_webpage = str_replace('{title}', $config['ftp']['title'], $webpage_template); - - // put the file into a stream - $stream = fopen('php://memory', 'r+'); - if ($stream === false) { - throw new \Exception('Could not put the file into a stream!'); - } - fwrite($stream, $final_webpage); - rewind($stream); - - // load the index.php result file in the ftp server - $upload_webpage = ftp_fput($ftp, 'index.php', $stream, FTP_BINARY); - - fclose($stream); - - if (!$upload_webpage) { - $message = 'Unable to save file on FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - // update the session variable to avoid unnecessary checks - $_SESSION['ftpWebpageLoaded'] = $config['ftp']['title']; - } - } - - // close the connection - @ftp_close($ftp); } // Change permissions diff --git a/api/deletePhoto.php b/api/deletePhoto.php index 35c6abdea..d11bf785d 100644 --- a/api/deletePhoto.php +++ b/api/deletePhoto.php @@ -6,15 +6,17 @@ use Photobooth\Enum\FolderEnum; use Photobooth\FileDelete; -use Photobooth\Helper; use Photobooth\Service\DatabaseManagerService; use Photobooth\Service\LoggerService; +use Photobooth\Service\RemoteStorageService; header('Content-Type: application/json'); $logger = LoggerService::getInstance()->getLogger('main'); $logger->debug(basename($_SERVER['PHP_SELF'])); +$remoteStorage = RemoteStorageService::getInstance(); + try { if (empty($_POST['file'])) { throw new \Exception('No file provided'); @@ -47,56 +49,8 @@ } if ($config['ftp']['enabled'] && $config['ftp']['delete']) { - $ftp = ftp_ssl_connect($config['ftp']['baseURL'], $config['ftp']['port']); - - if ($ftp === false) { - $message = 'Failed to connect to FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - // login to ftp server - $login_result = ftp_login($ftp, $config['ftp']['username'], $config['ftp']['password']); - - if (!$login_result) { - $message = 'Can\'t connect to FTP Server!'; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - $remote_dest = empty($config['ftp']['baseFolder']) ? '' : DIRECTORY_SEPARATOR . $config['ftp']['baseFolder'] . DIRECTORY_SEPARATOR; - - $remote_dest .= $config['ftp']['folder'] . DIRECTORY_SEPARATOR . Helper::slugify($config['ftp']['title']); - if ($config['ftp']['appendDate']) { - $remote_dest .= DIRECTORY_SEPARATOR . date('Y/m/d'); - } - - @Helper::cdFTPTree($ftp, $remote_dest); - - $delete_result = ftp_delete($ftp, $file); - - if (!$delete_result) { - $message = 'Unable to delete file on ftp server ' . $file; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - - if ($config['ftp']['upload_thumb']) { - $delete_result = ftp_delete($ftp, 'tmb_' . $file); - - if (!$delete_result) { - $message = 'Unable to delete thumb on ftp server ' . $file; - $logger->error($message, $config['ftp']); - echo json_encode(['error' => $message]); - die(); - } - } - - // close the connection - @ftp_close($ftp); + $remoteStorage->delete($remoteStorage->getStorageFolder() . '/images/' . $file); + $remoteStorage->delete($remoteStorage->getStorageFolder() . '/thumbs/' . $file); } if (!$logData['success'] || $config['dev']['loglevel'] > 1) { diff --git a/api/print.php b/api/print.php index 3a5635fe4..f21a10c9e 100644 --- a/api/print.php +++ b/api/print.php @@ -9,6 +9,7 @@ use Photobooth\Processor\PrintProcessor; use Photobooth\Service\LoggerService; use Photobooth\Service\PrintManagerService; +use Photobooth\Service\RemoteStorageService; use Photobooth\Utility\PathUtility; header('Content-Type: application/json'); @@ -96,14 +97,18 @@ } if ($config['print']['qrcode']) { - // create qr code - if ($config['ftp']['enabled'] && $config['ftp']['useForQr'] && isset($config['ftp']['processedTemplate'])) { - $imageHandler->qrUrl = $config['ftp']['processedTemplate'] . DIRECTORY_SEPARATOR . $vars['fileName']; - } elseif ($config['qr']['append_filename']) { - $imageHandler->qrUrl = PathUtility::getPublicPath($config['qr']['url'] . $vars['fileName'], true); - } else { - $imageHandler->qrUrl = PathUtility::getPublicPath($config['qr']['url'], true); + $url = $config['qr']['url']; + if ($config['ftp']['enabled'] && $config['ftp']['useForQr']) { + $remoteStorageService = RemoteStorageService::getInstance(); + $url = $remoteStorageService->getWebpageUri(); + if ($config['qr']['append_filename']) { + $url .= '/images/'; + } } + if ($config['qr']['append_filename']) { + $url .= $vars['fileName']; + } + $imageHandler->qrUrl = PathUtility::getPublicPath($url, true); $imageHandler->qrSize = $config['print']['qrSize']; $imageHandler->qrMargin = $config['print']['qrMargin']; $imageHandler->qrColor = $config['print']['qrBgColor']; diff --git a/api/qrcode.php b/api/qrcode.php index 48e97baf7..459cbe97d 100644 --- a/api/qrcode.php +++ b/api/qrcode.php @@ -2,21 +2,26 @@ /** @var array $config */ +use Photobooth\Service\RemoteStorageService; use Photobooth\Utility\PathUtility; use Photobooth\Utility\QrCodeUtility; require_once '../lib/boot.php'; $filename = (isset($_GET['filename']) && $_GET['filename']) != '' ? $_GET['filename'] : false; - -if ($filename || !$config['qr']['append_filename']) { - if ($config['ftp']['enabled'] && $config['ftp']['useForQr'] && isset($config['ftp']['processedTemplate'])) { - $url = $config['ftp']['processedTemplate'] . DIRECTORY_SEPARATOR . $filename; - } elseif ($config['qr']['append_filename']) { - $url = PathUtility::getPublicPath($config['qr']['url'] . $filename, true); - } else { - $url = PathUtility::getPublicPath($config['qr']['url'], true); +if ($filename) { + $url = $config['qr']['url']; + if ($config['ftp']['enabled'] && $config['ftp']['useForQr']) { + $remoteStorageService = RemoteStorageService::getInstance(); + $url = $remoteStorageService->getWebpageUri(); + if ($config['qr']['append_filename']) { + $url .= '/images/'; + } } + if ($config['qr']['append_filename']) { + $url .= $filename; + } + $url = PathUtility::getPublicPath($url, true); try { $result = QrCodeUtility::create($url); header('Content-Type: ' . $result->getMimeType()); @@ -28,6 +33,7 @@ echo $e->getMessage(); } } + } else { http_response_code(400); echo 'No filename defined.'; diff --git a/api/serverInfo.php b/api/serverInfo.php index 83b2f5c86..e1504be86 100644 --- a/api/serverInfo.php +++ b/api/serverInfo.php @@ -18,6 +18,8 @@ function handleDebugPanel(string $content, array $config): string|false return readFileContents(PathUtility::getAbsolutePath('var/log/remotebuzzer.log')); case 'nav-synctodrivelog': return readFileContents(PathUtility::getAbsolutePath('var/log/synctodrive.log')); + case 'nav-remotestoragelog': + return readFileContents(PathUtility::getAbsolutePath('var/log/remotestorage.log')); case 'nav-myconfig': echo implode("\n", showConfig($config)); return json_encode(''); diff --git a/api/testFtpConnection.php b/api/testFtpConnection.php index b603b1800..f653de66a 100644 --- a/api/testFtpConnection.php +++ b/api/testFtpConnection.php @@ -2,57 +2,23 @@ require_once '../lib/boot.php'; -use Photobooth\Service\LoggerService; +use Photobooth\Service\RemoteStorageService; header('Content-Type: application/json'); -$logger = LoggerService::getInstance()->getLogger('main'); -$logger->debug(basename($_SERVER['PHP_SELF'])); - -$data = $_POST; - -$params = ['baseURL', 'port', 'username', 'password']; - -$result = [ - 'response' => 'error', - 'message' => 'ftp:missing_parameters', - 'missing' => [], -]; - -foreach ($params as $param) { - if ($data['ftp'][$param] == '') { - $result['missing'][] = $param; - } -} - -if (!empty($result['missing'])) { - die(json_encode($result)); +$remoteStorage = RemoteStorageService::getInstance(); +if (!$remoteStorage->testConnection()) { + echo json_encode([ + 'response' => 'error', + 'message' => 'ftp:no_connection', + 'missing' => [], + ]); + exit(); } -$baseUrl = $data['ftp']['baseURL']; -$port = $data['ftp']['port']; -$username = $data['ftp']['username']; -$password = $data['ftp']['password']; - -// init connection to ftp server -$ftp = ftp_ssl_connect($baseUrl, $port, 10); - -if ($ftp === false) { - $logger->error('Can\'t connect to FTP Server!'); - $result['response'] = 'error'; - $result['message'] = 'ftp:no_connection'; - die(json_encode($result)); -} - -// login to ftp server -$login_result = @ftp_login($ftp, $username, $password); -$result['response'] = 'success'; -$result['message'] = 'ftp:connected'; - -if (!$login_result) { - $logger->error('Can\'t connect to FTP Server!'); - $result['response'] = 'error'; - $result['message'] = 'ftp:no_connection'; -} -@ftp_close($ftp); -die(json_encode($result)); +echo json_encode([ + 'response' => 'success', + 'message' => 'ftp:connected', + 'missing' => [], +]); +exit(); diff --git a/composer.json b/composer.json index f31346a55..54929aa41 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,9 @@ "ext-zip": "*", "endroid/qr-code": "^6.0", "league/commonmark": "^2.4", + "league/flysystem": "^3.29", + "league/flysystem-ftp": "^3.29", + "league/flysystem-sftp-v3": "^3.29", "monolog/monolog": "^3.5", "phpmailer/phpmailer": "^6.8", "symfony/asset": "^7.0", diff --git a/composer.lock b/composer.lock index ef7aa43cc..f4976341a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c012e64b954eed31b67cb869c94f5fcb", + "content-hash": "402763602881508fc9eed15a9f34f519", "packages": [ { "name": "bacon/bacon-qr-code", @@ -446,6 +446,293 @@ ], "time": "2022-12-11T20:36:23+00:00" }, + { + "name": "league/flysystem", + "version": "3.29.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + }, + "time": "2024-10-08T08:58:34+00:00" + }, + { + "name": "league/flysystem-ftp", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-ftp.git", + "reference": "17e8e422cb43a7fefa06ec8ddf36ee8ec936d138" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/17e8e422cb43a7fefa06ec8ddf36ee8ec936d138", + "reference": "17e8e422cb43a7fefa06ec8ddf36ee8ec936d138", + "shasum": "" + }, + "require": { + "ext-ftp": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Ftp\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "FTP filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "ftp", + "ftpd" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.29.0" + }, + "time": "2024-06-12T09:46:12+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + }, + "time": "2024-08-09T21:24:39+00:00" + }, + { + "name": "league/flysystem-sftp-v3", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-sftp-v3.git", + "reference": "ce9b209e2fbe33122c755ffc18eb4d5bd256f252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-sftp-v3/zipball/ce9b209e2fbe33122c755ffc18eb4d5bd256f252", + "reference": "ce9b209e2fbe33122c755ffc18eb4d5bd256f252", + "shasum": "" + }, + "require": { + "league/flysystem": "^3.0.14", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2", + "phpseclib/phpseclib": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\PhpseclibV3\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "SFTP filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "sftp" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-sftp-v3/tree/3.29.0" + }, + "time": "2024-08-14T19:35:54+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, { "name": "monolog/monolog", "version": "3.9.0", @@ -697,6 +984,123 @@ }, "time": "2024-08-07T15:39:19+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4|^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2024-05-08T12:36:18+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v6.9.3", @@ -778,6 +1182,116 @@ ], "time": "2024-11-24T18:04:13+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.42", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.42" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-09-16T03:06:04+00:00" + }, { "name": "psr/container", "version": "2.0.2", diff --git a/docs/faq/index.md b/docs/faq/index.md index 46bd3c238..65343245c 100644 --- a/docs/faq/index.md +++ b/docs/faq/index.md @@ -1002,8 +1002,6 @@ The next variables are for the place where you want the pictures to be stored: - `baseFolder` is the folder of your website (if you have multiple websites living on the server with this property you can choose on which of these the file should be stored) - `folder` the folder dedicated to the upload of the files - `title` if you are doing an event you can set the title of the event to create another folder (the system will slugify the string) -- `appendDate` just like a simple blog websites, when articles are uploaded, the date is added to the url as the path. So if you want, the system will create a set of folder with this template: yyyy/mm/dd -- `upload_thumb` if you want you can upload next to the processed picture also the thumbnails In the end the processed picture, and the thumbnails, will be uploaded in the folder according to these variables. diff --git a/lib/boot.php b/lib/boot.php index ff5139e84..fa0194d35 100644 --- a/lib/boot.php +++ b/lib/boot.php @@ -10,6 +10,7 @@ use Photobooth\Service\MailService; use Photobooth\Service\PrintManagerService; use Photobooth\Service\ProcessService; +use Photobooth\Service\RemoteStorageService; use Photobooth\Service\SoundService; use Photobooth\Utility\FileUtility; use Photobooth\Utility\PathUtility; @@ -76,6 +77,7 @@ $GLOBALS[DatabaseManagerService::class] = new DatabaseManagerService(); $GLOBALS[MailService::class] = new MailService(); $GLOBALS[ProcessService::class] = new ProcessService(); +$GLOBALS[RemoteStorageService::class] = new RemoteStorageService(); $config = ConfigurationService::getInstance()->getConfiguration(); if ($config['dev']['loglevel'] > 0) { diff --git a/lib/configsetup.inc.php b/lib/configsetup.inc.php index d676d835b..a32df6418 100644 --- a/lib/configsetup.inc.php +++ b/lib/configsetup.inc.php @@ -3,6 +3,7 @@ use Photobooth\Enum\CollageLayoutEnum; use Photobooth\Enum\ImageFilterEnum; use Photobooth\Enum\MailSecurityTypeEnum; +use Photobooth\Enum\RemoteStorageTypeEnum; use Photobooth\Enum\TimezoneEnum; use Photobooth\Service\ConfigurationService; use Photobooth\Service\LanguageService; @@ -2437,33 +2438,41 @@ 'name' => 'ftp[enabled]', 'value' => $config['ftp']['enabled'], ], + 'type' => [ + 'view' => 'advanced', + 'type' => 'select', + 'name' => 'ftp[type]', + 'placeholder' => $defaultConfig['ftp']['type'], + 'options' => RemoteStorageTypeEnum::cases(), + 'value' => $config['ftp']['type'], + ], 'baseURL' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => 'ftp.photobooth.com', 'name' => 'ftp[baseURL]', - 'value' => htmlentities($config['ftp']['baseURL'] ?? ''), + 'value' => $config['ftp']['baseURL'], ], 'port' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => $defaultConfig['ftp']['port'], 'name' => 'ftp[port]', - 'value' => htmlentities($config['ftp']['port'] ?? ''), + 'value' => $config['ftp']['port'], ], 'username' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => '', 'name' => 'ftp[username]', - 'value' => htmlentities($config['ftp']['username'] ?? ''), + 'value' => $config['ftp']['username'], ], 'password' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => '', 'name' => 'ftp[password]', - 'value' => htmlentities($config['ftp']['password'] ?? ''), + 'value' => $config['ftp']['password'], ], 'test_connection' => [ 'view' => 'basic', @@ -2477,27 +2486,21 @@ 'type' => 'input', 'placeholder' => 'mysite', 'name' => 'ftp[baseFolder]', - 'value' => htmlentities($config['ftp']['baseFolder'] ?? ''), + 'value' => $config['ftp']['baseFolder'], ], 'folder' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => 'photobooth', 'name' => 'ftp[folder]', - 'value' => htmlentities($config['ftp']['folder'] ?? ''), + 'value' => $config['ftp']['folder'], ], 'title' => [ 'view' => 'advanced', 'type' => 'input', 'placeholder' => '', 'name' => 'ftp[title]', - 'value' => htmlentities($config['ftp']['title'] ?? ''), - ], - 'appendDate' => [ - 'view' => 'basic', - 'type' => 'checkbox', - 'name' => 'ftp[appendDate]', - 'value' => $config['ftp']['appendDate'], + 'value' => $config['ftp']['title'], ], 'useForQr' => [ 'view' => 'basic', @@ -2510,14 +2513,14 @@ 'type' => 'input', 'placeholder' => 'https://photobooth.com', 'name' => 'ftp[website]', - 'value' => htmlentities($config['ftp']['website'] ?? ''), + 'value' => $config['ftp']['website'], ], 'urlTemplate' => [ 'view' => 'advanced', 'type' => 'input', - 'placeholder' => '%website/%folder/%title/', + 'placeholder' => '%website%/%folder%/%title%', 'name' => 'ftp[urlTemplate]', - 'value' => htmlentities($config['ftp']['urlTemplate'] ?? ''), + 'value' => $config['ftp']['urlTemplate'], ], 'create_webpage' => [ 'view' => 'basic', @@ -2528,15 +2531,9 @@ 'template_location' => [ 'view' => 'advanced', 'type' => 'input', - 'placeholder' => '/resources/template/index.php', + 'placeholder' => 'resources/template/index.php', 'name' => 'ftp[template_location]', - 'value' => htmlentities($config['ftp']['template_location'] ?? ''), - ], - 'upload_thumb' => [ - 'view' => 'basic', - 'type' => 'checkbox', - 'name' => 'ftp[upload_thumb]', - 'value' => $config['ftp']['upload_thumb'], + 'value' => $config['ftp']['template_location'], ], 'delete' => [ 'view' => 'basic', diff --git a/resources/lang/en.json b/resources/lang/en.json index 23bd32699..97ae38c0a 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -130,7 +130,9 @@ "devlog": "Photobooth log", "disk_usage": "Disk Usage", "dot": ".", + "download": "Download", "download_zip": "Download data folder as zip", + "download_confirmation_images": "%s images will be downloaded. Do you want to proceed?", "enjoyPhotobooth": "Enjoy your Photobooth!", "error": "Something went wrong. Please try it again.", "error_path_noFonts": "The path does not contain any fonts", @@ -164,7 +166,6 @@ "frontpage:ui_show_fork": "Show Fork Badge", "frontpage:ui_skip_welcome": "Skip welcome screen", "ftp": "FTP Server", - "ftp:appendDate": "Add date as folder structure", "ftp:baseFolder": "Base folder", "ftp:baseURL": "Server URL", "ftp:connected": "Successfully connected to the FTP server.", @@ -178,8 +179,7 @@ "ftp:port": "FTP-Server port", "ftp:template_location": "Template file location", "ftp:test_connection": "Test connection", - "ftp:title": "Sub-folder name", - "ftp:upload_thumb": "Upload thumbnails", + "ftp:title": "Title", "ftp:urlTemplate": "Url template for qr generation", "ftp:useForQr": "Use the output from the FTP server as input to generate the QR code", "ftp:username": "Username", @@ -388,7 +388,6 @@ "manual:frontpage:ui_admin_shortcut_position": "Choose the position of the admin shortcut.", "manual:frontpage:ui_show_fork": "If enabled, a fork badge is shown on the right upper corner on the start screen.", "manual:frontpage:ui_skip_welcome": "If enabled, the welcome screen won't be visible while accessing Photobooth the first time after installation / update.", - "manual:ftp:appendDate": "If enabled, this add another folder structure to your ftp server with the formate /YYYY/MM/DD.", "manual:ftp:baseFolder": "FTP Server base folder (if you have multiple sites active on the same hosting).", "manual:ftp:baseURL": "FTP Server base URL.", "manual:ftp:create_webpage": "Create a webpage starting from the file index.php that function as a gallery on the base folder.", @@ -400,7 +399,6 @@ "manual:ftp:template_location": "Location of the index.php file. Choose another location to use a custom index.php file. REMEMBER: the file has to have a {title} placeholder.", "manual:ftp:test_connection": "Will execute a test connection to the FTP server using the data passed.", "manual:ftp:title": "Title of the sub-folder. It will be appended to folder. If website is enabled it will be used on the html title tag and in the page header.", - "manual:ftp:upload_thumb": "If enabled, thumbnails will also be uploaded to the ftp server to allow better loading of the webpage.", "manual:ftp:urlTemplate": "Set the url template to generate the qr code. The placeholder are '%website', '%baseFolder', '%folder', '%title' (as slug) and '%date'. The filename is appended at the end.", "manual:ftp:useForQr": "If enabled, the output received from the FTP server after storing the picture it will be used as input for the generation of the QR code (always check your ftp server configuration).", "manual:ftp:username": "In combination with password to authenticate the user who send the file on the server.", @@ -902,6 +900,7 @@ "remotebuzzer:remotebuzzer_videoled": "LED for Video Button", "remotebuzzer:remotebuzzer_videoledgpio": "GPIO used for video LED", "remotebuzzerGetTrigger": "Remotebuzzer GET request trigger", + "remoteStorageTemplate": "Remote Storage Template test", "reset": "Reset", "reset:reset_button": "Execute reset", "reset:reset_remove_config": "Restore default Photobooth configuration", @@ -918,6 +917,7 @@ "selectFilter": "Image filter", "send": "Send", "serverprocesses": "Processes", + "shareMessage": "Look at this photo! %s", "showCollageFrame": "Show collage Frame", "showPictureFrame": "Show picture Frame", "show_faq": "Open FAQ", diff --git a/resources/template/index.php b/resources/template/index.php index 8925b15d1..b31a291bc 100644 --- a/resources/template/index.php +++ b/resources/template/index.php @@ -1,28 +1,43 @@ glob($templateConfig['paths']['images'] . '/*.{jpg,JPG}', GLOB_BRACE) ?: [], + 'thumbs' => glob($templateConfig['paths']['thumbs'] . '/*.{jpg,JPG}', GLOB_BRACE) ?: [], +]; + +asort($images['images']); +asort($images['thumbs']); + +$firstImage = $images['images'][0] ?? null; +$totalImages = count($images['images']); + +$requestUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; +$urlPrefix = $requestUrl; +if (substr($urlPrefix, -4) === '.php') { + $baseName = basename($urlPrefix); + $urlPrefix = rtrim($urlPrefix, $baseName); +} +if (substr($urlPrefix, -1) !== '/') { + $urlPrefix .= '/'; +} + +$ogImage = $urlPrefix . $firstImage; + +header('Cache-Control: max-age=' . $templateConfig['meta']['max-age']); if ($_SERVER['REQUEST_METHOD'] === 'POST') { - zipFilesAndDownload($full_images); + zipFilesAndDownload($images['images'], $templateConfig); } -function zipFilesAndDownload($files) +function zipFilesAndDownload($files, $templateConfig) { // create new zip opbject $zip = new ZipArchive(); @@ -46,7 +61,7 @@ function zipFilesAndDownload($files) $zip->close(); // send the file to the browser as a download - header('Content-disposition: attachment; filename="{title}.zip"'); + header('Content-disposition: attachment; filename="' . $templateConfig['files']['download_prefix'] . '.zip"'); header('Content-type: application/zip'); header('Content-length: ' . filesize($tmp_file)); header('Pragma: no-cache'); @@ -55,95 +70,49 @@ function zipFilesAndDownload($files) ignore_user_abort(true); unlink($tmp_file); } -?> +$styles = ''; +$styles .= '' . PHP_EOL; + +?> - +
- + - - + - - - - - + + - - - - -