diff --git a/.htaccess b/.htaccess
index bd7cf45..bc6a177 100644
--- a/.htaccess
+++ b/.htaccess
@@ -20,12 +20,12 @@ Options -MultiViews
#RewriteRule images/.+\.(gif|jpe?g|a?png|bmp|webp) content/images/system/default/404.gif [NC,L]
RewriteRule images/.+\.(gif|jpe?g|png|bmp|webp) - [NC,L,R=404]
- # PHP front controller
+ # PHP front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
- # Single PHP-entrypoint
- RewriteCond %{THE_REQUEST} ^.+?\ [^?]+\.php[?\ ] [NC]
- RewriteRule \.php$ - [NC,L,F,R=404]
-
\ No newline at end of file
+ # Single PHP-entrypoint
+ RewriteCond %{THE_REQUEST} ^.+?\ [^?]+\.php[?\ ] [NC]
+ RewriteRule \.php$ - [NC,L,F,R=404]
+
diff --git a/.package/4.1.1.txt b/.package/4.1.1.txt
deleted file mode 100644
index aad804f..0000000
--- a/.package/4.1.1.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Chevereto 4.1.1 (2024-04-27)
-
-- 🎥 Added FFmpeg detection on Dashboard
-- 🎥 Added support for MOV files (video/quicktime)
-- 🎥 Improved detection of FFmpeg required functions proc_open and proc_close
-- 🎥 Improved FFprobe handling when processing video
-- 🎥 Improved video display for listing viewer
-- 💅 Added display title to listing viewer
-- 💅 Fixed files remark on Dashboard
-- 💅 Fixed file remarks on Bulk importer stats
-- 💅 Improved image viewer & natural zoom
-- 💅 Improved menu display for mobile
-- 💅 Updated homepage cover image
-- 🔑 Improved feedback on license key handling
-- 🐞 Fixed bug with missing scroll behavior
-- 🐞 Fixed bug with not working URL upload
-- 🐞 Fixed bug with video upload not working on iOS
-- 🐞 Fixed bug with file-upload documentation link
-- 🇨🇱 Updated Spanish translation
\ No newline at end of file
diff --git a/.package/4.1.2.txt b/.package/4.1.2.txt
new file mode 100644
index 0000000..d74d295
--- /dev/null
+++ b/.package/4.1.2.txt
@@ -0,0 +1,20 @@
+Chevereto 4.1.2 (2024-05-06)
+
+- 🎥 Added support for custom FFmpeg and FFprobe binaries
+- 🎥 Improved video display on listings and viewer
+- ✅ Improved embed codes display
+- ✅ Improved upgrading in systems without passthru
+- 🖼️ Improved compatibility with jpg extension
+- 🐘 Added Dashboard section for PHP configuration (ini files)
+- 💅 Added feedback on CLI update command
+- 💅 Added remark on Homepage settings when conflicts with single profile routing
+- 💅 Fixed file references on /album
+- 💅 Improved style for user settings button
+- 💅 Improved style for user top menu
+- 🐞 Fixed bug affecting album password when using encryption
+- 🐞 Fixed bug affecting full screen video behavior
+- 🐞 Fixed bug affecting not working URL upload editing
+- 🐞 Fixed bug affecting wrong video image frame permissions
+- 🐞 Fixed bug in album embed codes
+- 🐞 Fixed bug in password protected album editing on listings
+- 🐞 Fixed bug in Search class
diff --git a/README.md b/README.md
index 9e3c2b4..01acffd 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,5 @@
# Chevereto: Ultimate image and video sharing software
-> 🔔 [Subscribe](https://chv.to/newsletter) to don't miss any update regarding Chevereto.
-
@@ -16,6 +14,8 @@
[](https://github.com/rodber/chevereto-free)
[](https://awsmfoss.com/chevereto/)
+> 🔔 [Subscribe](https://chv.to/newsletter) to don't miss any update regarding Chevereto.
+
Chevereto enables to create a media sharing website on your own server. It's your hosting and your rules, say goodbye to closures and restrictions. ⭐️ [Live demo](https://demo.chevereto.com)
Chevereto is a turnkey system which main use case is to provide a self-hosted platform for content creators, communities and businesses. It's features are all about media sharing, with a strong focus on user experience, privacy and security. On its pro edition Chevereto excels as a content management system with heavy business related features that you won't get on other systems.
@@ -134,108 +134,111 @@ Chevereto is so **feature-rich**, mature and robust that we need three layers of
### Admin features
-| Feature | Free | Lite | Pro |
-| ----------------------------------------------------- | :---: | :---: | :---: |
-| Dashboard (admin UI) | ✅ | ✅ | ✅ |
-| System stats & usage | ✅ | ✅ | ✅ |
-| Website privacy mode (public, private) | ✅ | ✅ | ✅ |
-| Default timezone selection | ✅ | ✅ | ✅ |
-| Uploadable file extensions | ✅ | ✅ | ✅ |
-| Guest uploads auto delete | ✅ | ✅ | ✅ |
-| Upload threads | ✅ | ✅ | ✅ |
-| Upload maximum image size | ✅ | ✅ | ✅ |
-| Upload Exif removal | ✅ | ✅ | ✅ |
-| Upload max file size (users and guest) | ✅ | ✅ | ✅ |
-| Upload path | ✅ | ✅ | ✅ |
-| Upload file naming | ✅ | ✅ | ✅ |
-| Upload thumb size | ✅ | ✅ | ✅ |
-| Upload medium size and dimension | ✅ | ✅ | ✅ |
-| Semantics | ✅ | ✅ | ✅ |
-| Default palette | ✅ | ✅ | ✅ |
-| Default font | ✅ | ✅ | ✅ |
-| Image load max file size | ✅ | ✅ | ✅ |
-| Image first tab | ✅ | ✅ | ✅ |
-| Embed codes (content) | ✅ | ✅ | ✅ |
-| Custom JS & CSS | ✅ | ✅ | ✅ |
-| Universal CDN support | ✅ | ✅ | ✅ |
-| Default language | ✅ | ✅ | ✅ |
-| Homepage style | – | ✅ | ✅ |
-| Homepage cover images | – | ✅ | ✅ |
-| Homepage title & paragraph | – | ✅ | ✅ |
-| Homepage call to action | – | ✅ | ✅ |
-| Pages | – | ✅ | ✅ |
-| Lock NSFW editing | – | ✅ | ✅ |
-| User min age required | – | ✅ | ✅ |
-| User avatar max file size | – | ✅ | ✅ |
-| User background max file size | – | ✅ | ✅ |
-| Guest API key | – | ✅ | ✅ |
-| Available languages (configurable) | – | – | ✅ |
-| Hide "Powered by Chevereto" | – | – | ✅ |
-| Logo & branding | – | – | ✅ |
-| Logo type (vector, image, text) | – | – | ✅ |
-| Logo height | – | – | ✅ |
-| Logo favicon image | – | – | ✅ |
-| Routing (user, image, album) | – | – | ✅ |
-| Routing root | – | – | ✅ |
-| External services | – | – | ✅ |
-| Comments API (Disqus, JS) | – | – | ✅ |
-| Analytics code | – | – | ✅ |
-| Akismet spam protection | – | – | ✅ |
-| StopForumSpam spam protection | – | – | ✅ |
-| CAPTCHA (reCAPTCHA, hCaptcha) | – | – | ✅ |
-| CAPTCHA threshold | – | – | ✅ |
-| Project Arachnid | – | – | ✅ |
-| ModerateContent (auto approve, block, flag) | – | – | ✅ |
-| OAuth2 login providers (Amazon, Google, Discord, etc) | – | – | ✅ |
-| Banners | – | – | ✅ |
-| Watermark uploads (guest, user, admin) | – | – | ✅ |
-| Watermark file toggles | – | – | ✅ |
-| Watermark size requirement | – | – | ✅ |
-| Watermark custom image | – | – | ✅ |
-| Watermark position | – | – | ✅ |
-| Watermark percentage | – | – | ✅ |
-| Watermark margin | – | – | ✅ |
-| Watermark opacity | – | – | ✅ |
+| Feature | Free | Lite | Pro |
+| --------------------------------------------------------------------------------------------- | :---: | :---: | :---: |
+| Dashboard (admin UI) | ✅ | ✅ | ✅ |
+| System stats & usage | ✅ | ✅ | ✅ |
+| Website name | ✅ | ✅ | ✅ |
+| Website doctitle | ✅ | ✅ | ✅ |
+| Website description | ✅ | ✅ | ✅ |
+| Website privacy mode (public, private) | ✅ | ✅ | ✅ |
+| Default timezone | ✅ | ✅ | ✅ |
+| Uploadable file extensions | ✅ | ✅ | ✅ |
+| Guest uploads auto delete | ✅ | ✅ | ✅ |
+| Upload threads | ✅ | ✅ | ✅ |
+| Upload maximum image size | ✅ | ✅ | ✅ |
+| Upload Exif removal | ✅ | ✅ | ✅ |
+| Upload max file size (users and guest) | ✅ | ✅ | ✅ |
+| Upload path | ✅ | ✅ | ✅ |
+| Upload file naming | ✅ | ✅ | ✅ |
+| Upload thumb size | ✅ | ✅ | ✅ |
+| Upload medium size and dimension | ✅ | ✅ | ✅ |
+| Semantics | ✅ | ✅ | ✅ |
+| Default palette | ✅ | ✅ | ✅ |
+| Default font | ✅ | ✅ | ✅ |
+| Image load max file size | ✅ | ✅ | ✅ |
+| Image first tab | ✅ | ✅ | ✅ |
+| Embed codes (content) | ✅ | ✅ | ✅ |
+| Custom JS & CSS | ✅ | ✅ | ✅ |
+| Universal CDN support | ✅ | ✅ | ✅ |
+| [Default language](https://v4-admin.chevereto.com/settings/languages.html#default-language) | ✅ | ✅ | ✅ |
+| Homepage style | – | ✅ | ✅ |
+| Homepage cover images | – | ✅ | ✅ |
+| Homepage title & paragraph | – | ✅ | ✅ |
+| Homepage call to action | – | ✅ | ✅ |
+| Pages | – | ✅ | ✅ |
+| Lock NSFW editing | – | ✅ | ✅ |
+| User min age required | – | ✅ | ✅ |
+| User avatar max file size | – | ✅ | ✅ |
+| User background max file size | – | ✅ | ✅ |
+| Guest API key | – | ✅ | ✅ |
+| [Enabled languages](https://v4-admin.chevereto.com/settings/languages.html#enabled-languages) | – | – | ✅ |
+| Hide "Powered by Chevereto" | – | – | ✅ |
+| Logo & branding | – | – | ✅ |
+| Logo type (vector, image, text) | – | – | ✅ |
+| Logo height | – | – | ✅ |
+| Logo favicon image | – | – | ✅ |
+| Routing (user, image, album) | – | – | ✅ |
+| Routing root | – | – | ✅ |
+| External services | – | – | ✅ |
+| Comments API (Disqus, JS) | – | – | ✅ |
+| Analytics code | – | – | ✅ |
+| Akismet spam protection | – | – | ✅ |
+| StopForumSpam spam protection | – | – | ✅ |
+| CAPTCHA (reCAPTCHA, hCaptcha) | – | – | ✅ |
+| CAPTCHA threshold | – | – | ✅ |
+| Project Arachnid | – | – | ✅ |
+| ModerateContent (auto approve, block, flag) | – | – | ✅ |
+| OAuth2 login providers (Amazon, Google, Discord, etc) | – | – | ✅ |
+| Banners | – | – | ✅ |
+| Watermark uploads (guest, user, admin) | – | – | ✅ |
+| Watermark file toggles | – | – | ✅ |
+| Watermark size requirement | – | – | ✅ |
+| Watermark custom image | – | – | ✅ |
+| Watermark position | – | – | ✅ |
+| Watermark percentage | – | – | ✅ |
+| Watermark margin | – | – | ✅ |
+| Watermark opacity | – | – | ✅ |
### Admin toggles
-| Feature | Free | Lite | Pro |
-| --------------------------- | :---: | :---: | :---: |
-| Search (users and guest) | ✅ | ✅ | ✅ |
-| Explore (users and guest) | ✅ | ✅ | ✅ |
-| Random (users and guest) | ✅ | ✅ | ✅ |
-| NSFW listings | ✅ | ✅ | ✅ |
-| Blur NSFW content | ✅ | ✅ | ✅ |
-| NSFW on random mode | ✅ | ✅ | ✅ |
-| Banners on NSFW | ✅ | ✅ | ✅ |
-| Uploads (users and guest) | ✅ | ✅ | ✅ |
-| Uploads (URL) | ✅ | ✅ | ✅ |
-| Upload moderation | ✅ | ✅ | ✅ |
-| Upload embed codes | ✅ | ✅ | ✅ |
-| Upload redirection | ✅ | ✅ | ✅ |
-| Upload duplication | ✅ | ✅ | ✅ |
-| Upload expiration | ✅ | ✅ | ✅ |
-| Upload NSFW checkbox | ✅ | ✅ | ✅ |
-| Download button | ✅ | ✅ | ✅ |
-| Right click | ✅ | ✅ | ✅ |
-| Show Exif data | ✅ | ✅ | ✅ |
-| Social share buttons | ✅ | ✅ | ✅ |
-| Automatic updates check | ✅ | ✅ | ✅ |
-| Dump update query | ✅ | ✅ | ✅ |
-| Debug errors | ✅ | ✅ | ✅ |
-| Consent screen (age gate) | – | ✅ | ✅ |
-| User sign up | – | ✅ | ✅ |
-| User content delete | – | ✅ | ✅ |
-| User notify sign up | – | ✅ | ✅ |
-| User email confirmation | – | ✅ | ✅ |
-| User email for social login | – | ✅ | ✅ |
-| Auto language | – | – | ✅ |
-| Language chooser | – | – | ✅ |
-| SEO URLs (media and album) | – | – | ✅ |
-| Cookie law compliance | – | – | ✅ |
-| Flood protection | – | – | ✅ |
-| Flood protection notify | – | – | ✅ |
-| Watermarks | – | – | ✅ |
+| Feature | Free | Lite | Pro |
+| ------------------------------------------------------------------------------------------- | :---: | :---: | :---: |
+| Search (users and guest) | ✅ | ✅ | ✅ |
+| Explore (users and guest) | ✅ | ✅ | ✅ |
+| Random (users and guest) | ✅ | ✅ | ✅ |
+| NSFW listings | ✅ | ✅ | ✅ |
+| Blur NSFW content | ✅ | ✅ | ✅ |
+| NSFW on random mode | ✅ | ✅ | ✅ |
+| Banners on NSFW | ✅ | ✅ | ✅ |
+| Uploads (users and guest) | ✅ | ✅ | ✅ |
+| Uploads (URL) | ✅ | ✅ | ✅ |
+| Upload moderation | ✅ | ✅ | ✅ |
+| Upload embed codes | ✅ | ✅ | ✅ |
+| Upload redirection | ✅ | ✅ | ✅ |
+| Upload duplication | ✅ | ✅ | ✅ |
+| Upload expiration | ✅ | ✅ | ✅ |
+| Upload NSFW checkbox | ✅ | ✅ | ✅ |
+| Download button | ✅ | ✅ | ✅ |
+| Right click | ✅ | ✅ | ✅ |
+| Show Exif data | ✅ | ✅ | ✅ |
+| Social share buttons | ✅ | ✅ | ✅ |
+| Automatic updates check | ✅ | ✅ | ✅ |
+| Dump update query | ✅ | ✅ | ✅ |
+| Debug errors | ✅ | ✅ | ✅ |
+| Consent screen (age gate) | – | ✅ | ✅ |
+| User sign up | – | ✅ | ✅ |
+| User content delete | – | ✅ | ✅ |
+| User notify sign up | – | ✅ | ✅ |
+| User email confirmation | – | ✅ | ✅ |
+| User email for social login | – | ✅ | ✅ |
+| [Auto language](https://v4-admin.chevereto.com/settings/languages.html#auto-language) | – | – | ✅ |
+| [Language chooser](https://v4-admin.chevereto.com/settings/languages.html#language-chooser) | – | – | ✅ |
+| SEO URLs (media and album) | – | – | ✅ |
+| Cookie law compliance | – | – | ✅ |
+| Flood protection | – | – | ✅ |
+| Flood protection notify | – | – | ✅ |
+| Watermarks | – | – | ✅ |
### System features
diff --git a/app/composer.lock b/app/composer.lock
index 15ad497..7dd1995 100644
--- a/app/composer.lock
+++ b/app/composer.lock
@@ -3277,20 +3277,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.7.5",
+ "version": "4.7.6",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
+ "reference": "91039bc1faa45ba123c4328958e620d382ec7088"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
- "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
+ "reference": "91039bc1faa45ba123c4328958e620d382ec7088",
"shasum": ""
},
"require": {
- "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
@@ -3353,7 +3353,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.7.5"
+ "source": "https://github.com/ramsey/uuid/tree/4.7.6"
},
"funding": [
{
@@ -3365,7 +3365,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-08T05:53:05+00:00"
+ "time": "2024-04-27T21:32:50+00:00"
},
{
"name": "react/cache",
@@ -4083,16 +4083,16 @@
},
{
"name": "symfony/cache",
- "version": "v5.4.38",
+ "version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "223c3afac82e003a76931b71d77db408636a0de8"
+ "reference": "982237e35079fdcc31ab724f06b6131992c4fd24"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/223c3afac82e003a76931b71d77db408636a0de8",
- "reference": "223c3afac82e003a76931b71d77db408636a0de8",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/982237e35079fdcc31ab724f06b6131992c4fd24",
+ "reference": "982237e35079fdcc31ab724f06b6131992c4fd24",
"shasum": ""
},
"require": {
@@ -4160,7 +4160,7 @@
"psr6"
],
"support": {
- "source": "https://github.com/symfony/cache/tree/v5.4.38"
+ "source": "https://github.com/symfony/cache/tree/v5.4.39"
},
"funding": [
{
@@ -4176,7 +4176,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T09:55:32+00:00"
+ "time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/cache-contracts",
diff --git a/app/env-default.php b/app/env-default.php
index 2367770..d1bd041 100644
--- a/app/env-default.php
+++ b/app/env-default.php
@@ -68,6 +68,8 @@ return [
'CHEVERETO_ENABLE_UPLOAD_PLUGIN' => '1',
'CHEVERETO_ENABLE_UPLOAD_WATERMARK' => '1',
'CHEVERETO_ENABLE_USERS' => '1',
+ 'CHEVERETO_ENABLE_SEO_IMAGE_URL' => '1',
+ 'CHEVERETO_ENABLE_SEO_ALBUM_URL' => '1',
'CHEVERETO_ENCRYPTION_KEY' => '',
'CHEVERETO_ERROR_LOG' => 'php://stderr',
'CHEVERETO_HEADER_CLIENT_IP' => '',
@@ -88,4 +90,6 @@ return [
'CHEVERETO_SESSION_SAVE_HANDLER' => 'files',
'CHEVERETO_SESSION_SAVE_PATH' => '/tmp',
'CHEVERETO_EDITION' => 'pro',
+ 'CHEVERETO_BINARY_FFMPEG' => 'ffmpeg',
+ 'CHEVERETO_BINARY_FFPROBE' => 'ffprobe',
];
diff --git a/app/legacy/commands/cron.php b/app/legacy/commands/cron.php
index bdede94..c138533 100644
--- a/app/legacy/commands/cron.php
+++ b/app/legacy/commands/cron.php
@@ -115,7 +115,7 @@ function removeDeleteLog(): void
}
function checkForNews(): void
{
- if (!checkoutUpdate('news_check_datetimegmt')) {
+ if (!checkoutUpdate('news_check_datetimegmt', 'PT4H')) {
feedbackAlert('Skipping news check');
return;
@@ -133,7 +133,7 @@ function checkForNews(): void
}
function checkForUpdates(): void
{
- if (!checkoutUpdate('update_check_datetimegmt')) {
+ if (!checkoutUpdate('update_check_datetimegmt', 'P1D')) {
feedbackAlert('Skipping updates check');
return;
@@ -149,10 +149,10 @@ function checkForUpdates(): void
}
echoLocked($job);
}
-function checkoutUpdate(string $datetimeSetting): bool
+function checkoutUpdate(string $datetimeSetting, string $past): bool
{
return is_null(Settings::get($datetimeSetting))
- || datetime_add(Settings::get($datetimeSetting), 'P1D') < datetimegmt();
+ || datetime_add(Settings::get($datetimeSetting), $past) < datetimegmt();
}
function checkHtaccess()
{
diff --git a/app/legacy/commands/langs.php b/app/legacy/commands/langs.php
index 2f3c6c1..86536a5 100644
--- a/app/legacy/commands/langs.php
+++ b/app/legacy/commands/langs.php
@@ -52,6 +52,9 @@ foreach ($languages as $lang) {
]);
}
echo "$lang\n";
+ if (file_exists($language_override_file)) {
+ echo "$lang [override]\n";
+ }
}
echo "---\n";
echo L10n::LOCALES_AVAILABLE_FILEPATH . "\n";
diff --git a/app/legacy/install/installer.php b/app/legacy/install/installer.php
index 1423cc1..c1e06e5 100644
--- a/app/legacy/install/installer.php
+++ b/app/legacy/install/installer.php
@@ -604,6 +604,7 @@ $settings_updates = [
'4.1.1' => [
'upload_enabled_image_formats' => 'jpg,png,bmp,gif,webp,mov,mp4,webm',
],
+ '4.1.2' => null,
];
$cheveretoFreeMap = [
'1.0.0' => '3.8.3',
@@ -2053,6 +2054,7 @@ ALTER TABLE `%table_prefix%users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8m
xr($sql_update);
try {
+ logger("[STATUS] Updating Chevereto database (this may take a while)...\n");
$updated = $db->exec();
if ($updated) {
$chevereto_version_installed = DB::get('settings', ['name' => 'chevereto_version_installed'])[0]['setting_value'];
diff --git a/app/legacy/load/app.php b/app/legacy/load/app.php
index 5f35748..2d1d5a0 100644
--- a/app/legacy/load/app.php
+++ b/app/legacy/load/app.php
@@ -9,5 +9,5 @@
* file that was distributed with this source code.
*/
-const APP_VERSION = '4.1.1';
+const APP_VERSION = '4.1.2';
const APP_VERSION_AKA = 'pulento';
diff --git a/app/legacy/routes/dashboard.php b/app/legacy/routes/dashboard.php
index fc21e21..88e228d 100644
--- a/app/legacy/routes/dashboard.php
+++ b/app/legacy/routes/dashboard.php
@@ -39,6 +39,7 @@ use function Chevereto\Legacy\G\get_app_version;
use function Chevereto\Legacy\G\get_base_url;
use function Chevereto\Legacy\G\get_bytes;
use function Chevereto\Legacy\G\get_client_ip;
+use function Chevereto\Legacy\G\get_ffmpeg_error;
use function Chevereto\Legacy\G\get_ini_bytes;
use function Chevereto\Legacy\G\get_regex_match;
use Chevereto\Legacy\G\Handler;
@@ -69,6 +70,7 @@ use function Chevereto\Vars\server;
use function Chevereto\Vars\session;
use function Chevereto\Vars\sessionVar;
use FFMpeg\FFMpeg;
+use FFMpeg\FFProbe;
use Intervention\Image\ImageManagerStatic;
use PHPMailer\PHPMailer\SMTP;
@@ -174,13 +176,13 @@ return function (Handler $handler) {
'languages' => _s('Languages'),
'email' => _s('Email'),
'tools' => _s('Tools'),
- 'logo' => _s('Logo'),
'homepage' => _s('Homepage'),
'pages' => _s('Pages'),
'upload-plugin' => _s('Upload plugin'),
'consent-screen' => _s('Consent screen'),
'users' => _n('User', 'Users', 20),
'guest-api' => _s('Guests %s', 'API'),
+ 'logo' => _s('Logo'),
'external-storage' => _s('External storage'),
'routing' => _s('Routing'),
'external-services' => _s('External services'),
@@ -231,7 +233,7 @@ return function (Handler $handler) {
'homepage' => ['lite', 'CHEVERETO_ENABLE_USERS'],
'ip-bans' => ['pro', 'CHEVERETO_ENABLE_IP_BANS'],
'login-providers' => ['pro', 'CHEVERETO_ENABLE_LOGIN_PROVIDERS'],
- 'logo' => ['lite', 'CHEVERETO_ENABLE_LOGO'],
+ 'logo' => ['pro', 'CHEVERETO_ENABLE_LOGO'],
'pages' => ['lite', 'CHEVERETO_ENABLE_PAGES'],
'routing' => ['pro', 'CHEVERETO_ENABLE_ROUTING'],
'upload-plugin' => ['lite', 'CHEVERETO_ENABLE_UPLOAD_PLUGIN'],
@@ -417,7 +419,6 @@ return function (Handler $handler) {
$errorLogRemark .= 'docker logs ' . (gethostname() ?: 'chv-container') . ' -f 1>/dev/null
';
}
}
-
$ffmpegContent = ' ';
try {
@@ -434,14 +435,43 @@ return function (Handler $handler) {
)
);
}
- $ffmpegContent .= FFMpeg::create()->getFFMpegDriver()->getVersion();
+ $ffmpegErrors = [];
+
+ try {
+ $ffmpeg = FFMpeg::create(
+ [
+ 'ffmpeg.binaries' => env()['CHEVERETO_BINARY_FFMPEG'],
+ 'ffprobe.binaries' => env()['CHEVERETO_BINARY_FFPROBE'],
+ ]
+ );
+ } catch (Throwable $e) {
+ $ffmpegErrors[] = get_ffmpeg_error($e);
+ }
+
+ try {
+ $ffprobe = FFProbe::create(
+ [
+ 'ffprobe.binaries' => env()['CHEVERETO_BINARY_FFPROBE'],
+ ]
+ );
+ } catch (Throwable $e) {
+ $ffmpegErrors[] = get_ffmpeg_error($e);
+ }
+ if ($ffmpegErrors !== []) {
+ throw new Exception(implode(', ', $ffmpegErrors));
+ }
+
+ $ffprobe->getFFProbeDriver()->getName();
+ $ffmpegContent .= 'FFmpeg bin:'
+ . env()['CHEVERETO_BINARY_FFMPEG']
+ . ' version '
+ . $ffmpeg->getFFMpegDriver()->getVersion()
+ . '
'
+ . ' FFprobe bin:'
+ . env()['CHEVERETO_BINARY_FFPROBE'];
} catch (Throwable $e) {
- $previous = $e->getPrevious() ?
- ': ' . $e->getPrevious()->getMessage() :
- '';
$ffmpegContent = ' Error: '
- . $e->getMessage()
- . $previous
+ . get_ffmpeg_error($e)
. '';
}
@@ -534,6 +564,16 @@ return function (Handler $handler) {
$mysqlVersion = $db->getAttr(PDO::ATTR_SERVER_VERSION);
$db->closeCursor();
$mysqlServerInfo = $db->getAttr(PDO::ATTR_SERVER_INFO);
+ $phpIniLoaded = php_ini_loaded_file();
+ $phpIniFiles = php_ini_scanned_files() ?: 'N/A';
+ $phpIniFiles = explode(',', $phpIniFiles);
+ if ($phpIniLoaded) {
+ array_unshift($phpIniFiles, $phpIniLoaded);
+ }
+ $phpIniFiles = array_map(function ($v) {
+ return '' . $v . '
';
+ }, $phpIniFiles);
+ $phpIniFiles = implode('', $phpIniFiles);
$system_values_more = [
'links' => [
'label' => _s('Links'),
@@ -551,10 +591,6 @@ return function (Handler $handler) {
'label' => 'Error log',
'content' => ' ' . Config::system()->errorLog() . '' . $errorLogRemark,
],
- 'php_version' => [
- 'label' => _s('PHP version'),
- 'content' => ' ' . PHP_VERSION . ' ' . php_ini_loaded_file()
- ],
'server' => [
'label' => _s('Server'),
'content' => ' '
@@ -577,6 +613,12 @@ return function (Handler $handler) {
. '
'
. $mysqlServerInfo
],
+ 'php_version' => [
+ 'label' => _s('PHP version'),
+ 'content' => ' '
+ . PHP_VERSION
+ . $phpIniFiles
+ ],
'file_uploads' => [
'label' => _s('File uploads'),
'content' => (int) ini_get('file_uploads') == 1
diff --git a/app/legacy/routes/image.php b/app/legacy/routes/image.php
index 6eb81db..3489024 100644
--- a/app/legacy/routes/image.php
+++ b/app/legacy/routes/image.php
@@ -15,6 +15,7 @@ use Chevereto\Legacy\Classes\IpBan;
use Chevereto\Legacy\Classes\Login;
use Chevereto\Legacy\Classes\User;
use function Chevereto\Legacy\encodeID;
+use function Chevereto\Legacy\flatten_array;
use function Chevereto\Legacy\G\get_current_url;
use function Chevereto\Legacy\G\get_global;
use Chevereto\Legacy\G\Handler;
@@ -275,20 +276,23 @@ return function (Handler $handler) {
$handler::setVar('privacy', $image['album']['privacy'] ?? '');
include_theme_file('snippets/embed');
$embed_share_tpl = get_global('embed_share_tpl');
- $sharing = [
- '%URL_VIEWER%' => $image['url_viewer'],
- '%URL%' => $image['url'],
- '%DISPLAY_URL%' => $image['display_url'],
- '%DISPLAY_TITLE%' => $image['display_title'],
- '%URL_FRAME%' => $image['url_frame'],
- '%THUMB_URL%' => $image['thumb']['url'],
- '%MEDIUM_URL%' => $image['medium']['url'] ?? '',
- ];
+ $sharing = [];
+ foreach (flatten_array($image) as $imageKey => $imageValue) {
+ $sharing['%' . strtoupper($imageKey) . '%'] = $imageValue;
+ }
$embed = [];
+ $hasFrame = $image['url_frame'] !== '';
+ $hasMedium = $image['medium']['url'] !== null;
foreach ($embed_share_tpl as $code => $group) {
$entries = [];
$groupLabel = $group['label'];
foreach ($group['options'] as $option => $optionValue) {
+ if (!$hasFrame && str_starts_with($option, 'frame-')) {
+ continue;
+ }
+ if (!$hasMedium && str_starts_with($option, 'medium-')) {
+ continue;
+ }
$value = $optionValue['template'];
if (is_array($value)) {
$value = $value[$image['type']];
diff --git a/app/legacy/routes/json.php b/app/legacy/routes/json.php
index ce1867c..585c545 100644
--- a/app/legacy/routes/json.php
+++ b/app/legacy/routes/json.php
@@ -391,7 +391,7 @@ return function (Handler $handler) {
$json_array['album'] = array_filter_array($album, ['id', 'creation_ip', 'password', 'user', 'privacy_extra', 'privacy_notes'], 'rest');
$contents = [];
foreach ($listing->outputAssoc() as $v) {
- $contents[] = array_filter_array($v, ['title', 'id_encoded', 'url', 'url_short', 'path_viewer', 'url_viewer', 'filename', 'medium', 'thumb'], 'exclusion');
+ $contents[] = array_filter_array($v, ['title', 'id_encoded', 'url', 'url_short', 'path_viewer', 'url_viewer', 'filename', 'medium', 'thumb', 'type', 'url_frame'], 'exclusion');
}
$json_array['is_output_truncated'] = $album['image_count'] > $album_fetch ? 1 : 0;
$json_array['contents'] = $contents;
diff --git a/app/src/Legacy/Classes/Album.php b/app/src/Legacy/Classes/Album.php
index 48afabe..06b4e2b 100644
--- a/app/src/Legacy/Classes/Album.php
+++ b/app/src/Legacy/Classes/Album.php
@@ -86,18 +86,10 @@ class Album
if ($requester !== []) {
$album_db['album_liked'] = (bool) $album_db['like_user_id'];
}
- $return = $album_db;
- if (isset($return['album_password']) && hasEncryption()) {
- try {
- $return['album_password'] = decrypt($return['album_password']);
- } catch (Throwable) {
- $return['album_password'] = $return['album_password'];
- }
- }
return $pretty
- ? self::formatArray($return)
- : $return;
+ ? self::formatArray($album_db)
+ : self::cipherAwareDbRow($album_db);
}
public static function getMultiple(array $ids, bool $pretty = false): array
@@ -514,8 +506,22 @@ class Album
$album['cta'] = $album['cta'] ?? '[]';
}
+ public static function cipherAwareDbRow(array &$dbrow): array
+ {
+ if (isset($dbrow['album_password']) && hasEncryption()) {
+ try {
+ $dbrow['album_password'] = decrypt($dbrow['album_password']);
+ } catch (Throwable) {
+ $dbrow['album_password'] = $dbrow['album_password'];
+ }
+ }
+
+ return $dbrow;
+ }
+
public static function formatArray(array $dbrow, bool $safe = false): array
{
+ self::cipherAwareDbRow($dbrow);
$output = DB::formatRow($dbrow);
if (!isset($output['user'])) {
$output['user'] = [];
@@ -555,7 +561,7 @@ class Album
if (isset($session_password) && hasEncryption()) {
$session_password = decrypt($session_password);
}
- if (!isset($session_password) || !hash_equals($session_password, $album['password'])) {
+ if (!isset($session_password) || !hash_equals($album['password'], $session_password)) {
$removeValue = session()['password'] ?? null;
unset($removeValue['album'][$album['id']]);
sessionVar()->put('password', $removeValue);
diff --git a/app/src/Legacy/Classes/Image.php b/app/src/Legacy/Classes/Image.php
index b9d0dea..e615474 100644
--- a/app/src/Legacy/Classes/Image.php
+++ b/app/src/Legacy/Classes/Image.php
@@ -14,6 +14,8 @@ namespace Chevereto\Legacy\Classes;
use function Chevere\Message\message;
use function Chevere\String\randomString;
use Chevere\Throwable\Exceptions\LogicException;
+use function Chevereto\Encryption\decrypt;
+use function Chevereto\Encryption\hasEncryption;
use function Chevereto\Legacy\assertNotStopWords;
use function Chevereto\Legacy\decodeID;
use function Chevereto\Legacy\encodeID;
@@ -31,6 +33,7 @@ use function Chevereto\Legacy\G\format_bytes;
use function Chevereto\Legacy\G\get_basename_without_extension;
use function Chevereto\Legacy\G\get_bytes;
use function Chevereto\Legacy\G\get_client_ip;
+use function Chevereto\Legacy\G\get_ffmpeg_error;
use function Chevereto\Legacy\G\get_filename;
use function Chevereto\Legacy\G\get_image_fileinfo as GGet_image_fileinfo;
use function Chevereto\Legacy\G\get_public_url;
@@ -790,9 +793,16 @@ class Image
}
$resizeSourceImage = $image_upload['uploaded']['file'];
$uploadDir = dirname($resizeSourceImage);
+ $chainExtension = $image_upload['uploaded']['extension'];
if ($image_upload['source']['type'] === 'video') {
- $frameImage = $uploadDir . '/' . $image_upload['uploaded']['name'] . '.fr.jpeg';
+ $chainExtension = 'jpeg';
+ $frameImage = $uploadDir
+ . '/'
+ . $image_upload['uploaded']['name']
+ . '.fr.'
+ . $chainExtension;
rename($image_upload['uploaded']['frame'], $frameImage);
+ chmod($frameImage, 0644);
$resizeSourceImage = $frameImage;
$chain_mask[0] = 1;
}
@@ -810,11 +820,12 @@ class Image
} else {
$image_resize_options = ['width' => $params['width']];
}
+ $image_resize_options['extension'] = $image_upload['uploaded']['extension'];
$image_upload['uploaded'] = self::resize(
- $resizeSourceImage,
- dirname($resizeSourceImage),
- null,
- $image_resize_options
+ source: $resizeSourceImage,
+ destination: dirname($resizeSourceImage),
+ filename: null,
+ options: $image_resize_options
);
$image_upload['uploaded']['fileinfo']['is_360'] = $is_360;
}
@@ -824,6 +835,7 @@ class Image
'fitted' => true,
'width' => getSetting('upload_thumb_width'),
'height' => getSetting('upload_thumb_height'),
+ 'extension' => $chainExtension
];
$medium_size = getSetting('upload_medium_size');
$medium_fixed_dimension = getSetting('upload_medium_fixed_dimension');
@@ -870,11 +882,12 @@ class Image
$image_medium_options['forced'] = true;
$image_medium_options[$medium_fixed_dimension] = min($image_medium_options[$medium_fixed_dimension], $image_upload['uploaded']['fileinfo'][$medium_fixed_dimension]);
}
+ $image_medium_options['extension'] = $chainExtension;
$image_medium = self::resize(
- $resizeSourceImage,
- $uploadDir,
- $image_upload['uploaded']['name'] . '.md',
- $image_medium_options
+ source: $resizeSourceImage,
+ destination: $uploadDir,
+ filename: $image_upload['uploaded']['name'] . '.md',
+ options: $image_medium_options
);
$chain_mask[3] = 1;
}
@@ -1246,6 +1259,7 @@ class Image
'original_filename' => $image_upload['source']['filename'],
'original_exifdata' => $original_exifdata,
'is_360' => $is360,
+ 'extension' => $image_upload['uploaded']['extension'],
];
if (!isset($values['date'])) {
$populate_values = array_merge($populate_values, [
@@ -1478,7 +1492,6 @@ class Image
$image = array_merge($image, get_fileinfo($targets['chain']['image']), $image_fileinfo);
}
-
$image['file_resource'] = $targets;
$image['url_viewer'] = self::getUrlViewer(
$image['id_encoded'],
@@ -1518,6 +1531,7 @@ class Image
break;
}
+ $displaySize = $image['medium']['size'];
} elseif (
$image['size'] > get_bytes('200 KB')
&& $image['type'] === 1
@@ -1525,6 +1539,14 @@ class Image
$display_url = $image['thumb']['url'] ?? '';
$display_width = getSetting('upload_thumb_width');
$display_height = getSetting('upload_thumb_height');
+ $displaySize = $image['thumb']['size'];
+ }
+ if (isset($image['frame']['size'], $displaySize)
+ && $image['frame']['size'] < $displaySize
+ ) {
+ $display_url = $image['frame']['url'];
+ $display_width = $image['width'];
+ $display_height = $image['height'];
}
$image['duration'] = (int) ($image['duration'] ?? 0);
$seconds = $image['duration'] ?? 0;
@@ -1534,6 +1556,13 @@ class Image
} else {
$duration_time = '';
}
+ $image['medium'] = $image['medium'] ?? [
+ 'filename' => null,
+ 'name' => null,
+ 'mime' => null,
+ 'extension' => null,
+ 'url' => null,
+ ];
$image['duration_time'] = $duration_time;
$image['type'] = self::$types[$image['type']];
$image['display_url'] = $display_url;
@@ -1562,6 +1591,13 @@ class Image
}
if (isset($output['album']['id']) || isset($output['user']['id'])) {
$output['user'] = $output['user'] ?? [];
+ if (isset($output['album']['password']) && hasEncryption()) {
+ try {
+ $output['album']['password'] = decrypt($output['album']['password']);
+ } catch (Throwable) {
+ $output['album']['password'] = $output['album']['password'];
+ }
+ }
Album::fill($output['album'], $output['user']);
} else {
unset($output['album']);
@@ -1584,7 +1620,18 @@ class Image
public static function getVideoFrame(string $file, int $time): string
{
$frameFile = Upload::getTempNam(sys_get_temp_dir());
- $ffmpeg = FFMpeg::create();
+
+ try {
+ $ffmpeg = FFMpeg::create(
+ [
+ 'ffmpeg.binaries' => env()['CHEVERETO_BINARY_FFMPEG'],
+ 'ffprobe.binaries' => env()['CHEVERETO_BINARY_FFPROBE'],
+ ]
+ );
+ } catch (Throwable $e) {
+ throw new Exception("FFprobe error: " . get_ffmpeg_error($e), 600);
+ }
+
$video = $ffmpeg->open($file);
$video
->frame(TimeCode::fromSeconds($time))
diff --git a/app/src/Legacy/Classes/ImageResize.php b/app/src/Legacy/Classes/ImageResize.php
index bf17209..37ce0f4 100644
--- a/app/src/Legacy/Classes/ImageResize.php
+++ b/app/src/Legacy/Classes/ImageResize.php
@@ -105,7 +105,8 @@ class ImageResize
{
$this->validateInput(); // Exception 1xx
$source_filename = get_basename_without_extension($this->source);
- $this->file_extension = $this->source_image_fileinfo['extension'];
+ $this->file_extension = $this->options['extension']
+ ?? $this->source_image_fileinfo['extension'];
if (!isset($this->filename)) {
$this->filename = $source_filename;
}
diff --git a/app/src/Legacy/Classes/Search.php b/app/src/Legacy/Classes/Search.php
index 06aa773..e68c6b4 100644
--- a/app/src/Legacy/Classes/Search.php
+++ b/app/src/Legacy/Classes/Search.php
@@ -83,9 +83,6 @@ class Search
str_replace($v, '', $q_match)
)
);
- if ($q_match === '') {
- $q_match = null;
- }
$op = explode(':', $v);
if (!in_array($op[0], ['category', 'ip', 'storage'])) {
continue;
@@ -134,7 +131,7 @@ class Search
break;
}
}
- if (isset($q_match)) {
+ if ($q_match !== '') {
$q_value = $q_match;
if ($this->DBEngine == 'InnoDB') {
$q_value = trim($q_value, '><');
@@ -146,7 +143,7 @@ class Search
$wheres = null;
switch ($this->type) {
case 'images':
- if (isset($q_match)) {
+ if ($q_match !== '') {
$wheres = 'WHERE MATCH(`image_name`,`image_title`,`image_description`,`image_original_filename`) AGAINST (:q IN BOOLEAN MODE)';
}
if ($search_op_wheres !== []) {
diff --git a/app/src/Legacy/Classes/Settings.php b/app/src/Legacy/Classes/Settings.php
index 851e86c..c471dfd 100644
--- a/app/src/Legacy/Classes/Settings.php
+++ b/app/src/Legacy/Classes/Settings.php
@@ -386,6 +386,16 @@ class Settings
'watermark_target_min_width' => '100',
]
],
+ 'CHEVERETO_ENABLE_SEO_IMAGE_URL' => ['0',
+ [
+ 'seo_image_urls' => false,
+ ]
+ ],
+ 'CHEVERETO_ENABLE_SEO_ALBUM_URL' => ['0',
+ [
+ 'seo_album_urls' => false,
+ ]
+ ],
] as $envKey => $settingValues) {
if (env()[$envKey] == $settingValues[0]) {
foreach ($settingValues[1] as $k => $v) {
diff --git a/app/src/Legacy/Classes/Upload.php b/app/src/Legacy/Classes/Upload.php
index bb682e7..304b8bc 100644
--- a/app/src/Legacy/Classes/Upload.php
+++ b/app/src/Legacy/Classes/Upload.php
@@ -67,6 +67,8 @@ class Upload
private array|string $source;
+ private string $source_extension;
+
private array $uploaded = [];
public bool $detectFlood = true;
@@ -145,6 +147,10 @@ class Upload
$this->type = (is_image_url($this->source) || is_url($this->source))
? 'url'
: 'file';
+ $this->source_extension = $this->type === 'url'
+ ? pathinfo($this->source, PATHINFO_EXTENSION)
+ : pathinfo($this->source['name'], PATHINFO_EXTENSION);
+ $this->source_extension = strtolower($this->source_extension);
if ($this->type === 'url') {
if (Settings::get('enable_uploads_url') === false) {
throw new LogicException(
@@ -202,6 +208,9 @@ class Upload
}
$this->source_name = get_basename_without_extension($this->type == 'url' ? $this->source : $this->source['name']);
$this->extension = $this->source_image_fileinfo['extension'];
+ if ($this->extension === 'jpeg' && $this->source_extension === 'jpg') {
+ $this->extension = 'jpg';
+ }
if (!isset($this->name)) {
$this->name = $this->source_name;
}
@@ -211,7 +220,7 @@ class Upload
}
$this->fixed_filename = preg_replace('/(.*)\.(th|md|original|lg)\.([\w]+)$/', '$1.$3', $this->name . '.' . $this->extension);
$is_360 = false;
- if ($this->extension == 'jpeg') {
+ if (in_array($this->extension, ['jpg', 'jpeg'])) {
$xmpDataExtractor = new XmpMetadataExtractor();
$xmpData = $xmpDataExtractor->extractFromFile($this->downstream);
$reader = \PHPExif\Reader\Reader::factory(\PHPExif\Reader\Reader::TYPE_NATIVE);
@@ -319,6 +328,7 @@ class Upload
'fileinfo' => $fileInfo,
'frame' => $frameFile,
'frameinfo' => $frameFile ? get_image_fileinfo($frameFile) : [],
+ 'extension' => $this->extension,
];
}
diff --git a/app/src/Legacy/G/functions.php b/app/src/Legacy/G/functions.php
index c2db5f6..0f690bd 100644
--- a/app/src/Legacy/G/functions.php
+++ b/app/src/Legacy/G/functions.php
@@ -1957,15 +1957,28 @@ function extension_to_mime(string $ext): string
][$ext] ?? '';
}
+function get_ffmpeg_error(Throwable $e): string
+{
+ $previous = $e->getPrevious() ?
+ (': ' . $e->getPrevious()->getMessage()) :
+ '';
+
+ return $e->getMessage() . $previous;
+}
+
function get_video_fileinfo(string $file): array
{
clearstatcache(true, $file);
- $ffprobe = FFProbe::create();
try {
+ $ffprobe = FFProbe::create(
+ [
+ 'ffprobe.binaries' => env()['CHEVERETO_BINARY_FFPROBE'],
+ ]
+ );
$format = $ffprobe->format($file);
} catch (Throwable $e) {
- throw new Exception("FFprobe error: " . $e->getMessage(), 600);
+ throw new Exception("FFprobe error: " . get_ffmpeg_error($e), 600);
}
if (!($format->get('duration') > 0)) {
throw new Exception("Invalid video file provided", 100);
diff --git a/app/src/Legacy/functions.php b/app/src/Legacy/functions.php
index f17b123..ba41a85 100644
--- a/app/src/Legacy/functions.php
+++ b/app/src/Legacy/functions.php
@@ -1007,7 +1007,7 @@ function loaderHandler(
'CHEVERETO_ENABLE_BANNERS' => '0',
'CHEVERETO_ENABLE_BULK_IMPORTER' => '0',
'CHEVERETO_ENABLE_CAPTCHA' => '0',
- 'CHEVERETO_ENABLE_CDN' => '0',
+ 'CHEVERETO_ENABLE_CDN' => '1',
'CHEVERETO_ENABLE_CONSENT_SCREEN' => '0',
'CHEVERETO_ENABLE_COOKIE_COMPLIANCE' => '0',
'CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES' => '1',
@@ -1035,6 +1035,8 @@ function loaderHandler(
'CHEVERETO_ENABLE_UPLOAD_PLUGIN' => '0',
'CHEVERETO_ENABLE_UPLOAD_WATERMARK' => '0',
'CHEVERETO_ENABLE_USERS' => '0',
+ 'CHEVERETO_ENABLE_SEO_IMAGE_URL' => '0',
+ 'CHEVERETO_ENABLE_SEO_ALBUM_URL' => '0',
'CHEVERETO_MAX_USERS' => '1',
'CHEVERETO_EDITION' => 'free',
));
diff --git a/app/upgrading.php b/app/upgrading.php
index 8221898..b125cf3 100644
--- a/app/upgrading.php
+++ b/app/upgrading.php
@@ -200,13 +200,14 @@ if ($singleStep || $action === 'extract') {
logger('Chevereto filesystem upgraded');
unlinkIfExists($lockUpgrading);
$safeResult = false;
- $command = $rootDir . '/app/bin/legacy -C update';
if (passthruEnabled()) {
- logger('Command passthru');
+ logger('Update command passthru');
+ $command = $rootDir . '/app/bin/legacy -C update';
$safeResult = passthru($command);
}
if ($safeResult === false) {
- logger('Continue with database update');
+ logger('Continuing with database update at /update');
+ $return = 'update';
}
if (PHP_SAPI !== 'cli') {
$continueUri = $rootUrl . $return;
diff --git a/content/legacy/system/style.css b/content/legacy/system/style.css
index e38d325..46a7d49 100644
--- a/content/legacy/system/style.css
+++ b/content/legacy/system/style.css
@@ -18,7 +18,6 @@ html {
color: #000;
font: 16px Helvetica, Arial, sans-serif;
line-height: 1.3;
-
}
.body--block {
diff --git a/content/legacy/themes/Peafowl/header.php b/content/legacy/themes/Peafowl/header.php
index edbc8db..f7e0e38 100644
--- a/content/legacy/themes/Peafowl/header.php
+++ b/content/legacy/themes/Peafowl/header.php
@@ -243,21 +243,18 @@ if (is_route('page') || is_route('plugin')) {
'),o=t('
'),r=t('
');t("body").append(i.html(o).prepend(r.html('
')))}else i=t("#tiptip_holder"),o=t("#tiptip_content"),r=t("#tiptip_arrow");return this.each(function(){function a(){var e;if(!1!==u.enter.call(l,d)&&(u.content?e=t.isFunction(u.content)?u.content.call(l,d):u.content:(e=u.content=l.attr(u.attribute),l.removeAttr(u.attribute)),e)){o.html(e),i.hide().removeAttr("class").css({margin:"0px","max-width":u.maxWidth}),u.cssClass&&i.addClass(u.cssClass),r.removeAttr("style");var n=parseInt(l.offset().top),a=parseInt(l.offset().left),s=parseInt(l.outerWidth()),c=parseInt(l.outerHeight()),f=i.outerWidth(),p=i.outerHeight(),g=Math.round((s-f)/2),m=Math.round((c-p)/2),b=Math.round(a+g),v=Math.round(n+c+u.edgeOffset),y="",w="",P=Math.round(f-12)/2;"bottom"==u.defaultPosition?y="_bottom":"top"==u.defaultPosition?y="_top":"left"==u.defaultPosition?y="_left":"right"==u.defaultPosition&&(y="_right");var $=g+a
parseInt(t(window).width());$&&g<0||"_right"==y&&!x||"_left"==y&&aparseInt(t(window).height()+t(window).scrollTop()),_=n+c-(u.edgeOffset+p+8)<0;F||"_bottom"==y&&F||"_top"==y&&!_?("_top"==y||"_bottom"==y?y="_top":y+="_top",w=p,v=Math.round(n-(p+5+u.edgeOffset))):(_|("_top"==y&&_)||"_bottom"==y&&!F)&&("_top"==y||"_bottom"==y?y="_bottom":y+="_bottom",w=-12,v=Math.round(n+c+u.edgeOffset)),"_right_top"==y||"_left_top"==y?v+=5:"_right_bottom"!=y&&"_left_bottom"!=y||(v-=5),"_left_top"!=y&&"_left_bottom"!=y||(b+=5),r.css({"margin-left":P+"px","margin-top":w+"px"}),i.css({"margin-left":b+"px","margin-top":v+"px"}).addClass("tip"+y),h&&clearTimeout(h),h=setTimeout(function(){i.stop(!0,!0).fadeIn(u.fadeIn)},u.delay),u.afterEnter.call(l,d)}}function s(){!1!==u.exit.call(l,d)&&(h&&clearTimeout(h),i.fadeOut(u.fadeOut),u.afterExit.call(l,d))}var l=t(this),c=l.data("tipTip"),u=c&&c.options||t.extend(n,e),d={holder:i,content:o,arrow:r,options:u};if(c)switch(e){case"show":a();break;case"hide":s();break;case"destroy":l.unbind(".tipTip").removeData("tipTip")}else{var h=!1;l.data("tipTip",{options:u}),"hover"==u.activation?l.bind("mouseenter.tipTip",function(){a()}).bind("mouseleave.tipTip",function(){u.keepAlive?i.one("mouseleave.tipTip",function(){s()}):s()}):"focus"==u.activation?l.bind("focus.tipTip",function(){a()}).bind("blur.tipTip",function(){s()}):"click"==u.activation?l.bind("click.tipTip",function(t){return t.preventDefault(),a(),!1}).bind("mouseleave.tipTip",function(){u.keepAlive?i.one("mouseleave.tipTip",function(){s()}):s()}):u.activation}})}}(jQuery),function(t){function e(t,e){if(!(t.originalEvent.touches.length>1)){t.preventDefault();var n=t.originalEvent.changedTouches[0],i=document.createEvent("MouseEvents");i.initMouseEvent(e,!0,!0,window,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),t.target.dispatchEvent(i)}}if(t.support.touch="ontouchend"in document,t.support.touch){var n,i=t.ui.mouse.prototype,o=i._mouseInit;i._touchStart=function(t){var i=this;!n&&i._mouseCapture(t.originalEvent.changedTouches[0])&&(n=!0,i._touchMoved=!1,e(t,"mouseover"),e(t,"mousemove"),e(t,"mousedown"))},i._touchMove=function(t){n&&(this._touchMoved=!0,e(t,"mousemove"))},i._touchEnd=function(t){n&&(e(t,"mouseup"),e(t,"mouseout"),this._touchMoved||e(t,"click"),n=!1)},i._mouseInit=function(){var e=this;e.element.bind("touchstart",t.proxy(e,"_touchStart")).bind("touchmove",t.proxy(e,"_touchMove")).bind("touchend",t.proxy(e,"_touchEnd")),o.call(e)}}}(jQuery),function(t){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],t):t(jQuery)}(function(t){function e(e){return!e||void 0!==e.allowPageScroll||void 0===e.swipe&&void 0===e.swipeStatus||(e.allowPageScroll=c),void 0!==e.click&&void 0===e.tap&&(e.tap=e.click),e||(e={}),e=t.extend({},t.fn.swipe.defaults,e),this.each(function(){var i=t(this),o=i.data(_);o||(o=new n(this,e),i.data(_,o))})}function n(e,n){function S(e){if(!(st()||t(e.target).closest(n.excludedElements,zt).length>0)){var i,o=e.originalEvent?e.originalEvent:e,r=F?o.touches[0]:o;return qt=w,F?Nt=o.touches.length:e.preventDefault(),Ot=0,At=null,Bt=null,Ht=0,Mt=0,Lt=0,Dt=1,Ut=0,Wt=ht(),Rt=gt(),rt(),!F||Nt===n.fingers||n.fingers===v||R()?(ct(0,r),Qt=Ft(),2==Nt&&(ct(1,o.touches[1]),Mt=Lt=vt(Wt[0].start,Wt[1].start)),(n.swipeStatus||n.pinchStatus)&&(i=O(o,qt))):i=!1,!1===i?(qt=x,O(o,qt),i):(lt(!0),null)}}function j(t){var e=t.originalEvent?t.originalEvent:t;if(qt!==$&&qt!==x&&!at()){var i,o=F?e.touches[0]:e,r=ut(o);if(Vt=Ft(),F&&(Nt=e.touches.length),qt=P,2==Nt&&(0==Mt?(ct(1,e.touches[1]),Mt=Lt=vt(Wt[0].start,Wt[1].start)):(ut(e.touches[1]),Lt=vt(Wt[0].end,Wt[1].end),Bt=wt(Wt[0].end,Wt[1].end)),Dt=yt(Mt,Lt),Ut=Math.abs(Mt-Lt)),Nt===n.fingers||n.fingers===v||!F||R()){if(At=xt(r.start,r.end),U(t,At),Ot=Pt(r.start,r.end),Ht=bt(),ft(At,Ot),(n.swipeStatus||n.pinchStatus)&&(i=O(e,qt)),!n.triggerOnTouchEnd||n.triggerOnTouchLeave){var a=!0;if(n.triggerOnTouchLeave){var s=_t(this);a=St(r.end,s)}!n.triggerOnTouchEnd&&a?qt=E(P):n.triggerOnTouchLeave&&!a&&(qt=E($)),qt!=x&&qt!=$||O(e,qt)}}else qt=x,O(e,qt);!1===i&&(qt=x,O(e,qt))}}function k(t){var e=t.originalEvent;return F&&e.touches.length>0?(ot(),!0):(at()&&(Nt=Xt),t.preventDefault(),Vt=Ft(),Ht=bt(),M()?(qt=x,O(e,qt)):n.triggerOnTouchEnd||0==n.triggerOnTouchEnd&&qt===P?(qt=$,O(e,qt)):!n.triggerOnTouchEnd&&G()?(qt=$,A(e,qt,f)):qt===P&&(qt=x,O(e,qt)),lt(!1),null)}function T(){Nt=0,Vt=0,Qt=0,Mt=0,Lt=0,Dt=1,rt(),lt(!1)}function C(t){var e=t.originalEvent;n.triggerOnTouchLeave&&(qt=E($),O(e,qt))}function I(){zt.unbind(kt,S),zt.unbind(Et,T),zt.unbind(Tt,j),zt.unbind(Ct,k),It&&zt.unbind(It,C),lt(!1)}function E(t){var e=t,i=D(),o=H(),r=M();return!i||r?e=x:!o||t!=P||n.triggerOnTouchEnd&&!n.triggerOnTouchLeave?!o&&t==$&&n.triggerOnTouchLeave&&(e=x):e=$,e}function O(t,e){var n=void 0;return W()||N()?n=A(t,e,d):(z()||R())&&!1!==n&&(n=A(t,e,h)),nt()&&!1!==n?n=A(t,e,p):it()&&!1!==n?n=A(t,e,g):et()&&!1!==n&&(n=A(t,e,f)),e===x&&T(t),e===$&&(F?0==t.touches.length&&T(t):T(t)),n}function A(e,c,u){var m=void 0;if(u==d){if(zt.trigger("swipeStatus",[c,At||null,Ot||0,Ht||0,Nt]),n.swipeStatus&&(m=n.swipeStatus.call(zt,e,c,At||null,Ot||0,Ht||0,Nt),!1===m))return!1;if(c==$&&q()){if(zt.trigger("swipe",[At,Ot,Ht,Nt]),n.swipe&&(m=n.swipe.call(zt,e,At,Ot,Ht,Nt),!1===m))return!1;switch(At){case i:zt.trigger("swipeLeft",[At,Ot,Ht,Nt]),n.swipeLeft&&(m=n.swipeLeft.call(zt,e,At,Ot,Ht,Nt));break;case o:zt.trigger("swipeRight",[At,Ot,Ht,Nt]),n.swipeRight&&(m=n.swipeRight.call(zt,e,At,Ot,Ht,Nt));break;case r:zt.trigger("swipeUp",[At,Ot,Ht,Nt]),n.swipeUp&&(m=n.swipeUp.call(zt,e,At,Ot,Ht,Nt));break;case a:zt.trigger("swipeDown",[At,Ot,Ht,Nt]),n.swipeDown&&(m=n.swipeDown.call(zt,e,At,Ot,Ht,Nt))}}}if(u==h){if(zt.trigger("pinchStatus",[c,Bt||null,Ut||0,Ht||0,Nt,Dt]),n.pinchStatus&&(m=n.pinchStatus.call(zt,e,c,Bt||null,Ut||0,Ht||0,Nt,Dt),!1===m))return!1;if(c==$&&B())switch(Bt){case s:zt.trigger("pinchIn",[Bt||null,Ut||0,Ht||0,Nt,Dt]),n.pinchIn&&(m=n.pinchIn.call(zt,e,Bt||null,Ut||0,Ht||0,Nt,Dt));break;case l:zt.trigger("pinchOut",[Bt||null,Ut||0,Ht||0,Nt,Dt]),n.pinchOut&&(m=n.pinchOut.call(zt,e,Bt||null,Ut||0,Ht||0,Nt,Dt))}}return u==f?c!==x&&c!==$||(clearTimeout(Jt),X()&&!K()?(Yt=Ft(),Jt=setTimeout(t.proxy(function(){Yt=null,zt.trigger("tap",[e.target]),n.tap&&(m=n.tap.call(zt,e,e.target))},this),n.doubleTapThreshold)):(Yt=null,zt.trigger("tap",[e.target]),n.tap&&(m=n.tap.call(zt,e,e.target)))):u==p?c!==x&&c!==$||(clearTimeout(Jt),Yt=null,zt.trigger("doubletap",[e.target]),n.doubleTap&&(m=n.doubleTap.call(zt,e,e.target))):u==g&&(c!==x&&c!==$||(clearTimeout(Jt),Yt=null,zt.trigger("longtap",[e.target]),n.longTap&&(m=n.longTap.call(zt,e,e.target)))),m}function H(){var t=!0;return null!==n.threshold&&(t=Ot>=n.threshold),t}function M(){var t=!1;return null!==n.cancelThreshold&&null!==At&&(t=pt(At)-Ot>=n.cancelThreshold),t}function L(){return null===n.pinchThreshold||Ut>=n.pinchThreshold}function D(){var t;return t=!n.maxTimeThreshold||!(Ht>=n.maxTimeThreshold),t}function U(t,e){if(n.allowPageScroll===c||R())t.preventDefault();else{var s=n.allowPageScroll===u;switch(e){case i:(n.swipeLeft&&s||!s&&n.allowPageScroll!=m)&&t.preventDefault();break;case o:(n.swipeRight&&s||!s&&n.allowPageScroll!=m)&&t.preventDefault();break;case r:(n.swipeUp&&s||!s&&n.allowPageScroll!=b)&&t.preventDefault();break;case a:(n.swipeDown&&s||!s&&n.allowPageScroll!=b)&&t.preventDefault()}}}function B(){var t=Q(),e=V(),n=L();return t&&e&&n}function R(){return!!(n.pinchStatus||n.pinchIn||n.pinchOut)}function z(){return!(!B()||!R())}function q(){var t=D(),e=H(),n=Q(),i=V(),o=M(),r=!o&&i&&n&&e&&t;return r}function N(){return!!(n.swipe||n.swipeStatus||n.swipeLeft||n.swipeRight||n.swipeUp||n.swipeDown)}function W(){return!(!q()||!N())}function Q(){return Nt===n.fingers||n.fingers===v||!F}function V(){return 0!==Wt[0].end.x}function G(){return!!n.tap}function X(){return!!n.doubleTap}function Y(){return!!n.longTap}function J(){if(null==Yt)return!1;var t=Ft();return X()&&t-Yt<=n.doubleTapThreshold}function K(){return J()}function Z(){return(1===Nt||!F)&&(isNaN(Ot)||0===Ot)}function tt(){return Ht>n.longTapThreshold&&Ot=0?i:n<=360&&n>=315?i:n>=135&&n<=225?o:n>45&&n<135?a:r}function Ft(){var t=new Date;return t.getTime()}function _t(e){e=t(e);var n=e.offset(),i={left:n.left,right:n.left+e.outerWidth(),top:n.top,bottom:n.top+e.outerHeight()};return i}function St(t,e){return t.x>e.left&&t.xe.top&&t.ya?(n.maxWidth=r*a,n.maxHeight=r):(n.maxWidth=o,n.maxHeight=o/a),n},e.renderImageToCanvas=function(t,e,n,i,o,r,a,s,l,c){return t.getContext("2d").drawImage(e,n,i,o,r,a,s,l,c),t},e.hasCanvasOption=function(t){return t.canvas||t.crop||!!t.aspectRatio},e.scale=function(t,n,i){function o(){var t=Math.max((l||P)/P,(c||$)/$);t>1&&(P*=t,$*=t)}function r(){var t=Math.min((a||P)/P,(s||$)/$);t<1&&(P*=t,$*=t)}n=n||{};var a,s,l,c,u,d,h,f,p,g,m,b=document.createElement("canvas"),v=t.getContext||e.hasCanvasOption(n)&&b.getContext,y=t.naturalWidth||t.width,w=t.naturalHeight||t.height,P=y,$=w;if(b.originalWidth=y,b.originalHeight=w,v&&(n=e.getTransformedOptions(t,n,i),h=n.left||0,f=n.top||0,n.sourceWidth?(u=n.sourceWidth,void 0!==n.right&&void 0===n.left&&(h=y-u-n.right)):u=y-h-(n.right||0),n.sourceHeight?(d=n.sourceHeight,void 0!==n.bottom&&void 0===n.top&&(f=w-d-n.bottom)):d=w-f-(n.bottom||0),P=u,$=d),a=n.maxWidth,s=n.maxHeight,l=n.minWidth,c=n.minHeight,v&&a&&s&&n.crop?(P=a,$=s,m=u/d-a/s,m<0?(d=s*u/a,void 0===n.top&&void 0===n.bottom&&(f=(w-d)/2)):m>0&&(u=a*d/s,void 0===n.left&&void 0===n.right&&(h=(y-u)/2))):((n.contain||n.cover)&&(l=a=a||l,c=s=s||c),n.cover?(r(),o()):(o(),r())),v){if(p=n.pixelRatio,p>1&&(b.style.width=P+"px",b.style.height=$+"px",P*=p,$*=p,b.getContext("2d").scale(p,p)),g=n.downsamplingRatio,g>0&&g<1&&PP;)b.width=u*g,b.height=d*g,e.renderImageToCanvas(b,t,h,f,u,d,0,0,b.width,b.height),u=b.width,d=b.height,t=document.createElement("canvas"),t.width=u,t.height=d,e.renderImageToCanvas(t,b,0,0,u,d,0,0,u,d);return b.width=P,b.height=$,e.transformCoordinates(b,n),e.renderImageToCanvas(b,t,h,f,u,d,0,0,P,$)}return t.width=P,t.height=$,t},e.createObjectURL=function(t){return!!i&&i.createObjectURL(t)},e.revokeObjectURL=function(t){return!!i&&i.revokeObjectURL(t)},e.readFile=function(t,e,n){if(window.FileReader){var i=new FileReader;if(i.onload=i.onerror=e,n=n||"readAsDataURL",i[n])return i[n](t),i}return!1},"function"==typeof define&&define.amd?define(function(){return e}):"object"==typeof module&&module.exports?module.exports=e:t.loadImage=e}(window),function(t){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],t):t("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(t){"use strict";var e=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);t.blobSlice=e&&function(){var t=this.slice||this.webkitSlice||this.mozSlice;return t.apply(this,arguments)},t.metaDataParsers={jpeg:{65505:[]}},t.parseMetaData=function(e,n,i,o){i=i||{},o=o||{};var r=this,a=i.maxMetaDataSize||262144,s=!(window.DataView&&e&&e.size>=12&&"image/jpeg"===e.type&&t.blobSlice);!s&&t.readFile(t.blobSlice.call(e,0,a),function(e){if(e.target.error)return console.log(e.target.error),void n(o);var a,s,l,c,u=e.target.result,d=new DataView(u),h=2,f=d.byteLength-4,p=h;if(65496===d.getUint16(0)){for(;h=65504&&a<=65519||65534===a);){if(s=d.getUint16(h+2)+2,h+s>d.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(l=t.metaDataParsers.jpeg[a])for(c=0;c6&&(u.slice?o.imageHead=u.slice(0,p):o.imageHead=new Uint8Array(u).subarray(0,p))}else console.log("Invalid JPEG file: Missing JPEG marker.");n(o)},"readAsArrayBuffer")||n(o)},t.hasMetaOption=function(t){return t.meta};var n=t.transform;t.transform=function(e,i,o,r,a){t.hasMetaOption(i||{})?t.parseMetaData(r,function(a){n.call(t,e,i,o,r,a)},i,a):n.apply(t,arguments)}}),function(t){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],t):"object"==typeof module&&module.exports?t(require("./load-image"),require("./load-image-meta")):t(window.loadImage)}(function(t){"use strict";t.ExifMap=function(){return this},t.ExifMap.prototype.map={Orientation:274},t.ExifMap.prototype.get=function(t){return this[t]||this[this.map[t]]},t.getExifThumbnail=function(t,e,n){var i,o,r;if(n&&!(e+n>t.byteLength)){for(i=[],o=0;o4?n+e.getUint32(i+8,a):i+8,!(l+s>e.byteLength)){if(1===r)return f.getValue(e,l,a);for(c=[],u=0;ut.byteLength)console.log("Invalid Exif data: Invalid directory offset.");else{if(r=t.getUint16(n,i),a=n+2+12*r,!(a+4>t.byteLength)){for(s=0;se.byteLength)return void console.log("Invalid Exif data: Invalid segment size.");if(0!==e.getUint16(n+8))return void console.log("Invalid Exif data: Missing byte alignment offset.");switch(e.getUint16(c)){case 18761:a=!0;break;case 19789:a=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}if(42!==e.getUint16(c+2,a))return void console.log("Invalid Exif data: Missing TIFF marker.");s=e.getUint32(c+4,a),o.exif=new t.ExifMap,s=t.parseExifTags(e,c,c+s,a,o),s&&!r.disableExifThumbnail&&(l={exif:{}},s=t.parseExifTags(e,c,c+s,a,l),l.exif[513]&&(o.exif.Thumbnail=t.getExifThumbnail(e,c+l.exif[513],l.exif[514]))),o.exif[34665]&&!r.disableExifSub&&t.parseExifTags(e,c,c+o.exif[34665],a,o),
o.exif[34853]&&!r.disableExifGps&&t.parseExifTags(e,c,c+o.exif[34853],a,o)}}},t.metaDataParsers.jpeg[65505].push(t.parseExifData)}),function(t){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-exif"],t):"object"==typeof module&&module.exports?t(require("./load-image"),require("./load-image-exif")):t(window.loadImage)}(function(t){"use strict";t.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},t.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},t.ExifMap.prototype.getText=function(t){var e=this.get(t);switch(t){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[t][e];case"ExifVersion":case"FlashpixVersion":if(!e)return;return String.fromCharCode(e[0],e[1],e[2],e[3]);case"ComponentsConfiguration":if(!e)return;return this.stringValues[t][e[0]]+this.stringValues[t][e[1]]+this.stringValues[t][e[2]]+this.stringValues[t][e[3]];case"GPSVersionID":if(!e)return;return e[0]+"."+e[1]+"."+e[2]+"."+e[3]}return String(e)},function(t){var e,n=t.tags,i=t.map;for(e in n)n.hasOwnProperty(e)&&(i[n[e]]=e)}(t.ExifMap.prototype),t.ExifMap.prototype.getAll=function(){var t,e,n={};for(t in this)this.hasOwnProperty(t)&&(e=this.tags[t],e&&(n[e]=this.getText(e)));return n}}),function(t){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],t):t("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(t){"use strict";var e=t.hasCanvasOption,n=t.hasMetaOption,i=t.transformCoordinates,o=t.getTransformedOptions;t.hasCanvasOption=function(n){return!!n.orientation||e.call(t,n)},t.hasMetaOption=function(e){return!0===e.orientation||n.call(t,e)},t.transformCoordinates=function(e,n){i.call(t,e,n);var o=e.getContext("2d"),r=e.width,a=e.height,s=e.style.width,l=e.style.height,c=n.orientation;if(c&&!(c>8))switch(c>4&&(e.width=a,e.height=r,e.style.width=l,e.style.height=s),c){case 2:o.translate(r,0),o.scale(-1,1);break;case 3:o.translate(r,a),o.rotate(Math.PI);break;case 4:o.translate(0,a),o.scale(1,-1);break;case 5:o.rotate(.5*Math.PI),o.scale(1,-1);break;case 6:o.rotate(.5*Math.PI),o.translate(0,-a);break;case 7:o.rotate(.5*Math.PI),o.translate(r,-a),o.scale(-1,1);break;case 8:o.rotate(-.5*Math.PI),o.translate(-r,0)}},t.getTransformedOptions=function(e,n,i){var r,a,s=o.call(t,e,n),l=s.orientation;if(!0===l&&i&&i.exif&&(l=i.exif.get("Orientation")),!l||l>8||1===l)return s;for(a in r={},s)s.hasOwnProperty(a)&&(r[a]=s[a]);switch(r.orientation=l,l){case 2:r.left=s.right,r.right=s.left;break;case 3:r.left=s.right,r.top=s.bottom,r.right=s.left,r.bottom=s.top;break;case 4:r.top=s.bottom,r.bottom=s.top;break;case 5:r.left=s.top,r.top=s.left,r.right=s.bottom,r.bottom=s.right;break;case 6:r.left=s.top,r.top=s.right,r.right=s.bottom,r.bottom=s.left;break;case 7:r.left=s.bottom,r.top=s.right,r.right=s.top,r.bottom=s.left;break;case 8:r.left=s.bottom,r.top=s.left,r.right=s.top,r.bottom=s.right}return s.orientation>4&&(r.maxWidth=s.maxHeight,r.maxHeight=s.maxWidth,r.minWidth=s.minHeight,r.minHeight=s.minWidth,r.sourceWidth=s.sourceHeight,r.sourceHeight=s.sourceWidth),r}}),"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return t<10?"0"+t:t}function quote(t){return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var n,i,o,r,a,s=gap,l=e[t];switch(l&&"object"==typeof l&&"function"==typeof l.toJSON&&(l=l.toJSON(t)),"function"==typeof rep&&(l=rep.call(e,t,l)),typeof l){case"string":return quote(l);case"number":return isFinite(l)?String(l):"null";case"boolean":case"null":return String(l);case"object":if(!l)return"null";if(gap+=indent,a=[],"[object Array]"===Object.prototype.toString.apply(l)){for(r=l.length,n=0;n")&&n[0];);return t>4&&t}();return t},h.isInternetExplorer=function(){var t=h.isInternetExplorer.cached=void 0!==h.isInternetExplorer.cached?h.isInternetExplorer.cached:Boolean(h.getInternetExplorerMajorVersion());return t},h.options.html4Mode?h.emulated={pushState:!0,hashChange:!0}:h.emulated={pushState:!Boolean(t.history&&t.history.pushState&&t.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(o.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(o.userAgent)),hashChange:Boolean(!("onhashchange"in t||"onhashchange"in i)||h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8)},h.enabled=!h.emulated.pushState,h.bugs={setHash:Boolean(!h.emulated.pushState&&"Apple Computer, Inc."===o.vendor&&/AppleWebKit\/5([0-2]|3[0-3])/.test(o.userAgent)),safariPoll:Boolean(!h.emulated.pushState&&"Apple Computer, Inc."===o.vendor&&/AppleWebKit\/5([0-2]|3[0-3])/.test(o.userAgent)),ieDoubleCheck:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<7)},h.isEmptyObject=function(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0},h.cloneObject=function(t){var e,n;return t?(e=u.stringify(t),n=u.parse(e)):n={},n},h.getRootUrl=function(){var t=i.location.protocol+"//"+(i.location.hostname||i.location.host);return i.location.port&&(t+=":"+i.location.port),t+="/",t},h.getBaseHref=function(){var t=i.getElementsByTagName("base"),e=null,n="";return 1===t.length&&(e=t[0],n=e.href.replace(/[^\/]+$/,"")),n=n.replace(/\/+$/,""),n&&(n+="/"),n},h.getBaseUrl=function(){var t=h.getBaseHref()||h.getBasePageUrl()||h.getRootUrl();return t},h.getPageUrl=function(){var t,e=h.getState(!1,!1),n=(e||{}).url||h.getLocationHref();return t=n.replace(/\/+$/,"").replace(/[^\/]+$/,function(t,e,n){return/\./.test(t)?t:t+"/"}),t},h.getBasePageUrl=function(){var t=h.getLocationHref().replace(/[#\?].*/,"").replace(/[^\/]+$/,function(t,e,n){return/[^\/]$/.test(t)?"":t}).replace(/\/+$/,"")+"/";return t},h.getFullUrl=function(t,e){var n=t,i=t.substring(0,1);return e=void 0===e||e,/[a-z]+\:\/\//.test(t)||(n="/"===i?h.getRootUrl()+t.replace(/^\/+/,""):"#"===i?h.getPageUrl().replace(/#.*/,"")+t:"?"===i?h.getPageUrl().replace(/[\?#].*/,"")+t:e?h.getBaseUrl()+t.replace(/^(\.\/)+/,""):h.getBasePageUrl()+t.replace(/^(\.\/)+/,"")),n.replace(/\#$/,"")},h.getShortUrl=function(t){var e=t,n=h.getBaseUrl(),i=h.getRootUrl();return h.emulated.pushState&&(e=e.replace(n,"")),e=e.replace(i,"/"),h.isTraditionalAnchor(e)&&(e="./"+e),e=e.replace(/^(\.\/)+/g,"./").replace(/\#$/,""),e},h.getLocationHref=function(t){return t=t||i,t.URL===t.location.href?t.location.href:t.location.href===decodeURIComponent(t.URL)?t.URL:t.location.hash&&decodeURIComponent(t.location.href.replace(/^[^#]+/,""))===t.location.hash?t.location.href:-1==t.URL.indexOf("#")&&-1!=t.location.href.indexOf("#")?t.location.href:t.URL||t.location.href},h.store={},h.idToState=h.idToState||{},h.stateToId=h.stateToId||{},h.urlToId=h.urlToId||{},h.storedStates=h.storedStates||[],h.savedStates=h.savedStates||[],h.normalizeStore=function(){h.store.idToState=h.store.idToState||{},h.store.urlToId=h.store.urlToId||{},h.store.stateToId=h.store.stateToId||{}},h.getState=function(t,e){void 0===t&&(t=!0),void 0===e&&(e=!0);var n=h.getLastSavedState();return!n&&e&&(n=h.createStateObject()),t&&(n=h.cloneObject(n),n.url=n.cleanUrl||n.url),n},h.getIdByState=function(t){var e,n=h.extractId(t.url);if(!n)if(e=h.getStateString(t),void 0!==h.stateToId[e])n=h.stateToId[e];else if(void 0!==h.store.stateToId[e])n=h.store.stateToId[e];else{for(;n=(new Date).getTime()+String(Math.random()).replace(/\D/g,""),void 0!==h.idToState[n]||void 0!==h.store.idToState[n];);h.stateToId[e]=n,h.idToState[n]=t}return n},h.normalizeState=function(t){var e,n;return t&&"object"==typeof t||(t={}),void 0!==t.normalized?t:(t.data&&"object"==typeof t.data||(t.data={}),e={},e.normalized=!0,e.title=t.title||"",e.url=h.getFullUrl(t.url?t.url:h.getLocationHref()),e.hash=h.getShortUrl(e.url),e.data=h.cloneObject(t.data),e.id=h.getIdByState(e),e.cleanUrl=e.url.replace(/\??\&_suid.*/,""),e.url=e.cleanUrl,n=!h.isEmptyObject(e.data),(e.title||n)&&!0!==h.options.disableSuid&&(e.hash=h.getShortUrl(e.url).replace(/\??\&_suid.*/,""),/\?/.test(e.hash)||(e.hash+="?"),e.hash+="&_suid="+e.id),e.hashedUrl=h.getFullUrl(e.hash),(h.emulated.pushState||h.bugs.safariPoll)&&h.hasUrlDuplicate(e)&&(e.url=e.hashedUrl),e)},h.createStateObject=function(t,e,n){var i={data:t,title:e,url:n};return i=h.normalizeState(i),i},h.getStateById=function(t){t=String(t);var n=h.idToState[t]||h.store.idToState[t]||e;return n},h.getStateString=function(t){var e,n,i;return e=h.normalizeState(t),n={data:e.data,title:t.title,url:t.url},i=u.stringify(n),i},h.getStateId=function(t){var e,n;return e=h.normalizeState(t),n=e.id,n},h.getHashByState=function(t){var e,n;return e=h.normalizeState(t),n=e.hash,n},h.extractId=function(t){var e,n,i;return i=-1!=t.indexOf("#")?t.split("#")[0]:t,n=/(.*)\&_suid=([0-9]+)$/.exec(i),n&&n[1]||t,e=n?String(n[2]||""):"",e||!1},h.isTraditionalAnchor=function(t){var e=!/[\/\?\.]/.test(t);return e},h.extractState=function(t,e){var n,i,o=null;return e=e||!1,n=h.extractId(t),n&&(o=h.getStateById(n)),o||(i=h.getFullUrl(t),n=h.getIdByUrl(i)||!1,n&&(o=h.getStateById(n)),!o&&e&&!h.isTraditionalAnchor(t)&&(o=h.createStateObject(null,null,i))),o},h.getIdByUrl=function(t){var n=h.urlToId[t]||h.store.urlToId[t]||e;return n},h.getLastSavedState=function(){return h.savedStates[h.savedStates.length-1]||e},h.getLastStoredState=function(){return h.storedStates[h.storedStates.length-1]||e},h.hasUrlDuplicate=function(t){var e,n=!1;return e=h.extractState(t.url),n=e&&e.id!==t.id,n},h.storeState=function(t){return h.urlToId[t.url]=t.id,h.storedStates.push(h.cloneObject(t)),t},h.isLastSavedState=function(t){var e,n,i,o=!1;return h.savedStates.length&&(e=t.id,n=h.getLastSavedState(),i=n.id,o=e===i),o},h.saveState=function(t){return!h.isLastSavedState(t)&&(h.savedStates.push(h.cloneObject(t)),!0)},h.getStateByIndex=function(t){var e=null;return e=void 0===t?h.savedStates[h.savedStates.length-1]:t<0?h.savedStates[h.savedStates.length+t]:h.savedStates[t],e},h.getCurrentIndex=function(){var t=null;return t=h.savedStates.length<1?0:h.savedStates.length-1,t},h.getHash=function(t){var e,n=h.getLocationHref(t);return e=h.getHashByUrl(n),e},h.unescapeHash=function(t){var e=h.normalizeHash(t);return e=decodeURIComponent(e),e},h.normalizeHash=function(t){var e=t.replace(/[^#]*#/,"").replace(/#.*/,"");return e},h.setHash=function(t,e){var n,o;return!1!==e&&h.busy()?(h.pushQueue({scope:h,callback:h.setHash,args:arguments,queue:e}),!1):(h.busy(!0),n=h.extractState(t,!0),n&&!h.emulated.pushState?h.pushState(n.data,n.title,n.url,!1):h.getHash()!==t&&(h.bugs.setHash?(o=h.getPageUrl(),h.pushState(null,null,o+"#"+t,!1)):i.location.hash=t),h)},h.escapeHash=function(e){var n=h.normalizeHash(e);return n=t.encodeURIComponent(n),h.bugs.hashEscape||(n=n.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?")),n},h.getHashByUrl=function(t){var e=String(t).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");return e=h.unescapeHash(e),e},h.setTitle=function(t){var e,n=t.title;n||(e=h.getStateByIndex(0),e&&e.url===t.url&&(n=e.title||h.options.initialTitle));try{i.getElementsByTagName("title")[0].innerHTML=n.replace("<","<").replace(">",">").replace(" & "," & ")}catch(t){}return i.title=n,h},h.queues=[],h.busy=function(t){if(void 0!==t?h.busy.flag=t:void 0===h.busy.flag&&(h.busy.flag=!1),!h.busy.flag){s(h.busy.timeout);var e=function(){var t,n,i;if(!h.busy.flag)for(t=h.queues.length-1;t>=0;--t)n=h.queues[t],0!==n.length&&(i=n.shift(),h.fireQueueItem(i),h.busy.timeout=a(e,h.options.busyDelay))};h.busy.timeout=a(e,h.options.busyDelay)}return h.busy.flag},h.busy.flag=!1,h.fireQueueItem=function(t){return t.callback.apply(t.scope||h,t.args||[])},h.pushQueue=function(t){return h.queues[t.queue||0]=h.queues[t.queue||0]||[],h.queues[t.queue||0].push(t),h},h.queue=function(t,e){return"function"==typeof t&&(t={callback:t}),void 0!==e&&(t.queue=e),h.busy()?h.pushQueue(t):h.fireQueueItem(t),h},h.clearQueue=function(){return h.busy.flag=!1,h.queues=[],h},h.stateChanged=!1,h.doubleChecker=!1,h.doubleCheckComplete=function(){return h.stateChanged=!0,h.doubleCheckClear(),h},h.doubleCheckClear=function(){return h.doubleChecker&&(s(h.doubleChecker),h.doubleChecker=!1),h},h.doubleCheck=function(t){return h.stateChanged=!1,h.doubleCheckClear(),h.bugs.ieDoubleCheck&&(h.doubleChecker=a(function(){return h.doubleCheckClear(),h.stateChanged||t(),!0},h.options.doubleCheckInterval)),h},h.safariStatePoll=function(){var e,n=h.extractState(h.getLocationHref());if(!h.isLastSavedState(n))return e=n,e||(e=h.createStateObject()),h.Adapter.trigger(t,"popstate"),h},h.back=function(t){return!1!==t&&h.busy()?(h.pushQueue({scope:h,callback:h.back,args:arguments,queue:t}),!1):(h.busy(!0),h.doubleCheck(function(){h.back(!1)}),f.go(-1),!0)},h.forward=function(t){return!1!==t&&h.busy()?(h.pushQueue({scope:h,callback:h.forward,args:arguments,queue:t}),!1):(h.busy(!0),h.doubleCheck(function(){h.forward(!1)}),f.go(1),!0)},h.go=function(t,e){var n;if(t>0)for(n=1;n<=t;++n)h.forward(e);else{if(!(t<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(n=-1;n>=t;--n)h.back(e)}return h},h.emulated.pushState){var g=function(){};h.pushState=h.pushState||g,h.replaceState=h.replaceState||g}else h.onPopState=function(e,n){var i,o,r=!1,a=!1;return h.doubleCheckComplete(),i=h.getHash(),i?(o=h.extractState(i||h.getLocationHref(),!0),o?h.replaceState(o.data,o.title,o.url,!1):(h.Adapter.trigger(t,"anchorchange"),h.busy(!1)),h.expectedStateId=!1,!1):(r=h.Adapter.extractEventData("state",e,n)||!1,a=r?h.getStateById(r):h.expectedStateId?h.getStateById(h.expectedStateId):h.extractState(h.getLocationHref()),a||(a=h.createStateObject(null,null,h.getLocationHref())),h.expectedStateId=!1,h.isLastSavedState(a)?(h.busy(!1),!1):(h.storeState(a),h.saveState(a),h.setTitle(a),h.Adapter.trigger(t,"statechange"),h.busy(!1),!0))},h.Adapter.bind(t,"popstate",h.onPopState),h.pushState=function(e,n,i,o){if(h.getHashByUrl(i)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(!1!==o&&h.busy())return h.pushQueue({scope:h,callback:h.pushState,args:arguments,queue:o}),!1;h.busy(!0);var r=h.createStateObject(e,n,i);return h.isLastSavedState(r)?h.busy(!1):(h.storeState(r),h.expectedStateId=r.id,f.pushState(r.id,r.title,r.url),h.Adapter.trigger(t,"popstate")),!0},h.replaceState=function(e,n,i,o){if(h.getHashByUrl(i)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(!1!==o&&h.busy())return h.pushQueue({scope:h,callback:h.replaceState,args:arguments,queue:o}),!1;h.busy(!0);var r=h.createStateObject(e,n,i);return h.isLastSavedState(r)?h.busy(!1):(h.storeState(r),h.expectedStateId=r.id,f.replaceState(r.id,r.title,r.url),h.Adapter.trigger(t,"popstate")),!0};if(r){try{h.store=u.parse(r.getItem("History.store"))||{}}catch(t){h.store={}}h.normalizeStore()}else h.store={},h.normalizeStore();h.Adapter.bind(t,"unload",h.clearAllIntervals),h.saveState(h.storeState(h.extractState(h.getLocationHref(),!0))),r&&(h.onUnload=function(){var t,e,n;try{t=u.parse(r.getItem("History.store"))||{}}catch(e){t={}}for(e in t.idToState=t.idToState||{},t.urlToId=t.urlToId||{},t.stateToId=t.stateToId||{},h.idToState)h.idToState.hasOwnProperty(e)&&(t.idToState[e]=h.idToState[e]);for(e in h.urlToId)h.urlToId.hasOwnProperty(e)&&(t.urlToId[e]=h.urlToId[e]);for(e in h.stateToId)h.stateToId.hasOwnProperty(e)&&(t.stateToId[e]=h.stateToId[e]);h.store=t,h.normalizeStore(),n=u.stringify(t);try{r.setItem("History.store",n)}catch(t){if(t.code!==DOMException.QUOTA_EXCEEDED_ERR)throw t;r.length&&(r.removeItem("History.store"),r.setItem("History.store",n))}},h.intervalList.push(l(h.onUnload,h.options.storeInterval)),h.Adapter.bind(t,"beforeunload",h.onUnload),h.Adapter.bind(t,"unload",h.onUnload)),h.emulated.pushState||(h.bugs.safariPoll&&h.intervalList.push(l(h.safariStatePoll,h.options.safariPollInterval)),"Apple Computer, Inc."!==o.vendor&&"Mozilla"!==(o.appCodeName||"")||(h.Adapter.bind(t,"hashchange",function(){h.Adapter.trigger(t,"popstate")}),h.getHash()&&h.Adapter.onDomLoad(function(){h.Adapter.trigger(t,"hashchange")})))},(!h.options||!h.options.delayInit)&&h.init()}(window),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(window.jQuery)}(function(t){var e=0;t.ajaxTransport("iframe",function(n){var i,o,r;if(n.async)return{send:function(a,s){i=t(''),i.attr("accept-charset",n.formAcceptCharset),r=/\?/.test(n.url)?"&":"?","DELETE"===n.type?(n.url=n.url+r+"_method=DELETE",n.type="POST"):"PUT"===n.type?(n.url=n.url+r+"_method=PUT",
diff --git a/content/legacy/themes/Peafowl/snippets/embed.php b/content/legacy/themes/Peafowl/snippets/embed.php
index ec3b06b..6fd4e63 100644
--- a/content/legacy/themes/Peafowl/snippets/embed.php
+++ b/content/legacy/themes/Peafowl/snippets/embed.php
@@ -61,7 +61,7 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'html-embed-full' => [
+ 'full-html-embed' => [
'label' => _s('%s full linked', 'HTML'),
'template' => [
'image' => '
',
@@ -69,12 +69,12 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'html-embed-medium' => [
+ 'medium-html-embed' => [
'label' => _s('%s medium linked', 'HTML'),
- 'template' => '
',
+ 'template' => '
',
'size' => 'medium',
],
- 'html-embed-thumbnail' => [
+ 'thumbnail-html-embed' => [
'label' => _s('%s thumbnail linked', 'HTML'),
'template' => '
',
'size' => 'thumb',
@@ -92,7 +92,7 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'markdown-embed-full' => [
+ 'full-markdown-embed' => [
'label' => _s('%s full linked', 'Markdown'),
'template' => [
'image' => '[](%URL_VIEWER%)',
@@ -100,12 +100,12 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'markdown-embed-medium' => [
+ 'medium-markdown-embed' => [
'label' => _s('%s medium linked', 'Markdown'),
- 'template' => '[](%URL_VIEWER%)',
+ 'template' => '[](%URL_VIEWER%)',
'size' => 'medium',
],
- 'markdown-embed-thumbnail' => [
+ 'thumbnail-markdown-embed' => [
'label' => _s('%s thumbnail linked', 'Markdown'),
'template' => '[](%URL_VIEWER%)',
'size' => 'thumb',
@@ -123,7 +123,7 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'bbcode-embed-full' => [
+ 'full-bbcode-embed' => [
'label' => _s('%s full linked', 'BBCode'),
'template' => [
'image' => '[url=%URL_VIEWER%][img]%URL%[/img][/url]',
@@ -131,12 +131,12 @@ $embed_upload_tpl = [
],
'size' => 'full',
],
- 'bbcode-embed-medium' => [
+ 'medium-bbcode-embed' => [
'label' => _s('%s medium linked', 'BBCode'),
- 'template' => '[url=%URL_VIEWER%][img]%DISPLAY_URL%[/img][/url]',
+ 'template' => '[url=%URL_VIEWER%][img]%MEDIUM_URL%[/img][/url]',
'size' => 'medium',
],
- 'bbcode-embed-thumbnail' => [
+ 'thumbnail-bbcode-embed' => [
'label' => _s('%s thumbnail linked', 'BBCode'),
'template' => '[url=%URL_VIEWER%][img]%THUMB_URL%[/img][/url]',
'size' => 'thumb',
diff --git a/content/legacy/themes/Peafowl/snippets/image.js.php b/content/legacy/themes/Peafowl/snippets/image.js.php
index d78593e..67831d5 100644
--- a/content/legacy/themes/Peafowl/snippets/image.js.php
+++ b/content/legacy/themes/Peafowl/snippets/image.js.php
@@ -111,6 +111,7 @@ if (!defined('ACCESS') || !ACCESS) {
medium: {
url: ""
},
+ display_url: "",
url_viewer: "",
path_viewer: "",
is_360: ,
diff --git a/content/legacy/themes/Peafowl/snippets/listing_tools_editor.php b/content/legacy/themes/Peafowl/snippets/listing_tools_editor.php
index 084a066..0b408ef 100644
--- a/content/legacy/themes/Peafowl/snippets/listing_tools_editor.php
+++ b/content/legacy/themes/Peafowl/snippets/listing_tools_editor.php
@@ -16,7 +16,7 @@ foreach ($tabs as $tab) {
if ((isset($tab['list']) && $tab['list'] === false) || isset($tab['tools']) && $tab['tools'] === false) {
continue;
} ?>
-