mirror of
https://github.com/chevereto/chevereto.git
synced 2025-10-26 07:46:18 +01:00
Automatic push 4.2.0
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevere.
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevere.org>
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -11,202 +11,113 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpCsFixer\Fixer\Alias\NoAliasFunctionsFixer;
|
||||
use PhpCsFixer\Fixer\Alias\NoAliasLanguageConstructCallFixer;
|
||||
use PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer;
|
||||
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
|
||||
use PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer;
|
||||
use PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer;
|
||||
use PhpCsFixer\Fixer\Basic\BracesFixer;
|
||||
use PhpCsFixer\Fixer\Basic\EncodingFixer;
|
||||
use PhpCsFixer\Fixer\Casing\ConstantCaseFixer;
|
||||
use PhpCsFixer\Fixer\Casing\LowercaseKeywordsFixer;
|
||||
use PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer;
|
||||
use PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer;
|
||||
use PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer;
|
||||
use PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer;
|
||||
use PhpCsFixer\Fixer\ArrayNotation\NormalizeIndexBraceFixer;
|
||||
use PhpCsFixer\Fixer\Casing\IntegerLiteralCaseFixer;
|
||||
use PhpCsFixer\Fixer\Casing\LowercaseStaticReferenceFixer;
|
||||
use PhpCsFixer\Fixer\Casing\MagicConstantCasingFixer;
|
||||
use PhpCsFixer\Fixer\Casing\MagicMethodCasingFixer;
|
||||
use PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer;
|
||||
use PhpCsFixer\Fixer\Casing\NativeFunctionTypeDeclarationCasingFixer;
|
||||
use PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer;
|
||||
use PhpCsFixer\Fixer\CastNotation\NoUnsetCastFixer;
|
||||
use PhpCsFixer\Fixer\Comment\HeaderCommentFixer;
|
||||
use PhpCsFixer\Fixer\Comment\NoTrailingWhitespaceInCommentFixer;
|
||||
use PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\ElseifFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\IncludeFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\NoUnneededCurlyBracesFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer;
|
||||
use PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer;
|
||||
use PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer;
|
||||
use PhpCsFixer\Fixer\FunctionNotation\NoSpacesAfterFunctionNameFixer;
|
||||
use PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer;
|
||||
use PhpCsFixer\Fixer\Import\NoLeadingImportSlashFixer;
|
||||
use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer;
|
||||
use PhpCsFixer\Fixer\ControlStructure\NoAlternativeSyntaxFixer;
|
||||
use PhpCsFixer\Fixer\FunctionNotation\LambdaNotUsedImportFixer;
|
||||
use PhpCsFixer\Fixer\Import\OrderedImportsFixer;
|
||||
use PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer;
|
||||
use PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer;
|
||||
use PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveUnsetsFixer;
|
||||
use PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer;
|
||||
use PhpCsFixer\Fixer\NamespaceNotation\BlankLineAfterNamespaceFixer;
|
||||
use PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer;
|
||||
use PhpCsFixer\Fixer\Operator\ConcatSpaceFixer;
|
||||
use PhpCsFixer\Fixer\Operator\NewWithBracesFixer;
|
||||
use PhpCsFixer\Fixer\LanguageConstruct\SingleSpaceAroundConstructFixer;
|
||||
use PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer;
|
||||
use PhpCsFixer\Fixer\NamespaceNotation\CleanNamespaceFixer;
|
||||
use PhpCsFixer\Fixer\Operator\NoSpaceAroundDoubleColonFixer;
|
||||
use PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer;
|
||||
use PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer;
|
||||
use PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer;
|
||||
use PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer;
|
||||
use PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer;
|
||||
use PhpCsFixer\Fixer\PhpTag\NoClosingTagFixer;
|
||||
use PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer;
|
||||
use PhpCsFixer\Fixer\PhpTag\LinebreakAfterOpeningTagFixer;
|
||||
use PhpCsFixer\Fixer\ReturnNotation\NoUselessReturnFixer;
|
||||
use PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer;
|
||||
use PhpCsFixer\Fixer\Semicolon\MultilineWhitespaceBeforeSemicolonsFixer;
|
||||
use PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer;
|
||||
use PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer;
|
||||
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
|
||||
use PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\CompactNullableTypehintFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\LineEndingFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer;
|
||||
use PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer;
|
||||
use SlevomatCodingStandard\Sniffs\ControlStructures\RequireShortTernaryOperatorSniff;
|
||||
use SlevomatCodingStandard\Sniffs\Functions\UnusedInheritedVariablePassedToClosureSniff;
|
||||
use SlevomatCodingStandard\Sniffs\Operators\RequireCombinedAssignmentOperatorSniff;
|
||||
use SlevomatCodingStandard\Sniffs\PHP\DisallowDirectMagicInvokeCallSniff;
|
||||
use SlevomatCodingStandard\Sniffs\PHP\UselessParenthesesSniff;
|
||||
use SlevomatCodingStandard\Sniffs\PHP\UselessSemicolonSniff;
|
||||
use SlevomatCodingStandard\Sniffs\Variables\UnusedVariableSniff;
|
||||
use SlevomatCodingStandard\Sniffs\Variables\UselessVariableSniff;
|
||||
use PhpCsFixer\Fixer\Whitespace\TypesSpacesFixer;
|
||||
use Symplify\CodingStandard\Fixer\Commenting\ParamReturnAndVarTagMalformsFixer;
|
||||
use Symplify\EasyCodingStandard\Config\ECSConfig;
|
||||
use Symplify\EasyCodingStandard\ValueObject\Option;
|
||||
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
|
||||
|
||||
return static function (ECSConfig $containerConfigurator): void {
|
||||
return static function (ECSConfig $ecsConfig): void {
|
||||
$ecsConfig->parallel();
|
||||
$headerFile = __DIR__ . '/.header';
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
$parameters->set(Option::SETS, [
|
||||
SetList::COMMON,
|
||||
]);
|
||||
$services = $containerConfigurator->services();
|
||||
$ecsConfig->sets([SetList::PSR_12, SetList::COMMON]);
|
||||
if (file_exists($headerFile)) {
|
||||
$services->set(HeaderCommentFixer::class)
|
||||
->call('configure', [[
|
||||
'header' => file_get_contents($headerFile),
|
||||
'location' => 'after_open',
|
||||
]]);
|
||||
$ecsConfig->ruleWithConfiguration(HeaderCommentFixer::class, [
|
||||
'header' => file_get_contents($headerFile),
|
||||
'location' => 'after_open',
|
||||
]);
|
||||
}
|
||||
$services->set(EncodingFixer::class);
|
||||
$services->set(FullOpeningTagFixer::class);
|
||||
$services->set(BlankLineAfterNamespaceFixer::class);
|
||||
$services->set(BracesFixer::class);
|
||||
$services->set(ClassDefinitionFixer::class);
|
||||
$services->set(ConstantCaseFixer::class);
|
||||
$services->set(ElseifFixer::class);
|
||||
$services->set(FunctionDeclarationFixer::class);
|
||||
$services->set(IndentationTypeFixer::class);
|
||||
$services->set(LineEndingFixer::class);
|
||||
$services->set(LowercaseKeywordsFixer::class);
|
||||
$services->set(MethodArgumentSpaceFixer::class)
|
||||
->call('configure', [[
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
]]);
|
||||
$services->set(NoBreakCommentFixer::class);
|
||||
$services->set(NoClosingTagFixer::class);
|
||||
$services->set(NoSpacesAfterFunctionNameFixer::class);
|
||||
$services->set(NoSpacesInsideParenthesisFixer::class);
|
||||
$services->set(NoTrailingWhitespaceFixer::class);
|
||||
$services->set(NoTrailingWhitespaceInCommentFixer::class);
|
||||
$services->set(SingleBlankLineAtEofFixer::class);
|
||||
$services->set(SingleClassElementPerStatementFixer::class)
|
||||
->call('configure', [[
|
||||
'elements' => ['property'],
|
||||
]]);
|
||||
$services->set(SingleImportPerStatementFixer::class);
|
||||
$services->set(SingleLineAfterImportsFixer::class);
|
||||
// $services->set(SwitchCaseSemicolonToColonFixer::class); broken for php 8.0
|
||||
$services->set(SwitchCaseSpaceFixer::class);
|
||||
$services->set(VisibilityRequiredFixer::class);
|
||||
$services->set(LowercaseCastFixer::class);
|
||||
$services->set(ShortScalarCastFixer::class);
|
||||
$services->set(BlankLineAfterOpeningTagFixer::class);
|
||||
$services->set(NoLeadingImportSlashFixer::class);
|
||||
$services->set(OrderedImportsFixer::class)
|
||||
->call('configure', [[
|
||||
'importsOrder' => ['class', 'function', 'const'],
|
||||
]]);
|
||||
$services->set(DeclareEqualNormalizeFixer::class)
|
||||
->call('configure', [[
|
||||
'space' => 'none',
|
||||
]]);
|
||||
$services->set(NewWithBracesFixer::class);
|
||||
$services->set(BracesFixer::class)
|
||||
->call('configure', [[
|
||||
'allow_single_line_closure' => false,
|
||||
'position_after_functions_and_oop_constructs' => 'next',
|
||||
'position_after_control_structures' => 'same',
|
||||
'position_after_anonymous_constructs' => 'same',
|
||||
]]);
|
||||
$services->set(NoBlankLinesAfterClassOpeningFixer::class);
|
||||
$services->set(VisibilityRequiredFixer::class)
|
||||
->call('configure', [[
|
||||
'elements' => ['const', 'method', 'property'],
|
||||
]]);
|
||||
$services->set(BinaryOperatorSpacesFixer::class);
|
||||
$services->set(TernaryOperatorSpacesFixer::class);
|
||||
$services->set(UnaryOperatorSpacesFixer::class);
|
||||
$services->set(ReturnTypeDeclarationFixer::class);
|
||||
$services->set(NoTrailingWhitespaceFixer::class);
|
||||
$services->set(ConcatSpaceFixer::class)
|
||||
->call('configure', [[
|
||||
'spacing' => 'one',
|
||||
]]);
|
||||
$services->set(NoSinglelineWhitespaceBeforeSemicolonsFixer::class);
|
||||
$services->set(NoWhitespaceBeforeCommaInArrayFixer::class);
|
||||
$services->set(WhitespaceAfterCommaInArrayFixer::class);
|
||||
$services->set(DeclareStrictTypesFixer::class);
|
||||
$services->set(CompactNullableTypehintFixer::class);
|
||||
$services->set(BlankLineBeforeStatementFixer::class);
|
||||
$services->set(CombineConsecutiveUnsetsFixer::class);
|
||||
$services->set(ClassAttributesSeparationFixer::class);
|
||||
$services->set(MultilineWhitespaceBeforeSemicolonsFixer::class);
|
||||
$services->set(SingleLineCommentStyleFixer::class);
|
||||
$services->set(IncludeFixer::class);
|
||||
$services->set(ObjectOperatorWithoutWhitespaceFixer::class);
|
||||
$services->set(DisallowDirectMagicInvokeCallSniff::class);
|
||||
$services->set(ParamReturnAndVarTagMalformsFixer::class);
|
||||
$services->set(UnusedVariableSniff::class);
|
||||
$services->set(UselessVariableSniff::class);
|
||||
$services->set(UnusedInheritedVariablePassedToClosureSniff::class);
|
||||
$services->set(UselessSemicolonSniff::class);
|
||||
// $services->set(UselessParenthesesSniff::class); // broken for php 8.0
|
||||
$services->set(ArraySyntaxFixer::class)
|
||||
->call('configure', [[
|
||||
'syntax' => 'short',
|
||||
]]);
|
||||
$services->set(NoUnusedImportsFixer::class);
|
||||
$services->set(OrderedImportsFixer::class);
|
||||
$services->set(NoEmptyStatementFixer::class);
|
||||
$services->set(ProtectedToPrivateFixer::class);
|
||||
$services->set(NoUnneededControlParenthesesFixer::class);
|
||||
$services->set(NoUnneededCurlyBracesFixer::class);
|
||||
$services->set(ReturnAssignmentFixer::class);
|
||||
$services->set(RequireShortTernaryOperatorSniff::class);
|
||||
$services->set(RequireCombinedAssignmentOperatorSniff::class);
|
||||
$services->set(NoExtraBlankLinesFixer::class)
|
||||
->call('configure', [[
|
||||
'tokens' => [
|
||||
'curly_brace_block',
|
||||
'extra',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'throw',
|
||||
'use',
|
||||
]
|
||||
]]);
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
$parameters->set(Option::SKIP, [
|
||||
$ecsConfig->rule(TypesSpacesFixer::class);
|
||||
$ecsConfig->rule(NoUselessReturnFixer::class);
|
||||
$ecsConfig->rule(LinebreakAfterOpeningTagFixer::class);
|
||||
$ecsConfig->rule(StandardizeNotEqualsFixer::class);
|
||||
$ecsConfig->rule(NoSpaceAroundDoubleColonFixer::class);
|
||||
$ecsConfig->rule(CleanNamespaceFixer::class);
|
||||
$ecsConfig->rule(ListSyntaxFixer::class);
|
||||
$ecsConfig->rule(SingleSpaceAroundConstructFixer::class);
|
||||
$ecsConfig->rule(LambdaNotUsedImportFixer::class);
|
||||
$ecsConfig->rule(NoAlternativeSyntaxFixer::class);
|
||||
$ecsConfig->rule(NoUnsetCastFixer::class);
|
||||
$ecsConfig->rule(NoShortBoolCastFixer::class);
|
||||
$ecsConfig->rule(NativeFunctionTypeDeclarationCasingFixer::class);
|
||||
$ecsConfig->rule(NativeFunctionCasingFixer::class);
|
||||
$ecsConfig->rule(MagicMethodCasingFixer::class);
|
||||
$ecsConfig->rule(MagicConstantCasingFixer::class);
|
||||
$ecsConfig->rule(LowercaseStaticReferenceFixer::class);
|
||||
$ecsConfig->rule(IntegerLiteralCaseFixer::class);
|
||||
$ecsConfig->rule(NormalizeIndexBraceFixer::class);
|
||||
$ecsConfig->rule(NoMultilineWhitespaceAroundDoubleArrowFixer::class);
|
||||
$ecsConfig->rule(BlankLineBeforeStatementFixer::class);
|
||||
$ecsConfig->rule(CombineConsecutiveUnsetsFixer::class);
|
||||
$ecsConfig->rule(CompactNullableTypehintFixer::class);
|
||||
$ecsConfig->rule(DeclareStrictTypesFixer::class);
|
||||
$ecsConfig->rule(IncludeFixer::class);
|
||||
$ecsConfig->rule(MultilineWhitespaceBeforeSemicolonsFixer::class);
|
||||
$ecsConfig->rule(NoAliasFunctionsFixer::class);
|
||||
$ecsConfig->rule(NoAliasLanguageConstructCallFixer::class);
|
||||
$ecsConfig->rule(NoEmptyStatementFixer::class);
|
||||
$ecsConfig->rule(NoMixedEchoPrintFixer::class);
|
||||
$ecsConfig->rule(ObjectOperatorWithoutWhitespaceFixer::class);
|
||||
$ecsConfig->rule(ParamReturnAndVarTagMalformsFixer::class);
|
||||
$ecsConfig->rule(ReturnAssignmentFixer::class);
|
||||
$ecsConfig->ruleWithConfiguration(SingleLineCommentStyleFixer::class, [
|
||||
'comment_types' => ['hash'],
|
||||
]);
|
||||
$ecsConfig->rule(SingleQuoteFixer::class);
|
||||
$ecsConfig->ruleWithConfiguration(OrderedImportsFixer::class, [
|
||||
'imports_order' => ['class', 'function', 'const'],
|
||||
]);
|
||||
$ecsConfig->ruleWithConfiguration(ArraySyntaxFixer::class, [
|
||||
'syntax' => 'short',
|
||||
]);
|
||||
$ecsConfig->ruleWithConfiguration(NoExtraBlankLinesFixer::class, [
|
||||
'tokens' => [
|
||||
'curly_brace_block',
|
||||
'extra',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'throw',
|
||||
'use',
|
||||
],
|
||||
]);
|
||||
$ecsConfig->skip([
|
||||
SingleImportPerStatementFixer::class => null,
|
||||
]);
|
||||
};
|
||||
|
||||
16
.ecs/ecs.php
16
.ecs/ecs.php
@@ -10,13 +10,15 @@
|
||||
*/
|
||||
|
||||
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
|
||||
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
|
||||
use Symplify\EasyCodingStandard\Config\ECSConfig;
|
||||
use Symplify\EasyCodingStandard\ValueObject\Option;
|
||||
|
||||
return static function (ECSConfig $containerConfigurator): void {
|
||||
$containerConfigurator->import(__DIR__ . '/ecs-chevere.php');
|
||||
$services = $containerConfigurator->services();
|
||||
$services->remove(DeclareStrictTypesFixer::class);
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
$parameters->set(Option::SKIP, []);
|
||||
return static function (ECSConfig $ecsConfig): void {
|
||||
$ecsConfig->import(__DIR__ . '/ecs-chevere.php');
|
||||
$ecsConfig->skip([
|
||||
DeclareStrictTypesFixer::class,
|
||||
StrictComparisonFixer::class,
|
||||
getcwd() . '/vendor/*',
|
||||
getcwd() . '/content/legacy/themes/Peafowl/',
|
||||
]);
|
||||
};
|
||||
|
||||
15
.github/workflows/docker.yml
vendored
15
.github/workflows/docker.yml
vendored
@@ -14,7 +14,10 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
php: ["8.2"]
|
||||
php: ["8.1"]
|
||||
env:
|
||||
tools: composer
|
||||
ini-values: default_charset='UTF-8'
|
||||
name: Build on PHP ${{ matrix.php }} ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -27,6 +30,14 @@ jobs:
|
||||
raw=$(git branch -r --contains ${{ github.ref }})
|
||||
echo "branch=${raw##*/}" >> $GITHUB_OUTPUT
|
||||
- run: echo ${{ steps.get-branch.outputs.branch }}
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
ini-values: ${{ env.ini-values }}
|
||||
tools: ${{ env.tools }}
|
||||
env:
|
||||
fail-fast: true
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
@@ -42,7 +53,7 @@ jobs:
|
||||
type=semver,pattern={{major}}
|
||||
labels: |
|
||||
org.opencontainers.image.title=Chevereto V4
|
||||
org.opencontainers.image.description=Ultimate image sharing software
|
||||
org.opencontainers.image.description=Ultimate image and video sharing software
|
||||
org.opencontainers.image.vendor=Chevereto
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
Chevereto 4.1.4 (2024-05-24)
|
||||
|
||||
- ✅ Added checking for CHEVERETO_HOSTNAME_PATH setting
|
||||
- 🌎 Updated Chinese Traditional translation
|
||||
- 🌎 Updated French translation
|
||||
- 🐋 Improved upgrading instructions when using Docker
|
||||
- 🐞 Fixed bug affecting video uploads when using max image size
|
||||
- 🐞 Removed album hashing when upgrading from V3
|
||||
- 🐞 Removed login providers encryption when upgrading from V3
|
||||
115
.package/4.2.0.txt
Normal file
115
.package/4.2.0.txt
Normal file
@@ -0,0 +1,115 @@
|
||||
Chevereto 4.2.0 (2024-10-24)
|
||||
|
||||
- 🏷️ Added user-defined file tags
|
||||
- 🏷️ Added album top tags filtering system
|
||||
- 🏷️ Added automatic camera model tagging
|
||||
- 🏷️ Added bulk importer support for metadata tags
|
||||
- 🏷️ Added combined tag filtering system
|
||||
- 🏷️ Added tag autocomplete search
|
||||
- 🏷️ Added tag description
|
||||
- 🏷️ Added tags listings
|
||||
- 🏷️ Added top tags explorer list
|
||||
- 🕷️ Added support for Arachnid Shield API v1.0
|
||||
- 🪣 Added "Use path style endpoint" option for External storage
|
||||
- 🪣 Added removal for External storage
|
||||
- 🪣 Improved credentials handling at External storage
|
||||
- 🪣 Improved External storage error display
|
||||
- 📈 Added CRON runtime stat
|
||||
- 📈 Added Tags stat
|
||||
- 🖼️ Added image only Explorer listing
|
||||
- 🖼️ Added support for AVIF image format
|
||||
- 🐘 Added automatic ini_set for settings mismatch
|
||||
- 🐘 Requires PHP 8.1
|
||||
- 🌚 Added System color palette prefers-color-scheme
|
||||
- 📷 Added Exif data dedicated tab
|
||||
- 🐬 Added system variables
|
||||
- 📱 Changed mobile font root size to 16px
|
||||
- ✅ Added "Go up" button for sub-albums
|
||||
- ✅ Added album creation on behalf of users
|
||||
- ✅ Added API documentation page
|
||||
- ✅ Added asset storage deletions with queues
|
||||
- ✅ Added breadcrumb navigation for sub-albums
|
||||
- ✅ Added canonical URL for /explore
|
||||
- ✅ Added category editing tools to category view
|
||||
- ✅ Added configurable cache ttl
|
||||
- ✅ Added configurable video routing
|
||||
- ✅ Added custom SMTP port setting
|
||||
- ✅ Added database settings for asset storage
|
||||
- ✅ Added error log configuration for cron and CLI
|
||||
- ✅ Added HTML encoding for growl alerts
|
||||
- ✅ Added keywords meta tag
|
||||
- ✅ Added logout action for account routes
|
||||
- ✅ Added meta robots noindex, follow for search results
|
||||
- ✅ Added more ENV configurable limits
|
||||
- ✅ Added more ENV system configurable toggles
|
||||
- ✅ Added more error log information
|
||||
- ✅ Added new content section to explorer menu
|
||||
- ✅ Added new listing /explore/albums
|
||||
- ✅ Added new listing /explore/users
|
||||
- ✅ Added option to toggle guest album creation
|
||||
- ✅ Added root user support for CLI
|
||||
- ✅ Added single JavaScript dependency
|
||||
- ✅ Added SMTP without credentials
|
||||
- ✅ Added support for bfcache
|
||||
- ✅ Added support for case-sensitive url_key for categories
|
||||
- ✅ Added support for custom upload expiration via API
|
||||
- ✅ Added support for custom upload plugins
|
||||
- ✅ Added user's liked albums listing
|
||||
- ✅ Added web manifest
|
||||
- ✅ Added PUP.js support for XenForo 2.3
|
||||
- ✅ Improved API request handling
|
||||
- ✅ Improved confirmation table indexes
|
||||
- ✅ Improved CRON error handling
|
||||
- ✅ Improved form validation handling
|
||||
- ✅ Improved handling for boolean settings
|
||||
- ✅ Improved handling for string settings (HTML safe)
|
||||
- ✅ Improved hreflang implementation
|
||||
- ✅ Improved post upload message for guest
|
||||
- ✅ Improved session handling
|
||||
- ✅ Improved share modals which now use short URL
|
||||
- ✅ Migrated xrDebug configuration from database to ENV
|
||||
- ✅ Removed History.js and unload events
|
||||
- ✅ Removed local uploads re-check
|
||||
- ✅ Removed switch to local upload failover
|
||||
- 💅 Added apple-mobile-web-app-title property
|
||||
- 💅 Added automatic menu sizing display
|
||||
- 💅 Added color-scheme dark for applicable palettes
|
||||
- 💅 Added curl command example under /dashboard/settings/guest-api
|
||||
- 💅 Added curl command example under /settings/api
|
||||
- 💅 Added dashboard stat button links
|
||||
- 💅 Added download links for files
|
||||
- 💅 Added ESC key binding to clear and close search boxes
|
||||
- 💅 Added Explore button to mobile top bar
|
||||
- 💅 Disabled key feedback message
|
||||
- 💅 Improved "hamburger" menu
|
||||
- 💅 Improved album cover button icon
|
||||
- 💅 Improved listing bulk selection tool
|
||||
- 💅 Improved select elements display for Safari
|
||||
- 💅 Improved user profile display
|
||||
- 💅 Introducing all-new dark palette
|
||||
- 💅 Mobile menus now display two columns
|
||||
- 💅 Removed default avatar from guest owned content
|
||||
- 💅 Removed redundant success alerts
|
||||
- 💅 Removed top bar hide/show on scrolling
|
||||
- 💅 Unified user action buttons
|
||||
- 💅 Updated Font Awesome dependency
|
||||
- 🐞 Fixed bug in account change email confirm
|
||||
- 🐞 Fixed bug in album editing allowing empty string
|
||||
- 🐞 Fixed bug in album editing parent id
|
||||
- 🐞 Fixed bug in failing asset upload when running in sub-dir
|
||||
- 🐞 Fixed bug in front controller
|
||||
- 🐞 Fixed bug in listing selection tools
|
||||
- 🐞 Fixed bug in missing oEmbed tags when using custom image routing
|
||||
- 🐞 Fixed bug in oEmbed XML output
|
||||
- 🐞 Fixed bug in password reset
|
||||
- 🐞 Fixed bug in share modal
|
||||
- 🐞 Fixed bug in stop words filter system
|
||||
- 🐞 Fixed bug in sub-albums listing editor
|
||||
- 🐞 Fixed bug in URL-based lang change for logged users
|
||||
- 🐞 Fixed bug in user avatar upload
|
||||
- 🐞 Fixed bug in video upload when using watermarks
|
||||
- 🐞 Fixed bug in wrong redirects when running in sub-dir
|
||||
- 🐞 Fixed bug with not working album share button
|
||||
- 🐞 Fixed bug with wrong URL for album sharing
|
||||
- 🐞 Fixed ErrorException on contact page
|
||||
- 🐞 Fixed ErrorException on route json
|
||||
190
README.md
190
README.md
@@ -16,7 +16,7 @@
|
||||
|
||||
> 🔔 [Subscribe](https://chevereto.com/go/newsletter) to don't miss any update regarding Chevereto.
|
||||
|
||||
Chevereto is a powerful, self-hosted media-sharing platform that emphasizes flexibility and control. It allows you to create a media-sharing website on your own server, giving you full autonomy over your hosting environment and policies. With Chevereto, you can say goodbye to platform restrictions and closures, ensuring your site operates entirely on your terms.
|
||||
Chevereto is a robust, self-hosted media-sharing platform that prioritizes flexibility and control. It enables you to build and manage a media-sharing website on your own server, granting you complete autonomy over your hosting environment and policies. With Chevereto, you eliminate the risk of platform restrictions and shutdowns, ensuring your site operates entirely on your terms.
|
||||
|
||||
Our [commercial edition](https://chevereto.com/pricing) is designed for running very large media-sharing services, offering scalability and tools to manage multiple users, high traffic, and extensive media collections.
|
||||
|
||||
@@ -37,7 +37,9 @@ Install Chevereto following our guides for:
|
||||
* [cPanel](https://v4-docs.chevereto.com/guides/cpanel/)
|
||||
* [Plesk](https://v4-docs.chevereto.com/guides/plesk/)
|
||||
|
||||
Chevereto is also available at [DigitalOcean Marketplace](https://chevereto.com/go/digitalocean), [Vultr Marketplace](https://chevereto.com/go/vultr), [Installatron](https://installatron.com/chevereto) and [Softaculous](https://www.softaculous.com/apps/galleries/Chevereto). Review our [Installation docs](https://v4-docs.chevereto.com/application/installing/installation.html) for all alternatives.
|
||||
Chevereto is also available at [DigitalOcean Marketplace](https://chevereto.com/go/digitalocean), [Vultr Marketplace](https://chevereto.com/go/vultr), [Installatron](https://installatron.com/chevereto), [Softaculous](https://www.softaculous.com/apps/galleries/Chevereto) and [SwiftWave](https://swiftwave.org/docs/dashboard/swiftwave_app_store/).
|
||||
|
||||
Review our [Installation docs](https://v4-docs.chevereto.com/application/installing/installation.html) for all alternatives.
|
||||
|
||||
## Updating
|
||||
|
||||
@@ -74,32 +76,91 @@ Chevereto [Documentation](https://v4-docs.chevereto.com) covers the system requi
|
||||
|
||||
## Features
|
||||
|
||||
This is a short, not exhaustive, list of features available on Chevereto editions. Feel free to request a free demo of the pro edition at [chevereto.com](https://chevereto.com) to see all the features in action.
|
||||
This is a short, not exhaustive, list of features available on Chevereto editions. Feel free to request a demo of the pro edition at [chevereto.com](https://chevereto.com) (free of any charge, no payment required) to see all the features in action.
|
||||
|
||||
### Uploading features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| ---------------------------------------- | :---: | :---: | :---: |
|
||||
| Image & Video uploads | ✅ | ✅ | ✅ |
|
||||
| JPEG PNG BMP GIF WEBP MOV MP4 WEBM | ✅ | ✅ | ✅ |
|
||||
| ShareX support | ✅ | ✅ | ✅ |
|
||||
| 360° images | ✅ | ✅ | ✅ |
|
||||
| Strip image EXIF data | ✅ | ✅ | ✅ |
|
||||
| Clipboard upload | ✅ | ✅ | ✅ |
|
||||
| Drag-and-drop upload | ✅ | ✅ | ✅ |
|
||||
| File delete link | ✅ | ✅ | ✅ |
|
||||
| Time-based expirable uploads | ✅ | ✅ | ✅ |
|
||||
| Thumbs & medium sized images | ✅ | ✅ | ✅ |
|
||||
| Video frame image | ✅ | ✅ | ✅ |
|
||||
| Duplicate media detection | ✅ | ✅ | ✅ |
|
||||
| Auto file naming options | ✅ | ✅ | ✅ |
|
||||
| Storage modes (date, direct) | ✅ | ✅ | ✅ |
|
||||
| Upload user interface (container, route) | ✅ | ✅ | ✅ |
|
||||
| Upload plugin (PUP.js) | – | ✅ | ✅ |
|
||||
| Watermark image uploads | – | – | ✅ |
|
||||
| Upload moderation | – | – | ✅ |
|
||||
| External storage servers | – | – | ✅ |
|
||||
| Bulk content importer | – | – | ✅ |
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------------------------- | :---: | :---: | :------------------: |
|
||||
| Image & Video uploads | ✅ | ✅ | ✅ |
|
||||
| AVIF JPEG PNG BMP GIF WEBP MOV MP4 WEBM | ✅ | ✅ | ✅ |
|
||||
| API uploading (ShareX, etc) | ✅ | ✅ | ✅ |
|
||||
| Equirectangular 360° images | ✅ | ✅ | ✅ |
|
||||
| EXIF data (read, strip) | ✅ | ✅ | ✅ |
|
||||
| Clipboard upload | ✅ | ✅ | ✅ |
|
||||
| Drag-and-drop upload (drop zone) | ✅ | ✅ | ✅ |
|
||||
| File delete link | ✅ | ✅ | ✅ |
|
||||
| Time-based expirable uploads | ✅ | ✅ | ✅ |
|
||||
| Generate thumbs & medium sized images | ✅ | ✅ | ✅ |
|
||||
| Generate video frame image | ✅ | ✅ | ✅ |
|
||||
| Duplicate media detection | ✅ | ✅ | ✅ |
|
||||
| Auto file-naming options | ✅ | ✅ | ✅ |
|
||||
| Storage modes (date, direct) | ✅ | ✅ | ✅ |
|
||||
| Upload user interface (container, page) | ✅ | ✅ | ✅ |
|
||||
| Upload plugin (PUP.js, postMessage) | ✅ | ✅ | ✅ |
|
||||
| Upload moderation | – | ✅ | ✅ |
|
||||
| Asset storage API | Local | Local | Any |
|
||||
| External storage servers API | Local | Local | All (S3, SFTP, etc.) |
|
||||
| Watermark image uploads | – | – | ✅ |
|
||||
| Bulk content importer | – | – | ✅ |
|
||||
|
||||
### External storage APIs
|
||||
|
||||
| Storage API | Free | Lite | Pro |
|
||||
| --------------------- | :---: | :---: | :---: |
|
||||
| Amazon S3 | – | – | ✅ |
|
||||
| S3 compatible | – | – | ✅ |
|
||||
| Google Cloud Storage | – | – | ✅ |
|
||||
| Microsoft Azure | – | – | ✅ |
|
||||
| Alibaba Cloud OSS | – | – | ✅ |
|
||||
| SFTP | – | – | ✅ |
|
||||
| FTP | – | – | ✅ |
|
||||
| OpenStack Swift | – | – | ✅ |
|
||||
| Backblaze B2 (legacy) | – | – | ✅ |
|
||||
|
||||
### Content features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| ----------------------------------------------------------- | :---: | :---: | :---: |
|
||||
| Listing viewer (light box) | ✅ | ✅ | ✅ |
|
||||
| Dedicated Media, Album, Tags & Users listings | ✅ | ✅ | ✅ |
|
||||
| Configure items per page | ✅ | ✅ | ✅ |
|
||||
| Listing type (paginated/endless) | ✅ | ✅ | ✅ |
|
||||
| Image listing size (fixed, fluid) | ✅ | ✅ | ✅ |
|
||||
| Configure album listing requirement | ✅ | ✅ | ✅ |
|
||||
| Configure listing columns per device (mobile, tablet, etc.) | ✅ | ✅ | ✅ |
|
||||
|
||||
### Organization features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| ---------------------------- | :---: | :---: | :---: |
|
||||
| User defined Tags | ✅ | ✅ | ✅ |
|
||||
| Albums & Sub-albums (nested) | ✅ | ✅ | ✅ |
|
||||
| Categories | ✅ | ✅ | ✅ |
|
||||
| Search | ✅ | ✅ | ✅ |
|
||||
| Explore & Discovery | ✅ | ✅ | ✅ |
|
||||
|
||||
### Tags features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| ------------------------------ | :---: | :---: | :---: |
|
||||
| On-the-fly tag creation | ✅ | ✅ | ✅ |
|
||||
| Tag description | ✅ | ✅ | ✅ |
|
||||
| Tag listings | ✅ | ✅ | ✅ |
|
||||
| Tag filtering (users, albums) | ✅ | ✅ | ✅ |
|
||||
| Tag autocomplete | ✅ | ✅ | ✅ |
|
||||
| Top tags | ✅ | ✅ | ✅ |
|
||||
| Exif camera model auto-tagging | ✅ | ✅ | ✅ |
|
||||
|
||||
### Album features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------------- | :---: | :---: | :---: |
|
||||
| Nested albums (breadcrumbs) | ✅ | ✅ | ✅ |
|
||||
| Album cover image | ✅ | ✅ | ✅ |
|
||||
| Album privacy | ✅ | ✅ | ✅ |
|
||||
| Album password | ✅ | ✅ | ✅ |
|
||||
| Album description | ✅ | ✅ | ✅ |
|
||||
|
||||
### Sharing features
|
||||
|
||||
@@ -108,20 +169,21 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| Direct link sharing | ✅ | ✅ | ✅ |
|
||||
| Sharing button | ✅ | ✅ | ✅ |
|
||||
| Media oEmbed | ✅ | ✅ | ✅ |
|
||||
| HTML, Markdown & BBCode | ✅ | ✅ | ✅ |
|
||||
| HTML, Markdown & BBCodes | ✅ | ✅ | ✅ |
|
||||
| Embed codes on upload complete | ✅ | ✅ | ✅ |
|
||||
| Embed codes on selected media | ✅ | ✅ | ✅ |
|
||||
| Embed codes media page | ✅ | ✅ | ✅ |
|
||||
|
||||
### User features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------------- | :---: | :---: | :---: |
|
||||
| User profiles | ✅ | ✅ | ✅ |
|
||||
| Private user profiles | ✅ | ✅ | ✅ |
|
||||
| User-based API | ✅ | ✅ | ✅ |
|
||||
| Multiple users & management | – | ✅ | ✅ |
|
||||
| Guest API | – | ✅ | ✅ |
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------- | :---: | :---: | :---: |
|
||||
| User profiles | ✅ | ✅ | ✅ |
|
||||
| Private user profiles | ✅ | ✅ | ✅ |
|
||||
| User-based API | ✅ | ✅ | ✅ |
|
||||
| Multiple users | – | ✅ | ✅ |
|
||||
| User management | – | ✅ | ✅ |
|
||||
| Guest API | – | ✅ | ✅ |
|
||||
|
||||
### Social features
|
||||
|
||||
@@ -129,28 +191,11 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| ---------------------------- | :---: | :---: | :---: |
|
||||
| Call-to-action album buttons | ✅ | ✅ | ✅ |
|
||||
| Random button | ✅ | ✅ | ✅ |
|
||||
| Notifications | – | ✅ | ✅ |
|
||||
| List users | – | ✅ | ✅ |
|
||||
| Notifications | ✅ | ✅ | ✅ |
|
||||
| List users | ✅ | ✅ | ✅ |
|
||||
| Followers | – | – | ✅ |
|
||||
| Likes | – | – | ✅ |
|
||||
|
||||
### Organization features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------------------- | :---: | :---: | :---: |
|
||||
| Albums & Sub-albums | ✅ | ✅ | ✅ |
|
||||
| Categories | ✅ | ✅ | ✅ |
|
||||
| Search | ✅ | ✅ | ✅ |
|
||||
| Media & Album listings | ✅ | ✅ | ✅ |
|
||||
| Configurable list items per page | ✅ | ✅ | ✅ |
|
||||
| Classic + Endless scroll listings | ✅ | ✅ | ✅ |
|
||||
| Listing viewer | ✅ | ✅ | ✅ |
|
||||
| Image listing size (fixed, fluid) | ✅ | ✅ | ✅ |
|
||||
| Album listing requirement | ✅ | ✅ | ✅ |
|
||||
| Listing columns per device | ✅ | ✅ | ✅ |
|
||||
| Explore & Discovery | – | ✅ | ✅ |
|
||||
| Advanced search | – | ✅ | ✅ |
|
||||
|
||||
### Security features
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
@@ -165,6 +210,7 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
|
||||
| Feature | Free | Lite | Pro |
|
||||
| --------------------------------------------------------------------------------------------- | :---: | :---: | :---: |
|
||||
| Album creation on behalf of users | ✅ | ✅ | ✅ |
|
||||
| Dashboard (admin UI) | ✅ | ✅ | ✅ |
|
||||
| System stats & usage | ✅ | ✅ | ✅ |
|
||||
| Website name | ✅ | ✅ | ✅ |
|
||||
@@ -191,6 +237,10 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| Custom JS & CSS | ✅ | ✅ | ✅ |
|
||||
| Universal CDN support | ✅ | ✅ | ✅ |
|
||||
| [Default language](https://v4-admin.chevereto.com/settings/languages.html#default-language) | ✅ | ✅ | ✅ |
|
||||
| Logo & branding | ✅ | ✅ | ✅ |
|
||||
| Logo type (vector, image, text) | ✅ | ✅ | ✅ |
|
||||
| Logo height | ✅ | ✅ | ✅ |
|
||||
| Logo favicon image | ✅ | ✅ | ✅ |
|
||||
| Homepage style | – | ✅ | ✅ |
|
||||
| Homepage cover images | – | ✅ | ✅ |
|
||||
| Homepage title & paragraph | – | ✅ | ✅ |
|
||||
@@ -201,12 +251,8 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| User avatar max file size | – | ✅ | ✅ |
|
||||
| User background max file size | – | ✅ | ✅ |
|
||||
| Guest API key | – | ✅ | ✅ |
|
||||
| Hide "Powered by Chevereto" footer | – | – | ✅ |
|
||||
| [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 | – | – | ✅ |
|
||||
@@ -215,8 +261,8 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| Akismet spam protection | – | – | ✅ |
|
||||
| StopForumSpam spam protection | – | – | ✅ |
|
||||
| CAPTCHA (reCAPTCHA, hCaptcha) | – | – | ✅ |
|
||||
| CAPTCHA threshold | – | – | ✅ |
|
||||
| Project Arachnid | – | – | ✅ |
|
||||
| Configurable CAPTCHA threshold | – | – | ✅ |
|
||||
| Shield by Project Arachnid | – | – | ✅ |
|
||||
| ModerateContent (auto approve, block, flag) | – | – | ✅ |
|
||||
| OAuth2 login providers (Amazon, Google, Discord, etc) | – | – | ✅ |
|
||||
| Banners | – | – | ✅ |
|
||||
@@ -279,8 +325,7 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| One-click upgrade (web & CLI) | ✅ | ✅ | ✅ |
|
||||
| Maintenance mode | ✅ | ✅ | ✅ |
|
||||
| Email SMTP + phpmail() | ✅ | ✅ | ✅ |
|
||||
| Decode ID | ✅ | ✅ | ✅ |
|
||||
| Encode ID | ✅ | ✅ | ✅ |
|
||||
| Cipher ID | ✅ | ✅ | ✅ |
|
||||
| Test-email | ✅ | ✅ | ✅ |
|
||||
| Export user | ✅ | ✅ | ✅ |
|
||||
| Regenerate external storage stats | ✅ | ✅ | ✅ |
|
||||
@@ -290,11 +335,14 @@ This is a short, not exhaustive, list of features available on Chevereto edition
|
||||
| Built-in debugger ([xrDebug](https://xrdebug.com)) | ✅ | ✅ | ✅ |
|
||||
| Built-in REPL (PsySH) | ✅ | ✅ | ✅ |
|
||||
| Supports Tinkerwel REPL | ✅ | ✅ | ✅ |
|
||||
| Queue handling | – | – | ✅ |
|
||||
| Queue handling | ✅ | ✅ | ✅ |
|
||||
| Configurable cache TTL | ✅ | ✅ | ✅ |
|
||||
| Hreflang | ✅ | ✅ | ✅ |
|
||||
| Session storage (files, redis) | ✅ | ✅ | ✅ |
|
||||
|
||||
## Contributing
|
||||
|
||||
Chevereto is an open-source project, and we welcome contributions of all kinds. Any help is appreciated! The main goal is to improve the software and make it better for everyone. Any contribution made on this repository will abide by the AGPLv3 license, which means that your contributions will be open-source and available to everyone.
|
||||
Chevereto is an open-source project, and while contributions are welcomed, they are entirely voluntary. We appreciate any assistance aimed at enhancing the software and making it better for the community. Please note that any contributions to this repository will fall under the AGPLv3 license, ensuring that your work remains open-source and accessible to all.
|
||||
|
||||
## License
|
||||
|
||||
@@ -310,10 +358,20 @@ You should have received a copy of the GNU Affero General Public License along w
|
||||
|
||||
### Commercial license
|
||||
|
||||
The commercial license is designed to for you to use Chevereto in commercial products and applications, without the provisions of the AGPLv3. With the commercial license, your code is kept proprietary, to yourself. See the Chevereto Commercial License at [Chevereto License](https://chevereto.com/license)
|
||||
The commercial license allows you to use Chevereto in commercial products and applications without the obligations imposed by the AGPLv3. The commercial license ensures that your code remains proprietary and exclusive to you. For more details, please refer to the Chevereto Commercial License at [Chevereto License](https://chevereto.com/license).
|
||||
|
||||
### Compare licenses
|
||||
|
||||
Chevereto free edition is licensed under AGPLv3, which means that you can use it for free as long as you comply with the AGPLv3 terms. If you modify the code and distribute it, you must provide the source code to the users.
|
||||
The Chevereto Free edition is licensed under AGPLv3, allowing free use as long as you comply with its terms. If you modify and distribute the software, you are required to provide the source code to your users.
|
||||
|
||||
**Chevereto Lite** and **Chevereto Pro** editions are released under the **Chevereto License**, which is proprietary and it can be used for commercial purposes.
|
||||
Both **Chevereto Lite** and **Chevereto Pro** are distributed under the proprietary **Chevereto License**, which permits use for commercial purposes.
|
||||
|
||||
Here’s the revised version with the additional note:
|
||||
|
||||
---
|
||||
|
||||
The Chevereto Free edition is licensed under AGPLv3, allowing free use as long as you comply with its terms. If you modify and distribute the software, you are required to provide the source code to your users.
|
||||
|
||||
Both **Chevereto Lite** and **Chevereto Pro** are distributed under the proprietary **Chevereto License**, which permits use for commercial purposes.
|
||||
|
||||
*Note: Proprietary licensing does not mean closed source; the source code is accessible, but its use is governed by the specific terms of the Chevereto License.*
|
||||
|
||||
@@ -16,36 +16,40 @@
|
||||
"composer/package-versions-deprecated": true
|
||||
},
|
||||
"platform": {
|
||||
"php": "8.0.30"
|
||||
"php": "8.1.28"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"php": "^8.1",
|
||||
"intervention/image": "^2.6",
|
||||
"jeroendesloovere/xmp-metadata-extractor": "^2.0",
|
||||
"league/flysystem": "^2.0",
|
||||
"jenssegers/imagehash": "^0.5.0",
|
||||
"guzzlehttp/psr7": "^1.7",
|
||||
"phpmailer/phpmailer": "^6.5",
|
||||
"psr/cache": "^1",
|
||||
"psr/log": "^1",
|
||||
"phpseclib/phpseclib": "^3.0",
|
||||
"phpseclib/phpseclib": "^3.0.37",
|
||||
"mobiledetect/mobiledetectlib": "^2.8",
|
||||
"mlocati/ip-lib": "^1.17",
|
||||
"composer/ca-bundle": "^1.2",
|
||||
"chevere/chevere": "^2.0",
|
||||
"chevere/throwable-handler": "^0.9",
|
||||
"chevere/xr": "^0.7",
|
||||
"chevere/xr-server": "^0.7",
|
||||
"chevere/workflow": "^0.7.0",
|
||||
"chevere/throwable-handler": "^1.0.2",
|
||||
"xrdebug/php": "^2.0.2",
|
||||
"xrdebug/xrdebug": "^2.0.2",
|
||||
"chevere/workflow": "^0.9.0",
|
||||
"pragmarx/google2fa": "^8.0",
|
||||
"pragmarx/google2fa-qrcode": "^3.0",
|
||||
"chevere/cache": "^0.4",
|
||||
"phpseclib/bcmath_compat": "^2.0",
|
||||
"chillerlan/php-qrcode": "^4.3",
|
||||
"firebase/php-jwt": "^6.3",
|
||||
"lychee-org/php-exif": "^0.7.14",
|
||||
"p3k/emoji-detector": "^1.0",
|
||||
"php-ds/php-ds": "^1.4",
|
||||
"php-ffmpeg/php-ffmpeg": "^1.2"
|
||||
"php-ffmpeg/php-ffmpeg": "^1.2",
|
||||
"psy/psysh": "^0.11.8",
|
||||
"chevere/cache": "^0.5.0",
|
||||
"chevere/var-dump": "^2.0.x-dev",
|
||||
"chevere/var-support": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
@@ -70,10 +74,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.2",
|
||||
"symplify/easy-coding-standard": "^10.3",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"rector/rector": "^0.12.15",
|
||||
"psy/psysh": "^0.11.8"
|
||||
"symplify/easy-coding-standard": "^12.2",
|
||||
"phpstan/phpstan": "^1.11"
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
|
||||
3318
app/composer.lock
generated
3318
app/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,6 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Config\AssetConfig;
|
||||
use Chevereto\Config\Config;
|
||||
use Chevereto\Config\EnabledConfig;
|
||||
use Chevereto\Config\HostConfig;
|
||||
@@ -18,19 +17,6 @@ use Chevereto\Config\SystemConfig;
|
||||
use function Chevereto\Vars\env;
|
||||
|
||||
new Config(
|
||||
asset: new AssetConfig(
|
||||
accountId: env()['CHEVERETO_ASSET_STORAGE_ACCOUNT_ID'],
|
||||
accountName: env()['CHEVERETO_ASSET_STORAGE_ACCOUNT_NAME'],
|
||||
bucket: env()['CHEVERETO_ASSET_STORAGE_BUCKET'],
|
||||
key: env()['CHEVERETO_ASSET_STORAGE_KEY'],
|
||||
name: env()['CHEVERETO_ASSET_STORAGE_NAME'],
|
||||
region: env()['CHEVERETO_ASSET_STORAGE_REGION'],
|
||||
secret: env()['CHEVERETO_ASSET_STORAGE_SECRET'],
|
||||
server: env()['CHEVERETO_ASSET_STORAGE_SERVER'],
|
||||
service: env()['CHEVERETO_ASSET_STORAGE_SERVICE'],
|
||||
type: env()['CHEVERETO_ASSET_STORAGE_TYPE'],
|
||||
url: env()['CHEVERETO_ASSET_STORAGE_URL'],
|
||||
),
|
||||
enabled: new EnabledConfig(
|
||||
phpPages: (bool) env()['CHEVERETO_ENABLE_PHP_PAGES'],
|
||||
updateCli: (bool) env()['CHEVERETO_ENABLE_UPDATE_CLI'],
|
||||
|
||||
@@ -10,86 +10,97 @@
|
||||
*/
|
||||
|
||||
return [
|
||||
'CHEVERETO_ASSET_STORAGE_ACCOUNT_ID' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_ACCOUNT_NAME' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_BUCKET' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_KEY' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_NAME' => 'assets',
|
||||
'CHEVERETO_ASSET_STORAGE_REGION' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_SECRET' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_SERVER' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_SERVICE' => '',
|
||||
'CHEVERETO_ASSET_STORAGE_TYPE' => 'local',
|
||||
'CHEVERETO_ASSET_STORAGE_URL' => '',
|
||||
'CHEVERETO_CONTEXT' => '',
|
||||
'CHEVERETO_DB_DRIVER' => 'mysql',
|
||||
'CHEVERETO_DB_HOST' => 'localhost',
|
||||
'CHEVERETO_DB_NAME' => '',
|
||||
'CHEVERETO_DB_PASS' => '',
|
||||
'CHEVERETO_DB_PDO_ATTRS' => '[]',
|
||||
'CHEVERETO_DB_PORT' => '3306',
|
||||
'CHEVERETO_DB_TABLE_PREFIX' => 'chv_',
|
||||
'CHEVERETO_DB_USER' => '',
|
||||
'CHEVERETO_DEBUG_LEVEL' => '1',
|
||||
'CHEVERETO_ENABLE_API_GUEST' => '1',
|
||||
'CHEVERETO_ENABLE_BANNERS' => '1',
|
||||
'CHEVERETO_ENABLE_BULK_IMPORTER' => '1',
|
||||
'CHEVERETO_ENABLE_CAPTCHA' => '1',
|
||||
'CHEVERETO_ENABLE_CDN' => '1',
|
||||
'CHEVERETO_ENABLE_CHECK_UPDATES' => '1',
|
||||
'CHEVERETO_ENABLE_CONSENT_SCREEN' => '1',
|
||||
'CHEVERETO_ENABLE_COOKIE_COMPLIANCE' => '1',
|
||||
'CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES' => '1',
|
||||
'CHEVERETO_ENABLE_EXTERNAL_SERVICES' => '1',
|
||||
'CHEVERETO_ENABLE_EXTERNAL_STORAGE' => '1',
|
||||
'CHEVERETO_ENABLE_FAVICON' => '1',
|
||||
'CHEVERETO_ENABLE_FOLLOWERS' => '1',
|
||||
'CHEVERETO_ENABLE_HTACCESS_CHECK' => '0',
|
||||
'CHEVERETO_ENABLE_IP_BANS' => '1',
|
||||
'CHEVERETO_ENABLE_LANGUAGE_CHOOSER' => '1',
|
||||
'CHEVERETO_ENABLE_LIKES' => '1',
|
||||
'CHEVERETO_ENABLE_LOCAL_STORAGE' => '1',
|
||||
'CHEVERETO_ENABLE_LOGIN_PROVIDERS' => '1',
|
||||
'CHEVERETO_ENABLE_LOGO' => '1',
|
||||
'CHEVERETO_ENABLE_MODERATION' => '1',
|
||||
'CHEVERETO_ENABLE_NOTIFICATIONS' => '1',
|
||||
'CHEVERETO_ENABLE_PAGES' => '1',
|
||||
'CHEVERETO_ENABLE_PHP_PAGES' => '0',
|
||||
'CHEVERETO_ENABLE_POWERED_BY_FOOTER_SITE_WIDE' => '0',
|
||||
'CHEVERETO_ENABLE_ROUTING' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_AKISMET' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_MODERATECONTENT' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_PROJECTARACHNID' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_STOPFORUMSPAM' => '1',
|
||||
'CHEVERETO_ENABLE_STOPWORDS' => '1',
|
||||
'CHEVERETO_ENABLE_UPDATE_CLI' => '1',
|
||||
'CHEVERETO_ENABLE_UPDATE_HTTP' => '1',
|
||||
'CHEVERETO_ENABLE_UPLOAD_FLOOD_PROTECTION' => '1',
|
||||
'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' => '',
|
||||
'CHEVERETO_HOSTNAME_PATH' => '/',
|
||||
'CHEVERETO_HOSTNAME' => 'localhost',
|
||||
'CHEVERETO_HTTPS' => '1',
|
||||
'CHEVERETO_IMAGE_FORMATS_AVAILABLE' => '["JPEG","PNG","BMP","GIF","WEBP"]',
|
||||
'CHEVERETO_IMAGE_LIBRARY' => 'imagick',
|
||||
'CHEVERETO_MAX_ALBUMS' => '0',
|
||||
'CHEVERETO_MAX_EXECUTION_TIME_SECONDS' => '30',
|
||||
'CHEVERETO_MAX_IMAGES' => '0',
|
||||
'CHEVERETO_MAX_MEMORY_SIZE' => '512M',
|
||||
'CHEVERETO_MAX_POST_SIZE' => '64M',
|
||||
'CHEVERETO_MAX_UPLOAD_SIZE' => '64M',
|
||||
'CHEVERETO_MAX_USER_ALBUMS_LIST' => '300',
|
||||
'CHEVERETO_MAX_USERS' => '0',
|
||||
'CHEVERETO_SERVICING' => 'server',
|
||||
'CHEVERETO_SESSION_SAVE_HANDLER' => 'files',
|
||||
'CHEVERETO_SESSION_SAVE_PATH' => '/tmp',
|
||||
'CHEVERETO_EDITION' => 'pro',
|
||||
'CHEVERETO_BINARY_FFMPEG' => 'ffmpeg',
|
||||
'CHEVERETO_BINARY_FFPROBE' => 'ffprobe',
|
||||
'CHEVERETO_BINARY_FFMPEG' => 'ffmpeg',
|
||||
'CHEVERETO_BINARY_FFPROBE' => 'ffprobe',
|
||||
'CHEVERETO_CONTEXT' => '',
|
||||
'CHEVERETO_DB_DRIVER' => 'mysql',
|
||||
'CHEVERETO_DB_HOST' => 'localhost',
|
||||
'CHEVERETO_DB_NAME' => '',
|
||||
'CHEVERETO_DB_PASS' => '',
|
||||
'CHEVERETO_DB_PDO_ATTRS' => '[]',
|
||||
'CHEVERETO_DB_PORT' => '3306',
|
||||
'CHEVERETO_DB_TABLE_PREFIX' => 'chv_',
|
||||
'CHEVERETO_DB_USER' => '',
|
||||
'CHEVERETO_DEBUG_LEVEL' => '1',
|
||||
'CHEVERETO_EDITION' => 'pro',
|
||||
'CHEVERETO_ENABLE_API_GUEST' => '1',
|
||||
'CHEVERETO_ENABLE_BANNERS' => '1',
|
||||
'CHEVERETO_ENABLE_BULK_IMPORTER' => '1',
|
||||
'CHEVERETO_ENABLE_CAPTCHA' => '1',
|
||||
'CHEVERETO_ENABLE_CDN' => '1',
|
||||
'CHEVERETO_ENABLE_CONSENT_SCREEN' => '1',
|
||||
'CHEVERETO_ENABLE_COOKIE_COMPLIANCE' => '1',
|
||||
'CHEVERETO_ENABLE_DEBUG' => '1',
|
||||
'CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES' => '1',
|
||||
'CHEVERETO_ENABLE_EXTERNAL_SERVICES' => '1',
|
||||
'CHEVERETO_ENABLE_EXTERNAL_STORAGE_PROVIDERS' => '1',
|
||||
'CHEVERETO_ENABLE_FAVICON' => '1',
|
||||
'CHEVERETO_ENABLE_FOLLOWERS' => '1',
|
||||
'CHEVERETO_ENABLE_FORCE_POWERED_BY_FOOTER' => '0',
|
||||
'CHEVERETO_ENABLE_HTACCESS_CHECK' => '0',
|
||||
'CHEVERETO_ENABLE_IP_BANS' => '1',
|
||||
'CHEVERETO_ENABLE_LANGUAGE_CHOOSER' => '1',
|
||||
'CHEVERETO_ENABLE_LIKES' => '1',
|
||||
'CHEVERETO_ENABLE_LOCAL_STORAGE' => '1',
|
||||
'CHEVERETO_ENABLE_LOGIN_PROVIDERS' => '1',
|
||||
'CHEVERETO_ENABLE_LOGO_CUSTOM' => '1',
|
||||
'CHEVERETO_ENABLE_MODERATION' => '1',
|
||||
'CHEVERETO_ENABLE_NEWS_CHECK' => '1',
|
||||
'CHEVERETO_ENABLE_NOTIFICATIONS' => '1',
|
||||
'CHEVERETO_ENABLE_PAGES' => '1',
|
||||
'CHEVERETO_ENABLE_PHP_PAGES' => '0',
|
||||
'CHEVERETO_ENABLE_POWERED_BY_SETTING' => '1',
|
||||
'CHEVERETO_ENABLE_PUP_CUSTOM_URL' => '1',
|
||||
'CHEVERETO_ENABLE_ROUTING' => '1',
|
||||
'CHEVERETO_ENABLE_SEO_ALBUM_URL' => '1',
|
||||
'CHEVERETO_ENABLE_SEO_IMAGE_URL' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_AKISMET' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_MODERATECONTENT' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_PROJECTARACHNID' => '1',
|
||||
'CHEVERETO_ENABLE_SERVICE_STOPFORUMSPAM' => '1',
|
||||
'CHEVERETO_ENABLE_STOPWORDS' => '1',
|
||||
'CHEVERETO_ENABLE_UPDATE_CHECK' => '1',
|
||||
'CHEVERETO_ENABLE_UPDATE_CLI' => '1',
|
||||
'CHEVERETO_ENABLE_UPDATE_HTTP' => '1',
|
||||
'CHEVERETO_ENABLE_UPLOAD_FLOOD_PROTECTION' => '1',
|
||||
'CHEVERETO_ENABLE_UPLOAD_PLUGIN' => '1',
|
||||
'CHEVERETO_ENABLE_UPLOAD_URL' => '1',
|
||||
'CHEVERETO_ENABLE_UPLOAD_WATERMARK' => '1',
|
||||
'CHEVERETO_ENABLE_USERS' => '1',
|
||||
'CHEVERETO_ENABLE_XRDEBUG' => '0',
|
||||
'CHEVERETO_ENCRYPTION_KEY' => '',
|
||||
'CHEVERETO_ERROR_LOG_CLI' => '',
|
||||
'CHEVERETO_ERROR_LOG_CRON' => '',
|
||||
'CHEVERETO_ERROR_LOG' => 'php://stderr',
|
||||
'CHEVERETO_HEADER_CLIENT_IP' => '',
|
||||
'CHEVERETO_HOSTNAME_PATH' => '/',
|
||||
'CHEVERETO_HOSTNAME' => 'localhost',
|
||||
'CHEVERETO_HTTPS' => '1',
|
||||
'CHEVERETO_IMAGE_FORMATS_AVAILABLE' => '["AVIF","JPEG","PNG","BMP","GIF","WEBP"]',
|
||||
'CHEVERETO_IMAGE_LIBRARY' => 'imagick',
|
||||
'CHEVERETO_MAX_ADMINS' => '0',
|
||||
'CHEVERETO_MAX_ALBUMS' => '0',
|
||||
'CHEVERETO_MAX_CATEGORIES' => '0',
|
||||
'CHEVERETO_MAX_EXECUTION_TIME_SECONDS' => '30',
|
||||
'CHEVERETO_MAX_FILES' => '0',
|
||||
'CHEVERETO_MAX_LOGIN_PROVIDERS' => '0',
|
||||
'CHEVERETO_MAX_MANAGERS' => '0',
|
||||
'CHEVERETO_MAX_MEMORY_SIZE' => '512M',
|
||||
'CHEVERETO_MAX_PAGES' => '0',
|
||||
'CHEVERETO_MAX_POST_SIZE' => '100M',
|
||||
'CHEVERETO_MAX_STORAGES' => '0',
|
||||
'CHEVERETO_MAX_TAGS_PER_FILE' => '0',
|
||||
'CHEVERETO_MAX_TAGS_PER_LISTING' => '0',
|
||||
'CHEVERETO_MAX_TAGS' => '0',
|
||||
'CHEVERETO_MAX_UPLOAD_SIZE' => '100M',
|
||||
'CHEVERETO_MAX_USER_ALBUMS_LIST' => '500',
|
||||
'CHEVERETO_MAX_USERS' => '0',
|
||||
'CHEVERETO_MIN_STORAGES_ACTIVE' => '0',
|
||||
'CHEVERETO_SERVICING' => 'server',
|
||||
'CHEVERETO_SESSION_SAVE_HANDLER' => 'files',
|
||||
'CHEVERETO_SESSION_SAVE_PATH' => '/tmp',
|
||||
'CHEVERETO_XRDEBUG_HOST' => 'localhost',
|
||||
'CHEVERETO_XRDEBUG_HTTPS' => '0',
|
||||
'CHEVERETO_XRDEBUG_KEY' => '',
|
||||
'CHEVERETO_XRDEBUG_PORT' => '27420',
|
||||
];
|
||||
|
||||
@@ -35,8 +35,10 @@ $settings = Settings::get();
|
||||
new EncryptionInstance($toEncryption);
|
||||
foreach (Settings::ENCRYPTED_NAMES as $key) {
|
||||
$value = $settings[$key] ?? '';
|
||||
feedback("- $key: $value");
|
||||
Settings::update([$key => $value]);
|
||||
feedback("- {$key}: {$value}");
|
||||
Settings::update([
|
||||
$key => $value,
|
||||
]);
|
||||
}
|
||||
feedbackSeparator();
|
||||
feedbackStep($doing, 'storages');
|
||||
@@ -48,7 +50,7 @@ foreach ($storages as $storage) {
|
||||
$values = [];
|
||||
foreach (Storage::ENCRYPTED_NAMES as $key) {
|
||||
$value = $storage[$key] ?? '';
|
||||
feedback(" $key: $value");
|
||||
feedback(" {$key}: {$value}");
|
||||
$values[$key] = $value;
|
||||
}
|
||||
Storage::update(
|
||||
@@ -59,7 +61,10 @@ foreach ($storages as $storage) {
|
||||
}
|
||||
feedbackSeparator();
|
||||
feedbackStep($doing, 'two-factor secrets');
|
||||
$twoFactors = DB::get('two_factors', [], 'AND', ['field' => 'id', 'order' => 'desc']);
|
||||
$twoFactors = DB::get('two_factors', [], 'AND', [
|
||||
'field' => 'id',
|
||||
'order' => 'desc',
|
||||
]);
|
||||
foreach ($twoFactors as $twoFactor) {
|
||||
new EncryptionInstance($fromEncryption);
|
||||
$twoFactor = TwoFactor::get($twoFactor['two_factor_id']);
|
||||
@@ -69,7 +74,7 @@ foreach ($twoFactors as $twoFactor) {
|
||||
$values = [
|
||||
'secret' => $secret,
|
||||
];
|
||||
feedback("- secret: $secret");
|
||||
feedback("- secret: {$secret}");
|
||||
TwoFactor::update(
|
||||
id: $twoFactor['id'],
|
||||
values: $values,
|
||||
@@ -85,7 +90,7 @@ foreach ($loginProviders as $name => $loginProvider) {
|
||||
$values = [];
|
||||
foreach (Login::ENCRYPTED_PROVIDER_NAMES as $key) {
|
||||
$value = $loginProvider[$key] ?? '';
|
||||
feedback(" $key: $value");
|
||||
feedback(" {$key}: {$value}");
|
||||
$values[$key] = $value;
|
||||
}
|
||||
Login::updateProvider(
|
||||
@@ -95,11 +100,18 @@ foreach ($loginProviders as $name => $loginProvider) {
|
||||
}
|
||||
feedbackSeparator();
|
||||
feedbackStep($doing, 'login connection tokens');
|
||||
$connections = DB::get(table: 'login_connections', values: 'all', sort: ['field' => 'id', 'order' => 'desc']);
|
||||
$connections = DB::get(
|
||||
table: 'login_connections',
|
||||
where: 'all',
|
||||
sort: [
|
||||
'field' => 'id',
|
||||
'order' => 'desc',
|
||||
]
|
||||
);
|
||||
foreach ($connections as $connection) {
|
||||
new EncryptionInstance($fromEncryption);
|
||||
$connection = Login::getConnection($connection['login_connection_id']);
|
||||
feedback("> Login connection #" . $connection['id']);
|
||||
feedback('> Login connection #' . $connection['id']);
|
||||
new EncryptionInstance($toEncryption);
|
||||
$token = $connection['token'];
|
||||
$values = [
|
||||
@@ -110,14 +122,14 @@ foreach ($connections as $connection) {
|
||||
values: $values,
|
||||
);
|
||||
$tokenString = serialize($token);
|
||||
feedback("- token: $tokenString");
|
||||
feedback("- token: {$tokenString}");
|
||||
}
|
||||
feedbackSeparator();
|
||||
feedbackStep($doing, 'albums password');
|
||||
$albumsPassword = DB::queryFetchAll('SELECT album_id id, album_password password FROM ' . DB::getTable('albums') . ' WHERE album_password IS NOT NULL;');
|
||||
foreach ($albumsPassword as $album) {
|
||||
new EncryptionInstance($fromEncryption);
|
||||
feedback("> Album id #" . $album['id']);
|
||||
feedback('> Album id #' . $album['id']);
|
||||
new EncryptionInstance($toEncryption);
|
||||
$password = $album['password'];
|
||||
$values = [
|
||||
@@ -127,5 +139,5 @@ foreach ($albumsPassword as $album) {
|
||||
id: (int) $album['id'],
|
||||
values: $values,
|
||||
);
|
||||
feedback("- password: $password");
|
||||
feedback("- password: {$password}");
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevere\ThrowableHandler\Documents\PlainDocument;
|
||||
use Chevereto\Config\Config;
|
||||
use function Chevereto\Legacy\checkUpdates;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Image;
|
||||
use Chevereto\Legacy\Classes\L10n;
|
||||
@@ -18,6 +18,13 @@ use Chevereto\Legacy\Classes\Lock;
|
||||
use Chevereto\Legacy\Classes\Queue;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\Classes\Variable;
|
||||
use function Chevere\Message\message;
|
||||
use function Chevere\ThrowableHandler\throwableHandler;
|
||||
use function Chevere\Writer\writers;
|
||||
use function Chevere\xrDebug\PHP\throwableHandler as XrDebugThrowableHandler;
|
||||
use function Chevereto\Legacy\checkUpdates;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
use function Chevereto\Legacy\feedbackAlert;
|
||||
use function Chevereto\Legacy\feedbackStep;
|
||||
use function Chevereto\Legacy\G\datetime_add;
|
||||
@@ -30,44 +37,115 @@ use function Chevereto\Vars\env;
|
||||
|
||||
if (getSetting('maintenance')) {
|
||||
echo "[!] Chevereto is in maintenance mode.\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
$jobs = ['deleteExpiredImages', 'cleanUnconfirmedUsers', 'removeDeleteLog', 'checkForNews'];
|
||||
if ((bool) env()['CHEVERETO_ENABLE_EXTERNAL_STORAGE']) {
|
||||
$jobs[] = 'storageDelete';
|
||||
}
|
||||
if ((bool) env()['CHEVERETO_ENABLE_CHECK_UPDATES']) {
|
||||
$jobs = [
|
||||
'deleteExpiredImages',
|
||||
'cleanUnconfirmedUsers',
|
||||
'removeDeleteLog',
|
||||
'storageDelete',
|
||||
];
|
||||
if ((bool) env()['CHEVERETO_ENABLE_UPDATE_CHECK']) {
|
||||
$jobs[] = 'checkForUpdates';
|
||||
}
|
||||
if ((bool) env()['CHEVERETO_ENABLE_NEWS_CHECK']) {
|
||||
$jobs[] = 'checkForNews';
|
||||
}
|
||||
if (Config::enabled()->htaccessCheck()) {
|
||||
$jobs[] = 'checkHtaccess';
|
||||
}
|
||||
shuffle($jobs);
|
||||
$time_start = microtime(true);
|
||||
$errors = [];
|
||||
$namespace = env()['CHEVERETO_ID_HANDLE'] ?? false;
|
||||
foreach ($jobs as $job) {
|
||||
if (!isSafeToExecute()) {
|
||||
if (! isSafeToExecute()) {
|
||||
echo "[OK] Exit - (time is up)\n";
|
||||
writeLastRan();
|
||||
writeLastRan($time_start);
|
||||
exit(0);
|
||||
}
|
||||
feedbackStep('Job:', $job);
|
||||
$job();
|
||||
|
||||
try {
|
||||
$job();
|
||||
} catch (Throwable $throwable) {
|
||||
feedbackAlert($throwable->getMessage());
|
||||
$errors[$job] = $throwable->getMessage();
|
||||
$publicHandler = throwableHandler($throwable);
|
||||
if ($namespace) {
|
||||
$publicHandler = $publicHandler
|
||||
->withId($namespace . $publicHandler->id());
|
||||
}
|
||||
$internalHandler = $publicHandler->withIsDebug(true);
|
||||
$docInternal = new PlainDocument($internalHandler);
|
||||
$logMessage = '[' . $publicHandler->id() . '] '
|
||||
. $docInternal->__toString()
|
||||
. "\n\n";
|
||||
|
||||
try {
|
||||
$errorLog = ini_get('error_log');
|
||||
$fp = fopen($errorLog, 'a');
|
||||
fwrite($fp, $logMessage);
|
||||
fclose($fp);
|
||||
} catch (Throwable) {
|
||||
if (PHP_SAPI === 'cli') {
|
||||
error_log($logMessage);
|
||||
} else {
|
||||
writers()->error()->write($logMessage);
|
||||
}
|
||||
}
|
||||
$extra = <<<HTML
|
||||
<div class="throwable-message"><b>Incident {$publicHandler->id()}</b></div>
|
||||
<div class="throwable-message"><b>Backtrace</b></div>
|
||||
HTML;
|
||||
XrDebugThrowableHandler($throwable, $extra);
|
||||
}
|
||||
}
|
||||
writeLastRan();
|
||||
function writeLastRan(): void
|
||||
writeLastRan($time_start);
|
||||
function writeLastRan(float $time_start): void
|
||||
{
|
||||
$datetimegmt = datetimegmt();
|
||||
Settings::update(['cron_last_ran' => datetimegmt()]);
|
||||
echo "--\n✅ [DONE] Cron tasks ran @ $datetimegmt\n";
|
||||
Variable::set('cron_last_ran', $datetimegmt);
|
||||
$time_taken = microtime(true) - $time_start;
|
||||
$ceil = ceil($time_taken);
|
||||
$round = round($time_taken, 2);
|
||||
echo "--\n[DONE] Cron tasks ran @ {$datetimegmt}";
|
||||
echo "\n{$round}s\n--";
|
||||
if (version_compare(cheveretoVersionInstalled(), '4.2.0', '>=')) {
|
||||
$sql = <<<MySQL
|
||||
INSERT `%table_stats%` (stat_type, stat_date_gmt, stat_cron_time, stat_cron_runs)
|
||||
VALUES ("date", DATE("%date_gmt%"), %time%, 1)
|
||||
ON DUPLICATE KEY
|
||||
UPDATE stat_cron_time = stat_cron_time + %time%,
|
||||
stat_cron_runs = stat_cron_runs + 1;
|
||||
MySQL;
|
||||
$sql = (string) message(
|
||||
$sql,
|
||||
table_stats: DB::getTable('stats'),
|
||||
time: $ceil,
|
||||
date_gmt: $datetimegmt,
|
||||
);
|
||||
|
||||
try {
|
||||
DB::queryExecute($sql);
|
||||
} catch (Throwable $e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
exit;
|
||||
}
|
||||
function echoLocked(string $job): void
|
||||
{
|
||||
echo "* [!] Job $job is locked ~ skipping\n";
|
||||
echo "* Job: {$job} [now locked]\n";
|
||||
}
|
||||
function storageDelete(): void
|
||||
{
|
||||
$job = 'storage-delete';
|
||||
$lock = new Lock($job);
|
||||
if ($lock->create()) {
|
||||
Queue::process(['type' => $job]);
|
||||
Queue::process([
|
||||
'type' => $job,
|
||||
]);
|
||||
$lock->destroy();
|
||||
|
||||
return;
|
||||
@@ -115,7 +193,7 @@ function removeDeleteLog(): void
|
||||
}
|
||||
function checkForNews(): void
|
||||
{
|
||||
if (!checkoutUpdate('news_check_datetimegmt', 'PT4H')) {
|
||||
if (! checkoutUpdate('news_check_datetimegmt', 'PT4H')) {
|
||||
feedbackAlert('Skipping news check');
|
||||
|
||||
return;
|
||||
@@ -133,7 +211,7 @@ function checkForNews(): void
|
||||
}
|
||||
function checkForUpdates(): void
|
||||
{
|
||||
if (!checkoutUpdate('update_check_datetimegmt', 'P1D')) {
|
||||
if (! checkoutUpdate('update_check_datetimegmt', 'P1D')) {
|
||||
feedbackAlert('Skipping updates check');
|
||||
|
||||
return;
|
||||
@@ -151,8 +229,13 @@ function checkForUpdates(): void
|
||||
}
|
||||
function checkoutUpdate(string $datetimeSetting, string $past): bool
|
||||
{
|
||||
return is_null(Settings::get($datetimeSetting))
|
||||
|| datetime_add(Settings::get($datetimeSetting), $past) < datetimegmt();
|
||||
$get = Variable::fetch($datetimeSetting);
|
||||
|
||||
return $get === null
|
||||
|| datetime_add(
|
||||
$get,
|
||||
$past
|
||||
) < datetimegmt();
|
||||
}
|
||||
function checkHtaccess()
|
||||
{
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
|
||||
if (getSetting('chevereto_version_installed') !== null) {
|
||||
if (cheveretoVersionInstalled() !== '') {
|
||||
echo "[ERROR] Chevereto is already installed, try with the update command\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
require_once PATH_APP_LEGACY_INSTALL . 'installer.php';
|
||||
|
||||
41
app/legacy/commands/js.php
Normal file
41
app/legacy/commands/js.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
$workingDir = PATH_PUBLIC_CONTENT_LEGACY_THEMES_PEAFOWL_LIB;
|
||||
$target = 'chevereto-all.js';
|
||||
$outputFile = $workingDir . $target;
|
||||
echo "* Compile JavaScript\n";
|
||||
echo "---\n";
|
||||
$fh = fopen($outputFile, 'w');
|
||||
$files = [
|
||||
'js/css_browser_detector.js',
|
||||
'js/jquery.min.js',
|
||||
'js/jquery-ui.min.js',
|
||||
'js/hammer.min.js',
|
||||
'js/peafowl.js',
|
||||
'js/images-loaded.js',
|
||||
'js/load-image.js',
|
||||
'js/clipboard.js',
|
||||
'js/chevereto.js',
|
||||
];
|
||||
foreach ($files as $file) {
|
||||
$file = $workingDir . $file;
|
||||
if (! file_exists($file)) {
|
||||
echo "❌ [ERROR] Missing file: {$file}\n";
|
||||
exit(1);
|
||||
}
|
||||
echo "Packing: {$file}\n";
|
||||
fwrite($fh, file_get_contents($file) . "\n");
|
||||
}
|
||||
fclose($fh);
|
||||
echo "---\n";
|
||||
echo "💯 [OK] {$outputFile}\n";
|
||||
exit(0);
|
||||
@@ -9,9 +9,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevere\Filesystem\directoryForPath;
|
||||
use Chevereto\Legacy\Classes\L10n;
|
||||
use Chevereto\Legacy\G\Gettext;
|
||||
use function Chevere\Filesystem\directoryForPath;
|
||||
use function Chevereto\Legacy\G\unlinkIfExists;
|
||||
use function Chevereto\Legacy\get_available_languages;
|
||||
|
||||
@@ -27,20 +27,20 @@ foreach ($languages as $lang) {
|
||||
$language_override_file = PATH_APP_LANGUAGES . 'overrides/' . $filename;
|
||||
$language_handling = [
|
||||
'base' => [
|
||||
'file' => $language_file,
|
||||
'cache_path' => L10n::PATH_CACHE,
|
||||
'table' => [],
|
||||
'file' => $language_file,
|
||||
'cache_path' => L10n::PATH_CACHE,
|
||||
'table' => [],
|
||||
],
|
||||
'override' => [
|
||||
'file' => $language_override_file,
|
||||
'cache_path' => L10n::PATH_CACHE_OVERRIDES,
|
||||
'table' => [],
|
||||
]
|
||||
'file' => $language_override_file,
|
||||
'cache_path' => L10n::PATH_CACHE_OVERRIDES,
|
||||
'table' => [],
|
||||
],
|
||||
];
|
||||
foreach ($language_handling as $k => $v) {
|
||||
$cache_path = $v['cache_path'];
|
||||
$cache_file = basename($v['file']) . '.cache.php';
|
||||
if (!file_exists($v['file'])) {
|
||||
if (! file_exists($v['file'])) {
|
||||
continue;
|
||||
}
|
||||
$cache = $cache_path . $cache_file;
|
||||
@@ -51,12 +51,12 @@ foreach ($languages as $lang) {
|
||||
'cache_header' => $k == 'base',
|
||||
]);
|
||||
}
|
||||
echo "$lang\n";
|
||||
echo "{$lang}\n";
|
||||
if (file_exists($language_override_file)) {
|
||||
echo "$lang [override]\n";
|
||||
echo "{$lang} [override]\n";
|
||||
}
|
||||
}
|
||||
echo "---\n";
|
||||
echo L10n::LOCALES_AVAILABLE_FILEPATH . "\n";
|
||||
echo "💯 [OK] Languages re-cached\n";
|
||||
die(0);
|
||||
exit(0);
|
||||
|
||||
@@ -9,38 +9,38 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevere\String\randomString;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevere\Standard\randomString;
|
||||
|
||||
$opts = getopt('C:u:') ?: [];
|
||||
$missing = [];
|
||||
if (!isset($opts['u'])) {
|
||||
echo "[Error] Missing username" . "\n";
|
||||
die(255);
|
||||
if (! isset($opts['u'])) {
|
||||
echo '[Error] Missing username' . "\n";
|
||||
exit(255);
|
||||
}
|
||||
$password = randomString(24);
|
||||
$user = User::getSingle($opts['u'], 'username');
|
||||
if ($user === []) {
|
||||
echo "[Error] User not found" . "\n";
|
||||
die(255);
|
||||
echo '[Error] User not found' . "\n";
|
||||
exit(255);
|
||||
}
|
||||
$changed = Login::changePassword(
|
||||
userId: $user['id'],
|
||||
password: $password,
|
||||
update_session: false
|
||||
);
|
||||
if (!$changed) {
|
||||
if (! $changed) {
|
||||
// echo "[NOTICE] User doesn't have a password" . "\n";
|
||||
$added = Login::addPassword(
|
||||
userId: $user['id'],
|
||||
password: $password,
|
||||
update_session: false
|
||||
);
|
||||
if (!$added) {
|
||||
echo "[Error] Failed to add password" . "\n";
|
||||
die(255);
|
||||
if (! $added) {
|
||||
echo '[Error] Failed to add password' . "\n";
|
||||
exit(255);
|
||||
}
|
||||
}
|
||||
echo $password . "\n";
|
||||
die(0);
|
||||
exit(0);
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevere\Type\getType;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use function Chevere\Parameter\getType;
|
||||
|
||||
$opts = getopt('C:k:t::') ?: [];
|
||||
if (!isset($opts['k'])) {
|
||||
if (! isset($opts['k'])) {
|
||||
echo "[ERROR] Missing setting key\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
if (!Settings::hasKey($opts['k'])) {
|
||||
if (! Settings::hasKey($opts['k'])) {
|
||||
echo "[ERROR] Setting key doesn't exists\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
function toItalic(string $text): string
|
||||
{
|
||||
return "\e[3m$text\e[0m";
|
||||
return "\e[3m{$text}\e[0m";
|
||||
}
|
||||
$value = Settings::get($opts['k']);
|
||||
$echoValue = match (getType($value)) {
|
||||
@@ -31,9 +31,9 @@ $echoValue = match (getType($value)) {
|
||||
'boolean' => toItalic($value ? 'true' : 'false'),
|
||||
default => $value,
|
||||
};
|
||||
echo "$echoValue\n";
|
||||
echo "{$echoValue}\n";
|
||||
if (isset($opts['t'])) {
|
||||
$typeset = Settings::getTypeset($opts['k']);
|
||||
echo "%($typeset)\n";
|
||||
echo "%({$typeset})\n";
|
||||
}
|
||||
die(0);
|
||||
exit(0);
|
||||
|
||||
@@ -14,24 +14,22 @@ use Chevereto\Legacy\Classes\Settings;
|
||||
$opts = getopt('C:v:k:') ?: [];
|
||||
$missing = [];
|
||||
foreach (['k', 'v'] as $opt) {
|
||||
if (!isset($opts[$opt])) {
|
||||
if (! isset($opts[$opt])) {
|
||||
$missing[] = $opt;
|
||||
}
|
||||
}
|
||||
if ($missing !== []) {
|
||||
echo "[Error] Missing -" . implode(' -', $missing) . "\n";
|
||||
die(255);
|
||||
echo '[Error] Missing -' . implode(' -', $missing) . "\n";
|
||||
exit(255);
|
||||
}
|
||||
if (!Settings::hasKey($opts['k'])) {
|
||||
if (! Settings::hasKey($opts['k'])) {
|
||||
echo "[ERROR] Setting key doesn't exists\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
/** @var int|string|null $value */
|
||||
$value = $opts['v'] ?? null;
|
||||
$typeset = Settings::getTypeset($opts['k']);
|
||||
if ($typeset === 'bool') {
|
||||
$value = (int) ($value == 1 || strtolower($value) === 'true');
|
||||
}
|
||||
Settings::update([$opts['k'] => $value]);
|
||||
Settings::update([
|
||||
$opts['k'] => $value,
|
||||
]);
|
||||
require 'setting-get.php';
|
||||
die(0);
|
||||
exit(0);
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
|
||||
if (getSetting('chevereto_version_installed') === null) {
|
||||
if (cheveretoVersionInstalled() === '') {
|
||||
echo "[ERROR] Chevereto is not installed, try with the install command.\n";
|
||||
die(255);
|
||||
exit(255);
|
||||
}
|
||||
require_once PATH_APP_LEGACY_INSTALL . 'installer.php';
|
||||
|
||||
@@ -13,37 +13,37 @@ use function Chevereto\Legacy\loaderHandler;
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
header('HTTP/1.0 403 Forbidden');
|
||||
die("403 Forbidden\n");
|
||||
echo '403 Forbidden';
|
||||
exit(255);
|
||||
}
|
||||
$opts = getopt('C:') ?: [];
|
||||
if ($opts === []) {
|
||||
echo "Missing -C command\n";
|
||||
die(255);
|
||||
} else {
|
||||
$access = $opts['C'];
|
||||
$options = [
|
||||
'cron',
|
||||
'update',
|
||||
'encrypt-secrets',
|
||||
'decrypt-secrets',
|
||||
'htaccess-checksum',
|
||||
'htaccess-enforce',
|
||||
'bulk-importer',
|
||||
'install',
|
||||
'langs',
|
||||
'password-reset',
|
||||
'setting-get',
|
||||
'setting-update',
|
||||
'version'
|
||||
];
|
||||
if (!in_array($access, $options)) {
|
||||
echo "Invalid command\n";
|
||||
die(255);
|
||||
}
|
||||
echo 'Missing -C command' . PHP_EOL;
|
||||
exit(255);
|
||||
}
|
||||
$access = $opts['C'];
|
||||
$options = [
|
||||
'cron',
|
||||
'update',
|
||||
'encrypt-secrets',
|
||||
'decrypt-secrets',
|
||||
'htaccess-checksum',
|
||||
'htaccess-enforce',
|
||||
'bulk-importer',
|
||||
'install',
|
||||
'langs',
|
||||
'js',
|
||||
'password-reset',
|
||||
'setting-get',
|
||||
'setting-update',
|
||||
'version',
|
||||
];
|
||||
if (! in_array($access, $options, true)) {
|
||||
echo 'Invalid command' . PHP_EOL;
|
||||
exit(255);
|
||||
}
|
||||
define('ACCESS', $access);
|
||||
require_once __DIR__ . '/../load/php-boot.php';
|
||||
require_once __DIR__ . '/../load/loader.php';
|
||||
require_once loaderHandler(
|
||||
$_COOKIE,
|
||||
$_ENV,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\G\sanitize_path_slashes;
|
||||
use function Chevereto\Legacy\loaderHandler;
|
||||
|
||||
define('ACCESS', 'web');
|
||||
@@ -16,14 +17,21 @@ define('ACCESS', 'web');
|
||||
$appDir = __DIR__ . '/../..';
|
||||
$loadDir = __DIR__ . '/../load';
|
||||
require_once $loadDir . '/php-boot.php';
|
||||
$uri = $_SERVER['REQUEST_URI'] ?? '';
|
||||
$parseUri = parse_url($uri);
|
||||
if (in_array($parseUri['path'] ?? null, ['/upgrading', '/upgrading/'])
|
||||
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
|
||||
$scriptName = $_SERVER['SCRIPT_NAME'] ?? '';
|
||||
$urlPath = parse_url($requestUri, PHP_URL_PATH);
|
||||
if (str_ends_with($scriptName, 'index.php')) {
|
||||
$relative_root = sanitize_path_slashes(
|
||||
dirname($scriptName)
|
||||
. '/'
|
||||
);
|
||||
$urlPath = preg_replace('#' . $relative_root . '#', '/', $requestUri, 1);
|
||||
}
|
||||
if (in_array($urlPath, ['/upgrading', '/upgrading/'], true)
|
||||
&& file_exists($appDir . '/.upgrading/upgrading.lock')) {
|
||||
require $appDir . '/upgrading.php';
|
||||
exit;
|
||||
}
|
||||
require_once $loadDir . '/loader.php';
|
||||
require_once loaderHandler(
|
||||
$_COOKIE,
|
||||
$_ENV,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,12 @@
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (!defined('ACCESS') || !ACCESS) {
|
||||
die('This file cannot be directly accessed.');
|
||||
if (! defined('ACCESS') || ! ACCESS) {
|
||||
exit('This file cannot be directly accessed.');
|
||||
} ?>
|
||||
<h1><i class="far fa-check-circle"></i> Already installed</h1>
|
||||
<p>Chevereto is already installed and updated.</p>
|
||||
<div>
|
||||
<a href="<?php echo get_base_url('dashboard'); ?>" class="action button radius"><span class="btn-icon fa-btn-icon fas fa-tachometer-alt"></span> Dashboard</a>
|
||||
<a href="<?php echo get_base_url(); ?>" class="button radius"><span class="btn-icon fa-btn-icon fas fa-globe"></span> Website</a>
|
||||
<a href="<?php echo get_base_url('dashboard'); ?>" class="action button radius"><span class="fas fa-tachometer-alt"></span> Dashboard</a>
|
||||
<a href="<?php echo get_base_url(); ?>" class="button radius"><span class="fas fa-globe"></span> Website</a>
|
||||
</div>
|
||||
|
||||
@@ -3,13 +3,20 @@ use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\get_chevereto_version;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (!defined('ACCESS') || !ACCESS) {
|
||||
die('This file cannot be directly accessed.');
|
||||
if (! defined('ACCESS') || ! ACCESS) {
|
||||
exit('This file cannot be directly accessed.');
|
||||
} ?>
|
||||
<h1><i class="far fa-check-circle"></i> Installation complete</h1>
|
||||
<p><?php echo strtr('Chevereto has been successfully installed. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', ['%s' => get_chevereto_version(true), '%u' => get_base_url('dashboard/?welcome')]); ?></p>
|
||||
<p><?php echo strtr('Chevereto has been successfully installed. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', [
|
||||
'%s' => get_chevereto_version(true),
|
||||
'%u' => get_base_url('dashboard/?welcome'),
|
||||
]); ?></p>
|
||||
<div>
|
||||
<a href="<?php echo get_base_url('dashboard/?welcome'); ?>" class="action button radius">Dashboard</a>
|
||||
<a href="<?php echo get_base_url(); ?>" class="button radius">Website</a>
|
||||
</div>
|
||||
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
CHV.fn.system.checkUpdates();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (!defined('ACCESS') || !ACCESS) {
|
||||
die('This file cannot be directly accessed.');
|
||||
if (! defined('ACCESS') || ! ACCESS) {
|
||||
exit('This file cannot be directly accessed.');
|
||||
} ?>
|
||||
<h1><i class="fa fa-box-open"></i> Ready to install</h1>
|
||||
<p>Fill this form with the details of the initial admin account you want to use.</p>
|
||||
@@ -15,7 +16,10 @@ if (!defined('ACCESS') || !ACCESS) {
|
||||
<div>
|
||||
<div class="p input-label">
|
||||
<label for="username">Admin username</label>
|
||||
<input type="text" name="username" id="username" class="width-100p" value="<?php echo $safe_post['username'] ?? ''; ?>" placeholder="Admin username" pattern="<?php echo getSetting('username_pattern'); ?>" title='<?php echo strtr('%i to %f characters<br>Letters, numbers and "_"', ['%i' => getSetting('username_min_length'), '%f' => getSetting('username_max_length')]); ?>' maxlength="<?php echo getSetting('username_max_length'); ?>" required>
|
||||
<input type="text" name="username" id="username" class="width-100p" value="<?php echo $safe_post['username'] ?? ''; ?>" placeholder="Admin username" pattern="<?php echo Settings::USERNAME_PATTERN; ?>" title='<?php echo strtr('%i to %f characters<br>Letters, numbers and "_"', [
|
||||
'%i' => Settings::USERNAME_MIN_LENGTH,
|
||||
'%f' => Settings::USERNAME_MAX_LENGTH,
|
||||
]); ?>' maxlength="<?php echo Settings::USERNAME_MAX_LENGTH; ?>" required>
|
||||
<span class="input-warning red-warning"><?php echo $input_errors['username'] ?? ''; ?></span>
|
||||
</div>
|
||||
<div class="p input-label">
|
||||
@@ -25,7 +29,7 @@ if (!defined('ACCESS') || !ACCESS) {
|
||||
</div>
|
||||
<div class="p input-label input-password">
|
||||
<label for="password">Admin password</label>
|
||||
<input type="password" name="password" id="password" class="width-100p" value="" placeholder="Admin password" title="Password to login" pattern="<?php echo getSetting('user_password_pattern'); ?>" autocomplete="new-password" required>
|
||||
<input type="password" name="password" id="password" class="width-100p" value="" placeholder="Admin password" title="Password to login" pattern="<?php echo Settings::USER_PASSWORD_PATTERN; ?>" autocomplete="new-password" required>
|
||||
<div class="input-password-strength"><span style="width: 0%" data-content="password-meter-bar"></span></div>
|
||||
<div class="input-warning red-warning" data-text="password-meter-message"><?php echo $input_errors['password'] ?? ''; ?></div>
|
||||
</div>
|
||||
@@ -43,7 +47,7 @@ if (!defined('ACCESS') || !ACCESS) {
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
?>
|
||||
<div>
|
||||
<button class="action radius" type="submit">Install</button>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
// @phpstan-ignore-next-line
|
||||
// @phpstan-ignore-next-line
|
||||
if (!defined('ACCESS') || !ACCESS) {
|
||||
die('This file cannot be directly accessed.');
|
||||
if (! defined('ACCESS') || ! ACCESS) {
|
||||
exit('This file cannot be directly accessed.');
|
||||
} ?>
|
||||
<h1>Update failed</h1>
|
||||
<p>The update process failed. Here is the error returned:</p>
|
||||
|
||||
@@ -4,13 +4,20 @@ use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\get_chevereto_version;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (!defined('ACCESS') || !ACCESS) {
|
||||
die('This file cannot be directly accessed.');
|
||||
if (! defined('ACCESS') || ! ACCESS) {
|
||||
exit('This file cannot be directly accessed.');
|
||||
} ?>
|
||||
<h1><i class="far fa-check-circle"></i> Update complete</h1>
|
||||
<p><?php echo strtr('Chevereto has been successfully updated to %s. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', ['%s' => get_chevereto_version(true), '%u' => get_base_url('dashboard')]); ?></p>
|
||||
<p><?php echo strtr('Chevereto has been successfully updated to %s. You can now continue to the <a href="%u">admin dashboard</a> and configure your website.', [
|
||||
'%s' => get_chevereto_version(true),
|
||||
'%u' => get_base_url('dashboard'),
|
||||
]); ?></p>
|
||||
<div>
|
||||
<a href="<?php echo get_base_url('dashboard'); ?>" class="action button radius">Dashboard</a>
|
||||
<a href="<?php echo get_base_url(); ?>" class="button radius">Website</a>
|
||||
</div>
|
||||
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
CHV.fn.system.checkUpdates();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
const APP_VERSION = '4.1.4';
|
||||
const APP_VERSION_AKA = 'pulento';
|
||||
const APP_VERSION = '4.2.0';
|
||||
const APP_VERSION_AKA = 'regio';
|
||||
|
||||
@@ -13,11 +13,11 @@ namespace Chevereto\Legacy;
|
||||
|
||||
use Chevereto\Config\Config;
|
||||
use Chevereto\Config\SystemConfig;
|
||||
use Imagick;
|
||||
use Throwable;
|
||||
use function Chevereto\Legacy\G\absolute_to_relative;
|
||||
use function Chevereto\Legacy\G\is_writable;
|
||||
use function Chevereto\Vars\server;
|
||||
use Imagick;
|
||||
use Throwable;
|
||||
|
||||
function getFailingImageFormats(string $imageLibrary): array
|
||||
{
|
||||
@@ -30,14 +30,14 @@ function getFailingImageFormats(string $imageLibrary): array
|
||||
if ($imageLibrary === 'imagick') {
|
||||
$imageFormats = Imagick::queryFormats();
|
||||
foreach ($mustHaveFormats as $format) {
|
||||
if (!in_array($format, $imageFormats)) {
|
||||
if (! in_array($format, $imageFormats)) {
|
||||
$failed_formats[] = $format;
|
||||
}
|
||||
}
|
||||
} elseif ($imageLibrary === 'gd') {
|
||||
$imageTypes = imagetypes();
|
||||
foreach ($mustHaveFormats as $format) {
|
||||
if (!($imageTypes & constant("IMG_$format"))) {
|
||||
if (! ($imageTypes & constant("IMG_{$format}"))) {
|
||||
$failed_formats[] = $format;
|
||||
}
|
||||
}
|
||||
@@ -51,17 +51,21 @@ function filesystemPermissionsCheck(): void
|
||||
$errors = [];
|
||||
$writing_paths = [CHV_PATH_IMAGES, PATH_PUBLIC_CONTENT, PATH_APP_CONTENT];
|
||||
foreach ($writing_paths as $v) {
|
||||
if (!file_exists($v)) {
|
||||
if (! file_exists($v)) {
|
||||
try {
|
||||
mkdir($v);
|
||||
} catch (Throwable) {
|
||||
$errors[] = "<code>"
|
||||
$errors[] = '<code>'
|
||||
. absolute_to_relative($v)
|
||||
. "</code> doesn't exists and can't be created.";
|
||||
}
|
||||
} else {
|
||||
if (!is_writable($v)) {
|
||||
$errors[] = 'No write permission for PHP user ' . get_current_user() . ' in <code>' . absolute_to_relative($v) . '</code> directory. Chevereto needs to be able to write in this directory.';
|
||||
if (! is_writable($v)) {
|
||||
$errors[] = 'No write permission for PHP user '
|
||||
. get_current_user()
|
||||
. ' in <code>'
|
||||
. absolute_to_relative($v)
|
||||
. '</code> directory. Chevereto needs to be able to write in this directory.';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,12 +77,17 @@ function phpCheck(SystemConfig $systemConfig): void
|
||||
$errors = [];
|
||||
$missing_tpl = '%n (<a href="http://php.net/manual/en/%t.%u.php" target="_blank">%f</a>) %t is disabled in this server. This %t must be enabled in your PHP configuration (php.ini) and/or you must add this missing %t.';
|
||||
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
|
||||
$errors[] = 'This server is currently running PHP version ' . PHP_VERSION . ' and Chevereto needs at least PHP 8.0.0 to run.';
|
||||
$errors[] = 'This server is currently running PHP version '
|
||||
. PHP_VERSION
|
||||
. ' and Chevereto needs at least PHP 8.0.0 to run.';
|
||||
}
|
||||
if (ini_get('allow_url_fopen') !== '1' && !function_exists('curl_init')) {
|
||||
if (ini_get('allow_url_fopen') !== '1' && ! function_exists('curl_init')) {
|
||||
$errors[] = "cURL isn't installed and allow_url_fopen is disabled. Chevereto needs one of these to perform HTTP requests to remote servers.";
|
||||
}
|
||||
if (preg_match('/apache/i', server()['SERVER_SOFTWARE'] ?? '') && function_exists('apache_get_modules') && !in_array('mod_rewrite', apache_get_modules())) {
|
||||
if (preg_match('/apache/i', server()['SERVER_SOFTWARE'] ?? '')
|
||||
&& function_exists('apache_get_modules')
|
||||
&& ! in_array('mod_rewrite', apache_get_modules())
|
||||
) {
|
||||
$errors[] = 'Apache <a href="http://httpd.apache.org/docs/2.1/rewrite/rewrite_intro.html" target="_blank">mod_rewrite</a> is not enabled in this server. This must be enabled to run Chevereto.';
|
||||
}
|
||||
$extensionsRequired = [
|
||||
@@ -86,13 +95,13 @@ function phpCheck(SystemConfig $systemConfig): void
|
||||
'%label' => 'Exif',
|
||||
'%name' => 'Exchangeable image information',
|
||||
'%slug' => 'book.exif',
|
||||
'%desc' => 'Exif is required to handle image metadata'
|
||||
'%desc' => 'Exif is required to handle image metadata',
|
||||
],
|
||||
'pdo' => [
|
||||
'%label' => 'PDO',
|
||||
'%name' => 'PHP Data Objects',
|
||||
'%slug' => 'book.pdo',
|
||||
'%desc' => 'PDO is needed to perform database operations'
|
||||
'%desc' => 'PDO is needed to perform database operations',
|
||||
],
|
||||
'pdo_mysql' => [
|
||||
'%label' => 'PDO_MYSQL',
|
||||
@@ -119,7 +128,7 @@ function phpCheck(SystemConfig $systemConfig): void
|
||||
'%name' => 'gd',
|
||||
'%slug' => 'book.gd',
|
||||
'%desc' => 'GD is needed for image processing',
|
||||
]
|
||||
],
|
||||
];
|
||||
$imageLibs = [
|
||||
'gd' => extension_loaded('gd') && function_exists('gd_info'),
|
||||
@@ -136,7 +145,7 @@ function phpCheck(SystemConfig $systemConfig): void
|
||||
$errors[] = 'Configured image_library ' . $systemConfigLib . ' is not present in this system.';
|
||||
}
|
||||
foreach ($extensionsRequired as $k => $v) {
|
||||
if (!extension_loaded($k)) {
|
||||
if (! extension_loaded($k)) {
|
||||
$errors[] = strtr('%name (<a href="http://www.php.net/manual/%slug.php">%label</a>) is not loaded in this server. %desc.', $v);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +153,11 @@ function phpCheck(SystemConfig $systemConfig): void
|
||||
if ($disabled_classes !== []) {
|
||||
foreach (['DirectoryIterator', 'RegexIterator', 'Pdo', 'Exception'] as $k) {
|
||||
if (in_array($k, $disabled_classes)) {
|
||||
$errors[] = strtr(str_replace('%t', 'class', $missing_tpl), ['%n' => $k, '%f' => $k, '%u' => str_replace('_', '-', strtolower($k))]);
|
||||
$errors[] = strtr(str_replace('%t', 'class', $missing_tpl), [
|
||||
'%n' => $k,
|
||||
'%f' => $k,
|
||||
'%u' => str_replace('_', '-', strtolower($k)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,48 +9,50 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevere\Message\message;
|
||||
use Chevere\Throwable\Exceptions\RuntimeException;
|
||||
use function Chevere\VarDump\varDumpHtml;
|
||||
use Chevere\VarDump\VarDumpInstance;
|
||||
use function Chevere\Writer\streamFor;
|
||||
use Chevere\Writer\StreamWriter;
|
||||
use Chevere\Writer\Writers;
|
||||
use Chevere\Writer\WritersInstance;
|
||||
use function Chevere\VarDump\varDumpHtml;
|
||||
use function Chevere\Writer\streamFor;
|
||||
|
||||
define('TIME_EXECUTION_START', microtime(true));
|
||||
!defined('REPL') && define('REPL', false);
|
||||
!defined('PACKAGING') && define('PACKAGING', false);
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
new WritersInstance(
|
||||
(new Writers())
|
||||
->withOutput(
|
||||
new StreamWriter(
|
||||
streamFor('php://output', 'w')
|
||||
try {
|
||||
define('TIME_EXECUTION_START', microtime(true));
|
||||
! defined('REPL') && define('REPL', false);
|
||||
! defined('PACKAGING') && define('PACKAGING', false);
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
new WritersInstance(
|
||||
(new Writers())
|
||||
->withOutput(
|
||||
new StreamWriter(
|
||||
streamFor('php://output', 'w')
|
||||
)
|
||||
)
|
||||
)
|
||||
->withError(
|
||||
new StreamWriter(
|
||||
streamFor('php://stderr', 'a')
|
||||
->withError(
|
||||
new StreamWriter(
|
||||
streamFor('php://stderr', 'w')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
new VarDumpInstance(varDumpHtml());
|
||||
}
|
||||
require_once __DIR__ . '/register-handlers.php';
|
||||
$posix_getuid = function_exists('posix_getuid')
|
||||
? posix_getuid()
|
||||
: 'unknown';
|
||||
if ($posix_getuid === 0
|
||||
&& !(REPL || PACKAGING)) { // @phpstan-ignore-line
|
||||
$message = 'Unable to run as root (run this command as a regular user)';
|
||||
if (PHP_SAPI === 'cli') {
|
||||
echo "[ERROR] $message\n";
|
||||
die(255);
|
||||
);
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
new VarDumpInstance(varDumpHtml());
|
||||
}
|
||||
require_once __DIR__ . '/register-handlers.php';
|
||||
$posix_getuid = function_exists('posix_getuid')
|
||||
? posix_getuid()
|
||||
: 'unknown';
|
||||
} catch (Throwable $e) {
|
||||
$error = sprintf(
|
||||
'[CHEVERETO LOAD ERROR] %s: %s %s',
|
||||
$e::class,
|
||||
$e->getMessage(),
|
||||
$e->getFile() . ':' . $e->getLine()
|
||||
);
|
||||
error_log($error);
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
throw new RuntimeException(
|
||||
message($message)
|
||||
);
|
||||
echo 'An error occurred while loading Chevereto.' . PHP_EOL;
|
||||
exit(255);
|
||||
}
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
|
||||
define('CHEVERETO_PHP_VERSION_REQUIRED', '8.1.28');
|
||||
|
||||
if (version_compare(PHP_VERSION, CHEVERETO_PHP_VERSION_REQUIRED, '<')) {
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(503);
|
||||
}
|
||||
echo 'This server is currently running PHP ' . PHP_VERSION . ' and Chevereto needs at least PHP 8.0.0 to run.' . PHP_EOL;
|
||||
die(255);
|
||||
echo 'This server is running PHP '
|
||||
. PHP_VERSION
|
||||
. ' and Chevereto needs at least PHP '
|
||||
. CHEVERETO_PHP_VERSION_REQUIRED
|
||||
. PHP_EOL;
|
||||
exit(255);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/loader.php';
|
||||
|
||||
@@ -12,48 +12,159 @@
|
||||
use Chevere\ThrowableHandler\Documents\ConsoleDocument;
|
||||
use Chevere\ThrowableHandler\Documents\HtmlDocument;
|
||||
use Chevere\ThrowableHandler\Documents\PlainDocument;
|
||||
use function Chevere\ThrowableHandler\throwableHandler;
|
||||
use Chevere\ThrowableHandler\ThrowableHandler;
|
||||
use function Chevere\Writer\writers;
|
||||
use function Chevere\Xr\throwableHandler as XrThrowableHandler;
|
||||
use Chevere\VarDump\Formats\HtmlFormat;
|
||||
use Chevere\VarDump\Formats\PlainFormat;
|
||||
use Chevere\VarDump\Interfaces\FormatInterface;
|
||||
use Chevere\VarDump\Outputs\HtmlOutput;
|
||||
use Chevere\VarDump\Outputs\PlainOutput;
|
||||
use Chevere\VarDump\VarDump;
|
||||
use Chevereto\Config\Config;
|
||||
use function Chevere\ThrowableHandler\throwableHandler;
|
||||
use function Chevere\Writer\writers;
|
||||
use function Chevere\xrDebug\PHP\throwableHandler as XrDebugThrowableHandler;
|
||||
use function Chevereto\Legacy\isDebug;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\files;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\post;
|
||||
use function Chevereto\Vars\server;
|
||||
|
||||
set_error_handler(ThrowableHandler::ERROR_AS_EXCEPTION);
|
||||
class HeadlessHtmlOutput extends HtmlOutput
|
||||
{
|
||||
public function prepare(): void
|
||||
{
|
||||
$this->writer()->write(
|
||||
'<style>' . preg_replace('/\s+/', ' ', self::CSS) . '</style>'
|
||||
);
|
||||
$this->writer()->write(
|
||||
'<pre class="chv-dump">'
|
||||
);
|
||||
}
|
||||
|
||||
public function writeCallerFile(FormatInterface $format): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
class HeadlessPlainOutput extends PlainOutput
|
||||
{
|
||||
public function prepare(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function finalize(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function writeCallerFile(FormatInterface $format): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
set_error_handler(ThrowableHandler::ERROR_AS_EXCEPTION); // @phpstan-ignore-line
|
||||
register_shutdown_function(ThrowableHandler::SHUTDOWN_ERROR_AS_EXCEPTION);
|
||||
set_exception_handler(function (Throwable $throwable) {
|
||||
$throwableHandler = throwableHandler($throwable);
|
||||
$extra = '';
|
||||
$publicHandler = throwableHandler($throwable);
|
||||
$namespace = env()['CHEVERETO_ID_HANDLE']
|
||||
?? false;
|
||||
if ($namespace) {
|
||||
$publicHandler = $publicHandler
|
||||
->withId($namespace . $publicHandler->id());
|
||||
}
|
||||
if (PHP_SAPI === 'cli') {
|
||||
$docInternal = new ConsoleDocument($throwableHandler);
|
||||
$docInternal = new ConsoleDocument($publicHandler);
|
||||
$parameters = [];
|
||||
} else {
|
||||
$docInternal = new PlainDocument($throwableHandler);
|
||||
if (!headers_sent()) {
|
||||
if (! headers_sent()) {
|
||||
http_response_code(500);
|
||||
}
|
||||
$isDebug = isDebug();
|
||||
|
||||
try {
|
||||
$debugLevel = Config::system()->debugLevel();
|
||||
} catch (Throwable) {
|
||||
$debugLevel = (int) ($_ENV['CHEVERETO_DEBUG_LEVEL'] ?? 1);
|
||||
}
|
||||
|
||||
$doDebug = in_array($debugLevel, [2, 3], true) || isDebug();
|
||||
$publicHandler = $publicHandler->withIsDebug($doDebug);
|
||||
$internalHandler = $publicHandler->withIsDebug(true);
|
||||
$method = server()['REQUEST_METHOD'] ?? '';
|
||||
$uri = server()['REQUEST_URI'] ?? '';
|
||||
$uri = strtok($uri, '?');
|
||||
$internalHandler = $internalHandler->withPutExtra('URI', $uri);
|
||||
$internalHandler = $internalHandler->withPutExtra('Method', $method);
|
||||
$extra .= xrDebugExtraSection('URI', $uri);
|
||||
$extra .= xrDebugExtraSection('Method', $method);
|
||||
$parameters = [
|
||||
'POST' => post(),
|
||||
'GET' => get(),
|
||||
'FILES' => files(),
|
||||
];
|
||||
$parameters = array_filter($parameters, fn ($value) => $value !== []);
|
||||
if ($parameters !== []) {
|
||||
$parametersHtml = (new VarDump(
|
||||
new HtmlFormat(),
|
||||
new HeadlessHtmlOutput()
|
||||
))
|
||||
->withVariables(...$parameters)
|
||||
->export();
|
||||
$internalHandler = $internalHandler
|
||||
->withPutExtra('Parameters', $parametersHtml);
|
||||
$extra .= xrDebugExtraSection('Parameters', $parametersHtml);
|
||||
}
|
||||
$docPublic = new HtmlDocument(
|
||||
$throwableHandler->withIsDebug(
|
||||
in_array($debugLevel, [2, 3]) || $isDebug
|
||||
)
|
||||
$doDebug ? $internalHandler : $publicHandler
|
||||
);
|
||||
writers()->output()
|
||||
->write($docPublic->__toString() . "\n");
|
||||
}
|
||||
writers()->error()
|
||||
->write($docInternal->__toString() . "\n\n");
|
||||
$internalHandler = $internalHandler ?? $publicHandler;
|
||||
if ($parameters !== []) {
|
||||
$parametersPlain = (new VarDump(
|
||||
new PlainFormat(),
|
||||
new HeadlessPlainOutput()
|
||||
))
|
||||
->withVariables(...$parameters)
|
||||
->export();
|
||||
$internalHandler = $internalHandler
|
||||
->withPutExtra('Parameters', $parametersPlain);
|
||||
if (! isset($parametersHtml)) {
|
||||
$extra .= xrDebugExtraSection('Parameters', $parametersPlain);
|
||||
}
|
||||
}
|
||||
$docLogs = new PlainDocument($internalHandler);
|
||||
$logMessage = '[' . $publicHandler->id() . '] '
|
||||
. $docLogs->__toString()
|
||||
. "\n\n";
|
||||
|
||||
XrThrowableHandler(
|
||||
$throwable,
|
||||
<<<HTML
|
||||
<div class="throwable-message">Incident ID: {$throwableHandler->id()}</div>
|
||||
HTML
|
||||
);
|
||||
die(255);
|
||||
try {
|
||||
$errorLog = ini_get('error_log');
|
||||
$fp = fopen($errorLog, 'a');
|
||||
fwrite($fp, $logMessage);
|
||||
fclose($fp);
|
||||
} catch (Throwable) {
|
||||
if (PHP_SAPI === 'cli') {
|
||||
error_log($logMessage);
|
||||
} else {
|
||||
writers()->error()->write($logMessage);
|
||||
}
|
||||
}
|
||||
$extra .= <<<HTML
|
||||
<div class="throwable-message"><b>Incident {$publicHandler->id()}</b></div>
|
||||
<div class="throwable-message"><b>Backtrace</b></div>
|
||||
HTML;
|
||||
XrDebugThrowableHandler($throwable, $extra);
|
||||
exit(255);
|
||||
});
|
||||
|
||||
function xrDebugExtraSection(string $title, string $contents)
|
||||
{
|
||||
return <<<HTML
|
||||
<div class="throwable-message">
|
||||
<b>{$title}</b>
|
||||
<div>{$contents}</div>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,8 @@
|
||||
*/
|
||||
|
||||
use Chevereto\Config\Config;
|
||||
use function Chevereto\Legacy\badgePaid;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Fonts;
|
||||
use Chevereto\Legacy\Classes\Image;
|
||||
use Chevereto\Legacy\Classes\IpBan;
|
||||
use Chevereto\Legacy\Classes\L10n;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
@@ -21,20 +19,26 @@ use Chevereto\Legacy\Classes\Page;
|
||||
use Chevereto\Legacy\Classes\Palettes;
|
||||
use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\Tag;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\badgePaid;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
use function Chevereto\Legacy\editionCombo;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\is_route_available;
|
||||
use function Chevereto\Legacy\G\is_url;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\G\set_status_header;
|
||||
use function Chevereto\Legacy\get_enabled_languages;
|
||||
use function Chevereto\Legacy\getIdFromURLComponent;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\getSystemNotices;
|
||||
use function Chevereto\Legacy\getVariable;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Legacy\headersResetCache;
|
||||
use function Chevereto\Legacy\is_max_invalid_request;
|
||||
use function Chevereto\Vars\cookie;
|
||||
use function Chevereto\Vars\env;
|
||||
@@ -43,30 +47,65 @@ use function Chevereto\Vars\server;
|
||||
use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
|
||||
if (Settings::get('chevereto_version_installed') === null) {
|
||||
if (cheveretoVersionInstalled() === '') {
|
||||
new Handler(
|
||||
loadTemplate: !REPL, // @phpstan-ignore-line
|
||||
loadTemplate: ! REPL, // @phpstan-ignore-line
|
||||
before: function ($handler) {
|
||||
headersNoCache();
|
||||
if ($handler->request_array()[0] !== 'install') {
|
||||
redirect('install');
|
||||
redirect('install', 302);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
$bannedIp = IpBan::getSingle();
|
||||
if ($bannedIp !== []) {
|
||||
is_url($bannedIp['message'])
|
||||
? redirect($bannedIp['message'])
|
||||
: (
|
||||
die(empty($bannedIp['message'])
|
||||
? _s('You have been forbidden to use this website.')
|
||||
: $bannedIp['message']
|
||||
)
|
||||
);
|
||||
headersNoCache();
|
||||
// TODO: Cache until ban expires
|
||||
if (is_url($bannedIp['message'] ?? false)) {
|
||||
redirect($bannedIp['message'], 301);
|
||||
} else {
|
||||
$exitMessage = $bannedIp['message'] ?? '';
|
||||
$exitMessage = match ($exitMessage) {
|
||||
'' => _s('You have been forbidden to use this website.'),
|
||||
default => $bannedIp['message'],
|
||||
};
|
||||
exit($exitMessage);
|
||||
}
|
||||
}
|
||||
$hook_before = function (Handler $handler) {
|
||||
header('Permissions-Policy: unload=()');
|
||||
header('Permissions-Policy: interest-cohort=()');
|
||||
header("Content-Security-Policy: frame-ancestors 'none'");
|
||||
$exitEarlyRoutes = [
|
||||
'webmanifest',
|
||||
];
|
||||
$doNotCacheRoutes = [
|
||||
'login',
|
||||
'signup',
|
||||
'logout',
|
||||
'account',
|
||||
'connect',
|
||||
'json',
|
||||
'api',
|
||||
'captcha-verify',
|
||||
'oembed',
|
||||
'upload',
|
||||
'dashboard',
|
||||
'install',
|
||||
'settings',
|
||||
'redirect',
|
||||
];
|
||||
$cache_ttl = (int) max(0, getSetting('cache_ttl') ?? 0);
|
||||
if (in_array($handler->request_array()[0], $doNotCacheRoutes, true)) {
|
||||
headersNoCache();
|
||||
} elseif ($cache_ttl > 0) {
|
||||
headersResetCache();
|
||||
header("Cache-Control: private, max-age={$cache_ttl}");
|
||||
}
|
||||
if (in_array($handler->request_array()[0], $exitEarlyRoutes, true)) {
|
||||
return;
|
||||
}
|
||||
$failed_access_requests = RequestLog::getCounts(['login', 'signup'], 'fail');
|
||||
if (is_max_invalid_request($failed_access_requests['day'])) {
|
||||
set_status_header(403);
|
||||
@@ -81,13 +120,14 @@ $hook_before = function (Handler $handler) {
|
||||
set_status_header(403);
|
||||
}
|
||||
if (sessionVar()->hasKey('challenge_two_factor')
|
||||
&& !in_array($handler->getRoutePath(), ['account/two-factor', 'captcha-verify', 'logout'])
|
||||
&& ! in_array($handler->getRoutePath(), ['account/two-factor', 'captcha-verify', 'logout'], true)
|
||||
&& $handler->request_array()[0] !== 'page'
|
||||
) {
|
||||
redirect('account/two-factor');
|
||||
) {
|
||||
headersNoCache();
|
||||
redirect('account/two-factor', 302);
|
||||
}
|
||||
}
|
||||
if (!getSetting('language_chooser_enable')) {
|
||||
if (! getSetting('language_chooser_enable')) {
|
||||
$user_lang = getSetting('default_language');
|
||||
}
|
||||
new L10n(
|
||||
@@ -96,25 +136,31 @@ $hook_before = function (Handler $handler) {
|
||||
? false
|
||||
: getSetting('auto_language')
|
||||
);
|
||||
if (http_response_code() == 403) {
|
||||
die();
|
||||
if (http_response_code() === 403) {
|
||||
headersNoCache();
|
||||
exit();
|
||||
}
|
||||
if ($handler->request_array()[0] !== 'api'
|
||||
&& Settings::get('enable_uploads_url') && !Login::isAdmin()) {
|
||||
&& Settings::get('enable_uploads_url') && ! Login::isAdmin()) {
|
||||
Settings::setValue('enable_uploads_url', 0);
|
||||
}
|
||||
if (isset(get()['lang']) && array_key_exists(get()['lang'], get_enabled_languages())) {
|
||||
if (Login::isLoggedUser() && Login::getUser()['language'] !== get()['lang']) {
|
||||
User::update(Login::getUser()['id'], ['language' => get()['lang']]);
|
||||
}
|
||||
if (isset(get()['lang'])
|
||||
&& array_key_exists(get()['lang'], get_enabled_languages())
|
||||
) {
|
||||
L10n::setCookieLang(get()['lang']);
|
||||
L10n::processTranslation(get()['lang']);
|
||||
define('PUSH_LANG', get()['lang']);
|
||||
}
|
||||
if (array_key_exists('agree-consent', get())) {
|
||||
setcookie('AGREE_CONSENT', "1", time() + (60 * 60 * 24 * 30), Config::host()->hostnamePath());
|
||||
setcookie(
|
||||
'AGREE_CONSENT',
|
||||
'1',
|
||||
time() + (60 * 60 * 24 * 30),
|
||||
Config::host()->hostnamePath()
|
||||
);
|
||||
sessionVar()->put('agree-consent', true);
|
||||
redirect(get_current_url(true, ['agree-consent']));
|
||||
headersNoCache();
|
||||
redirect(get_current_url(true, ['agree-consent']), 302);
|
||||
}
|
||||
$base = $handler::baseRequest();
|
||||
parse_str(server()['QUERY_STRING'] ?? '', $querystr);
|
||||
@@ -128,11 +174,11 @@ $hook_before = function (Handler $handler) {
|
||||
$handler::setCond('manager', Login::isManager());
|
||||
$showContentManager = Login::isAdmin() || Login::isManager();
|
||||
$handler::setCond('content_manager', $showContentManager);
|
||||
$allowed_nsfw_flagging = !getSetting('image_lock_nsfw_editing');
|
||||
$allowed_nsfw_flagging = ! getSetting('image_lock_nsfw_editing');
|
||||
if ($handler::cond('content_manager')) {
|
||||
$moderateLink = get_base_url('moderate');
|
||||
$moderateLabel = _s('Moderate');
|
||||
if (!in_array('pro', editionCombo()[env()['CHEVERETO_EDITION']])) {
|
||||
if (! in_array('pro', editionCombo()[env()['CHEVERETO_EDITION']], true)) {
|
||||
if ((bool) env()['CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES']) {
|
||||
$moderateLink = 'https://chevereto.com/pricing';
|
||||
$moderateLabel .= ' ' . badgePaid('pro');
|
||||
@@ -146,18 +192,18 @@ $hook_before = function (Handler $handler) {
|
||||
}
|
||||
$handler::setCond('show_content_manager', $showContentManager);
|
||||
$handler::setCond('allowed_nsfw_flagging', $allowed_nsfw_flagging);
|
||||
$handler::setCond('maintenance', getSetting('maintenance') and !Login::isAdmin());
|
||||
$handler::setCond('maintenance', getSetting('maintenance') and ! Login::isAdmin());
|
||||
$handler::setCond(
|
||||
'show_consent_screen',
|
||||
$base !== 'api' && (
|
||||
getSetting('enable_consent_screen')
|
||||
? !(Login::getUser() || isset(session()['agree-consent']) || isset(cookie()['AGREE_CONSENT']))
|
||||
? ! (Login::getUser() || isset(session()['agree-consent']) || isset(cookie()['AGREE_CONSENT']))
|
||||
: false
|
||||
)
|
||||
);
|
||||
$handler::setCond('captcha_needed', getSetting('captcha') && getSetting('captcha_threshold') == 0);
|
||||
$handler::setCond('show_header', !($handler::cond('maintenance') || $handler::cond('show_consent_screen')));
|
||||
$handler::setCond('show_notifications', getSetting('website_mode') == 'community' && (getSetting('enable_followers') || getSetting('enable_likes')));
|
||||
$handler::setCond('captcha_needed', getSetting('captcha') && getSetting('captcha_threshold') === 0);
|
||||
$handler::setCond('show_header', ! ($handler::cond('maintenance') || $handler::cond('show_consent_screen')));
|
||||
$handler::setCond('show_notifications', getSetting('website_mode') === 'community' && (getSetting('enable_followers') || getSetting('enable_likes')));
|
||||
$handler::setCond('allowed_to_delete_content', Login::isAdmin() || getSetting('enable_user_content_delete'));
|
||||
$handler::setVar('canonical', null);
|
||||
$palettes = new Palettes();
|
||||
@@ -166,7 +212,7 @@ $hook_before = function (Handler $handler) {
|
||||
$handler::setVar('fonts', $fonts);
|
||||
$fontId = intval(getSetting('theme_font') ?? 0);
|
||||
$handler::setVar('theme_font', $fontId);
|
||||
if (in_array($handler->request_array()[0], ['login', 'signup', 'account'])) {
|
||||
if (in_array($handler->request_array()[0], ['login', 'signup', 'account'], true)) {
|
||||
$paletteId = 0;
|
||||
} else {
|
||||
$paletteId = Login::isLoggedUser()
|
||||
@@ -180,14 +226,21 @@ $hook_before = function (Handler $handler) {
|
||||
}
|
||||
$handler::setVar('theme_palette', $paletteId);
|
||||
$handler::setVar('theme_palette_handle', $theme_palette_handle);
|
||||
if ($handler::cond('maintenance') && $handler->request_array()[0] == 'dashboard') {
|
||||
redirect('login');
|
||||
if ($handler::cond('maintenance')
|
||||
&& $handler->request_array()[0] === 'dashboard') {
|
||||
headersNoCache();
|
||||
redirect('login', 302);
|
||||
}
|
||||
$langLinks = [];
|
||||
$langToggleUrl = get_current_url(true, ['lang']);
|
||||
parse_str(server()['QUERY_STRING'] ?? '', $qs);
|
||||
unset($qs['lang']);
|
||||
$qs = http_build_query($qs);
|
||||
$langLinks['x-default'] = [
|
||||
'hreflang' => 'x-default',
|
||||
'name' => 'x-default',
|
||||
'url' => get_public_url($langToggleUrl),
|
||||
];
|
||||
$langToggleUrl = rtrim($langToggleUrl, '/') . ($qs ? '&' : '/?') . 'lang=';
|
||||
foreach (get_enabled_languages() as $k => $v) {
|
||||
$hreflang = strtolower($k);
|
||||
@@ -195,7 +248,7 @@ $hook_before = function (Handler $handler) {
|
||||
$langLinks[$k] = [
|
||||
'hreflang' => $hreflang,
|
||||
'name' => $v['name'],
|
||||
'url' => $langUrl,
|
||||
'url' => get_public_url($langUrl),
|
||||
];
|
||||
}
|
||||
$handler::setVar('langLinks', $langLinks);
|
||||
@@ -210,46 +263,46 @@ $hook_before = function (Handler $handler) {
|
||||
$consent_accept_url
|
||||
);
|
||||
}
|
||||
if (!Login::getUser()) {
|
||||
if (! Login::getUser()) {
|
||||
if (getSetting('captcha') && $failed_access_requests['day'] >= getSetting('captcha_threshold')) {
|
||||
$handler::setCond('captcha_needed', true);
|
||||
}
|
||||
}
|
||||
if (getSetting('website_mode') == 'personal') {
|
||||
if (getSetting('website_mode') === 'personal') {
|
||||
$userMapPaths = ['search'];
|
||||
$userMapPaths[] = getSetting('user_profile_view') == 'files'
|
||||
$userMapPaths[] = getSetting('user_profile_view') === 'files'
|
||||
? 'albums'
|
||||
: 'files';
|
||||
if ($handler->request_array()[0] == '/'
|
||||
&& getSetting('website_mode_personal_routing') == '/'
|
||||
&& in_array(key($querystr), ['random'])
|
||||
if ($handler->request_array()[0] === '/'
|
||||
&& getSetting('website_mode_personal_routing') === '/'
|
||||
&& in_array(key($querystr), ['random'], true)
|
||||
) {
|
||||
$handler->mapRoute('index');
|
||||
} elseif ($handler->request_array()[0] == 'search'
|
||||
&& in_array($handler->request_array()[1] ?? [], ['images', 'albums', 'users'])
|
||||
} elseif ($handler->request_array()[0] === 'search'
|
||||
&& in_array($handler->request_array()[1] ?? [], ['images', 'albums', 'users'], true)
|
||||
) {
|
||||
$handler->mapRoute('search');
|
||||
} elseif ($handler->request_array()[0] == getSetting('website_mode_personal_routing')
|
||||
|| (getSetting('website_mode_personal_routing') == '/'
|
||||
&& in_array($handler->request_array()[0], $userMapPaths))
|
||||
} elseif ($handler->request_array()[0] === getSetting('website_mode_personal_routing')
|
||||
|| (getSetting('website_mode_personal_routing') === '/'
|
||||
&& in_array($handler->request_array()[0], $userMapPaths, true))
|
||||
) {
|
||||
$handler->mapRoute('user', [
|
||||
'id' => getSetting('website_mode_personal_uid'),
|
||||
]);
|
||||
}
|
||||
if ($handler->request_array()[0] == '/'
|
||||
&& !in_array(key($querystr), ['random', 'lang'])
|
||||
&& !$handler::cond('mapped_route')
|
||||
if ($handler->request_array()[0] === '/'
|
||||
&& ! in_array(key($querystr), ['random', 'lang'], true)
|
||||
&& ! $handler::cond('mapped_route')
|
||||
) {
|
||||
$personal_mode_user = User::getSingle(getSetting('website_mode_personal_uid'));
|
||||
if ($personal_mode_user !== []) {
|
||||
if (Settings::get('homepage_cta_html') == null) {
|
||||
if (Settings::get('homepage_cta_html') === null) {
|
||||
Settings::setValue('homepage_cta_html', _s('View all my images'));
|
||||
}
|
||||
if (Settings::get('homepage_title_html') == null) {
|
||||
if (Settings::get('homepage_title_html') === null) {
|
||||
Settings::setValue('homepage_title_html', $personal_mode_user['name']);
|
||||
}
|
||||
if (Settings::get('homepage_paragraph_html') == null) {
|
||||
if (Settings::get('homepage_paragraph_html') === null) {
|
||||
Settings::setValue('homepage_paragraph_html', _s('Feel free to browse and discover all my shared images and albums.'));
|
||||
}
|
||||
if (Settings::get('homepage_cta_fn') !== 'cta-link') {
|
||||
@@ -262,13 +315,13 @@ $hook_before = function (Handler $handler) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($base !== 'index' and !is_route_available($handler->request_array()[0])) {
|
||||
if ($base !== 'index' and ! is_route_available($handler->request_array()[0])) {
|
||||
$mapTo = getSetting('root_route');
|
||||
$handler->mapRoute($mapTo);
|
||||
}
|
||||
}
|
||||
$virtualizable_routes = ['image', 'album', 'user'];
|
||||
if (in_array($handler->request_array()[0], $virtualizable_routes)) {
|
||||
$virtual_routes = ['image', 'album', 'user', 'video', 'audio'];
|
||||
if (in_array($handler->request_array()[0], $virtual_routes, true)) {
|
||||
$virtual_route = getSetting('route_' . $handler->request_array()[0]);
|
||||
if ($handler->request_array()[0] !== $virtual_route) {
|
||||
$virtualized_url = str_replace(
|
||||
@@ -276,21 +329,21 @@ $hook_before = function (Handler $handler) {
|
||||
get_base_url($virtual_route),
|
||||
get_current_url()
|
||||
);
|
||||
redirect($virtualized_url);
|
||||
redirect($virtualized_url, 301);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($base !== 'index' && !is_route_available($handler->request_array()[0])) {
|
||||
foreach ($virtualizable_routes as $k) {
|
||||
if ($handler->request_array()[0] == getSetting('route_' . $k)) {
|
||||
if ($base !== 'index' && ! is_route_available($handler->request_array()[0])) {
|
||||
foreach ($virtual_routes as $k) {
|
||||
if ($handler->request_array()[0] === getSetting('route_' . $k)) {
|
||||
$handler->mapRoute($k);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getSetting('website_privacy_mode') == 'private' && !Login::getUser()) {
|
||||
if (getSetting('website_privacy_mode') === 'private' && ! Login::getUser()) {
|
||||
$allowed_requests = ['api', 'login', 'logout', 'page', 'account', 'connect', 'json', 'captcha-verify'];
|
||||
foreach ($virtualizable_routes as $v) {
|
||||
foreach ($virtual_routes as $v) {
|
||||
$v = getSetting('route_' . $v);
|
||||
if (isset($v)) {
|
||||
$allowed_requests[] = $v;
|
||||
@@ -299,13 +352,28 @@ $hook_before = function (Handler $handler) {
|
||||
if (getSetting('enable_signups')) {
|
||||
$allowed_requests[] = 'signup';
|
||||
}
|
||||
if (!in_array($handler->request_array()[0], $allowed_requests)) {
|
||||
redirect('login');
|
||||
if (! in_array($handler->request_array()[0], $allowed_requests, true)) {
|
||||
headersNoCache();
|
||||
redirect('login', 302);
|
||||
}
|
||||
}
|
||||
$handler::setCond('private_gate', getSetting('website_privacy_mode') == 'private' and !Login::getUser());
|
||||
$handler::setCond('forced_private_mode', (getSetting('website_privacy_mode') == 'private' and getSetting('website_content_privacy_mode') !== 'default'));
|
||||
$handler::setCond('explore_enabled', $handler::cond('content_manager') ?: (getSetting('website_explore_page') ? ((bool) Login::isLoggedUser() ?: getSetting('website_explore_page_guest')) : false));
|
||||
$handler::setCond(
|
||||
'private_gate',
|
||||
getSetting('website_privacy_mode') === 'private'
|
||||
&& ! Login::getUser()
|
||||
);
|
||||
$handler::setCond(
|
||||
'forced_private_mode',
|
||||
getSetting('website_privacy_mode') === 'private'
|
||||
&& getSetting('website_content_privacy_mode') !== 'default'
|
||||
);
|
||||
$handler::setCond(
|
||||
'explore_enabled',
|
||||
$handler::cond('content_manager')
|
||||
?: (getSetting('website_explore_page')
|
||||
? ((bool) Login::isLoggedUser() ?: getSetting('website_explore_page_guest'))
|
||||
: false)
|
||||
);
|
||||
$handler::setCond(
|
||||
'search_enabled',
|
||||
$handler::cond('content_manager')
|
||||
@@ -316,47 +384,60 @@ $hook_before = function (Handler $handler) {
|
||||
);
|
||||
$handler::setCond(
|
||||
'random_enabled',
|
||||
$handler::cond('content_manager')
|
||||
?: (
|
||||
getSetting('website_random')
|
||||
&& (Login::isLoggedUser() ?: getSetting('website_random_guest'))
|
||||
)
|
||||
getSetting('website_random')
|
||||
&& (Login::isLoggedUser() ?: getSetting('website_random_guest'))
|
||||
);
|
||||
$moderate_uploads = false;
|
||||
switch (getSetting('moderate_uploads')) {
|
||||
case 'all':
|
||||
$moderate_uploads = !$handler::cond('content_manager');
|
||||
$moderate_uploads = ! $handler::cond('content_manager');
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'guest':
|
||||
$moderate_uploads = !Login::isLoggedUser();
|
||||
$moderate_uploads = ! Login::isLoggedUser();
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$handler::setCond('moderate_uploads', $moderate_uploads);
|
||||
$categories = [];
|
||||
if ($handler::cond('explore_enabled') || $base == 'dashboard') {
|
||||
$tags_top = [];
|
||||
if ($handler::cond('explore_enabled') || $base === 'dashboard') {
|
||||
try {
|
||||
$categories_db = DB::queryFetchAll('SELECT * FROM ' . DB::getTable('categories') . ' ORDER BY category_name ASC;');
|
||||
if (count($categories_db) > 0) {
|
||||
foreach ($categories_db as $k => $v) {
|
||||
$key = $v['category_id'];
|
||||
$categories[$key] = $v;
|
||||
$categories[$key]['category_url'] = get_base_url('category/' . $v['category_url_key']);
|
||||
$categories[$key] = DB::formatRow($categories[$key]);
|
||||
}
|
||||
$categories_db = DB::queryFetchAll(
|
||||
'SELECT * FROM '
|
||||
. DB::getTable('categories')
|
||||
. ' ORDER BY category_name ASC;'
|
||||
);
|
||||
foreach ($categories_db as $k => $v) {
|
||||
$key = $v['category_id'];
|
||||
$categories[$key] = $v;
|
||||
$categories[$key]['category_url'] = get_base_url('category/' . $v['category_url_key']);
|
||||
$categories[$key] = DB::formatRow($categories[$key]);
|
||||
}
|
||||
} catch (Throwable) {
|
||||
}
|
||||
|
||||
try {
|
||||
$tagsTable = DB::getTable('tags');
|
||||
$tags_db = DB::queryFetchAll(
|
||||
<<<MYSQL
|
||||
SELECT t.tag_name name, t.tag_id id, t.tag_files files, t.tag_views views
|
||||
FROM `{$tagsTable}` t
|
||||
ORDER BY `tag_files` DESC, `tag_name` ASC
|
||||
LIMIT 30;
|
||||
|
||||
MYSQL
|
||||
);
|
||||
foreach ($tags_db as $k => $v) {
|
||||
$tag = array_merge($v, Tag::row($v['name']));
|
||||
$tags_top[] = $tag;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
}
|
||||
}
|
||||
if ($handler::cond('explore_enabled')
|
||||
&& $categories === []
|
||||
&& !(bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
) {
|
||||
$handler::setCond('explore_enabled', false);
|
||||
}
|
||||
$handler::setVar('categories', $categories);
|
||||
$explore_semantics = [
|
||||
$handler::setVar('tags_top', $tags_top);
|
||||
$explore_discovery = [
|
||||
'recent' => [
|
||||
'label' => _s('Recent'),
|
||||
'icon' => 'fas fa-history',
|
||||
@@ -369,73 +450,126 @@ $hook_before = function (Handler $handler) {
|
||||
'label' => _s('Popular'),
|
||||
'icon' => 'fas fa-heart',
|
||||
],
|
||||
];
|
||||
$explore_content = [
|
||||
'images' => [
|
||||
'label' => _n('Image', 'Images', 20),
|
||||
'icon' => 'fas fa-image',
|
||||
],
|
||||
'videos' => [
|
||||
'label' => _s('Videos'),
|
||||
'label' => _n('Video', 'Videos', 20),
|
||||
'icon' => 'fas fa-video',
|
||||
],
|
||||
'animated' => [
|
||||
'label' => _s('Animated'),
|
||||
'icon' => 'fas fa-play',
|
||||
],
|
||||
'tags' => [
|
||||
'label' => _n('Tag', 'Tags', 20),
|
||||
'icon' => 'fas fa-tags',
|
||||
],
|
||||
'albums' => [
|
||||
'label' => _n('Album', 'Albums', 20),
|
||||
'icon' => 'fas fa-photo-film',
|
||||
],
|
||||
'users' => [
|
||||
'label' => _n('User', 'Users', 20),
|
||||
'icon' => 'fas fa-users',
|
||||
],
|
||||
];
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS']) {
|
||||
$explore_semantics = [];
|
||||
if (Login::isLoggedUser() && getSetting('enable_followers')) {
|
||||
$explore_discovery['following'] = [
|
||||
'label' => _s('Following'),
|
||||
'icon' => 'fas fa-rss',
|
||||
'url' => get_base_url('following'),
|
||||
];
|
||||
}
|
||||
if (!getSetting('enable_likes')) {
|
||||
unset($explore_semantics['popular']);
|
||||
if (! getSetting('enable_likes')) {
|
||||
unset($explore_discovery['popular']);
|
||||
}
|
||||
if (!in_array('gif', Image::getEnabledImageExtensions())) {
|
||||
unset($explore_semantics['animated']);
|
||||
foreach ($explore_discovery as $k => &$v) {
|
||||
$v['url'] = get_base_url('explore/' . $k);
|
||||
}
|
||||
foreach ($explore_semantics as $k => &$v) {
|
||||
foreach ($explore_content as $k => &$v) {
|
||||
$v['url'] = get_base_url('explore/' . $k);
|
||||
}
|
||||
unset($v);
|
||||
$handler::setVar('explore_semantics', $explore_semantics);
|
||||
if (version_compare(Settings::get('chevereto_version_installed'), '3.6.7', '>=')) {
|
||||
$pages_visible_db = Page::getAll(['is_active' => 1, 'is_link_visible' => 1], ['field' => 'sort_display', 'order' => 'ASC']);
|
||||
$pageHandle = version_compare(Settings::get('chevereto_version_installed'), '3.12.4', '>=') ? 'internal' : 'url_key';
|
||||
$handler::setVar('page_tos', Page::getSingle('tos', $pageHandle));
|
||||
$handler::setVar('page_privacy', Page::getSingle('privacy', $pageHandle));
|
||||
}
|
||||
$handler::setVar('explore_discovery', $explore_discovery);
|
||||
$handler::setVar('explore_content', $explore_content);
|
||||
$versionInstalled = cheveretoVersionInstalled();
|
||||
$pages_visible = [];
|
||||
if (version_compare($versionInstalled, '3.6.7', '>=')) {
|
||||
$pages_visible_db = Page::getAll(
|
||||
args: [
|
||||
'is_active' => '1',
|
||||
'is_link_visible' => '1',
|
||||
],
|
||||
sort: [
|
||||
'field' => 'sort_display',
|
||||
'order' => 'ASC',
|
||||
]
|
||||
);
|
||||
$handler::setVar('page_tos', $pages_visible_db['tos'] ?? null);
|
||||
$handler::setVar('page_privacy', $pages_visible_db['privacy'] ?? null);
|
||||
}
|
||||
if ((bool) env()['CHEVERETO_ENABLE_PAGES']) {
|
||||
foreach ($pages_visible_db as $k => $v) {
|
||||
if (!($v['is_active'] ?? false) && !($v['is_link_visible'] ?? false)) {
|
||||
foreach ($pages_visible_db ?? [] as $k => $v) {
|
||||
if (! ($v['is_active'] ?? false) && ! ($v['is_link_visible'] ?? false)) {
|
||||
continue;
|
||||
}
|
||||
$pages_visible[$v['id']] = $v;
|
||||
}
|
||||
if (getSetting('enable_plugin_route')) {
|
||||
$plugin_page = [
|
||||
'type' => 'link',
|
||||
'link_url' => get_base_url('plugin'),
|
||||
'icon' => 'fas fa-code',
|
||||
'title' => _s('Plugin'),
|
||||
'is_active' => 1,
|
||||
'is_link_visible' => 1,
|
||||
'attr_target' => '_self',
|
||||
'sort_display' => 999,
|
||||
];
|
||||
Page::fill($plugin_page);
|
||||
$pages_visible[] = $plugin_page;
|
||||
}
|
||||
}
|
||||
$api_page = [
|
||||
'type' => 'link',
|
||||
'link_url' => get_base_url('api-v1'),
|
||||
'icon' => 'fas fa-project-diagram',
|
||||
'title' => 'API',
|
||||
'is_active' => 1,
|
||||
'is_link_visible' => 1,
|
||||
'attr_target' => '_self',
|
||||
'sort_display' => -2,
|
||||
];
|
||||
Page::fill($api_page);
|
||||
$pages_visible[] = $api_page;
|
||||
if (getSetting('enable_plugin_route')) {
|
||||
$plugin_page = [
|
||||
'type' => 'link',
|
||||
'link_url' => get_base_url('plugin'),
|
||||
'icon' => 'fas fa-plug-circle-plus',
|
||||
'title' => _s('Plugin'),
|
||||
'is_active' => 1,
|
||||
'is_link_visible' => 1,
|
||||
'attr_target' => '_self',
|
||||
'sort_display' => -1,
|
||||
];
|
||||
Page::fill($plugin_page);
|
||||
$pages_visible[] = $plugin_page;
|
||||
}
|
||||
uasort($pages_visible, function ($a, $b) {
|
||||
return $a['sort_display'] - $b['sort_display'];
|
||||
});
|
||||
$handler::setVar('pages_link_visible', $pages_visible);
|
||||
$upload_enabled = Login::isAdmin() ?: getSetting('enable_uploads');
|
||||
$upload_allowed = $upload_enabled;
|
||||
if (!Login::getUser()) {
|
||||
if (!getSetting('guest_uploads') || getSetting('website_privacy_mode') == 'private' || $handler::cond('maintenance')) {
|
||||
if (! Login::getUser()) {
|
||||
if (! getSetting('guest_uploads') || getSetting('website_privacy_mode') === 'private' || $handler::cond('maintenance')) {
|
||||
$upload_allowed = false;
|
||||
}
|
||||
} elseif (!Login::isAdmin() && getSetting('website_mode') == 'personal' && getSetting('website_mode_personal_uid') !== Login::getUser()['id']) {
|
||||
} elseif (! Login::isAdmin() && getSetting('website_mode') === 'personal' && getSetting('website_mode_personal_uid') !== Login::getUser()['id']) {
|
||||
$upload_allowed = false;
|
||||
}
|
||||
if (!Login::getUser() && $upload_allowed && getSetting('upload_max_filesize_mb_guest')) {
|
||||
if ((! (bool) env()['CHEVERETO_ENABLE_LOCAL_STORAGE']) && getVariable('storages_active')->nullInt() === 0) {
|
||||
$upload_enabled = false;
|
||||
$upload_allowed = false;
|
||||
}
|
||||
if (! Login::getUser() && $upload_allowed && getSetting('upload_max_filesize_mb_guest')) {
|
||||
Settings::setValue('upload_max_filesize_mb_bak', getSetting('upload_max_filesize_mb'));
|
||||
Settings::setValue('upload_max_filesize_mb', getSetting('upload_max_filesize_mb_guest'));
|
||||
}
|
||||
if ($upload_allowed && in_array($handler->request_array()[0], ['login', 'signup', 'account'])) {
|
||||
if ($upload_allowed
|
||||
&& in_array($handler->request_array()[0], ['login', 'signup', 'account'], true)
|
||||
) {
|
||||
$upload_allowed = false;
|
||||
}
|
||||
$handler::setCond('upload_enabled', $upload_enabled); // System allows to upload?
|
||||
@@ -443,53 +577,53 @@ $hook_before = function (Handler $handler) {
|
||||
if ($handler::cond('maintenance') || $handler::cond('show_consent_screen')) {
|
||||
$handler::setCond('private_gate', true);
|
||||
$allowed_requests = ['login', 'account', 'connect', 'captcha-verify', 'oembed'];
|
||||
if (!in_array($handler->request_array()[0], $allowed_requests)) {
|
||||
if (! in_array($handler->request_array()[0], $allowed_requests, true)) {
|
||||
$handler->preventRoute($handler::cond('show_consent_screen') ? 'consent-screen' : 'maintenance');
|
||||
}
|
||||
}
|
||||
if ($handler->request_array()[0] == getSetting('route_image')) {
|
||||
$id = getIdFromURLComponent($handler->request()[0] ?? '');
|
||||
if ($id !== 0) {
|
||||
$image = Image::getSingle($id, false, true, $handler::var('logged_user'));
|
||||
$userNotBanned = ($image['user']['status'] ?? '') != 'banned';
|
||||
if ($image !== [] && $image['is_approved'] && $userNotBanned && !in_array($image['album']['privacy'] ?? '', ['private', 'custom'])) {
|
||||
$image_safe_html = safe_html($image);
|
||||
$handler::setVar('oembed', [
|
||||
'title' => ($image_safe_html['title'] ?? ($image_safe_html['name'] . '.' . $image['extension'])) . ' hosted at ' . getSetting('website_name'),
|
||||
'url' => $image['url_viewer']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$handler::setVar('system_notices', Login::isAdmin() ? getSystemNotices() : []);
|
||||
if (!in_array($handler->request_array()[0], ['login', 'signup', 'account', 'connect', 'logout', 'json', 'api', 'captcha-verify'])) {
|
||||
$excludeLastUrl = [
|
||||
'login',
|
||||
'signup',
|
||||
'account',
|
||||
'connect',
|
||||
'logout',
|
||||
'json',
|
||||
'api',
|
||||
'captcha-verify',
|
||||
'webmanifest',
|
||||
'tag-autocomplete',
|
||||
];
|
||||
if (! in_array($handler->request_array()[0], $excludeLastUrl, true)) {
|
||||
sessionVar()->put('last_url', get_current_url());
|
||||
}
|
||||
$detect = new Mobile_Detect();
|
||||
$isMobile = $detect->isMobile();
|
||||
$handler::setCond('mobile_device', (bool) $isMobile);
|
||||
$handler::setCond('show_viewer_zero', false);
|
||||
if ($handler->template() == 'request-denied') {
|
||||
$handler::setVar('doctitle', _s("Request denied") . ' (403) - ' . getSetting('website_name'));
|
||||
if ($handler->template() === 'request-denied') {
|
||||
$handler::setVar('doctitle', _s('Request denied') . ' (403) - ' . getSetting('website_name'));
|
||||
$handler->preventRoute('request-denied');
|
||||
}
|
||||
$handler::setVar('tos_privacy_agreement', _s('I agree to the %terms_link and %privacy_link', [
|
||||
'%terms_link' => '<a ' . ($handler::var('page_tos')['link_attr'] ?? '') . '>' . _s('terms') . '</a>',
|
||||
'%privacy_link' => '<a ' . ($handler::var('page_privacy')['link_attr'] ?? '') . '>' . _s('privacy policy') . '</a>'
|
||||
'%privacy_link' => '<a ' . ($handler::var('page_privacy')['link_attr'] ?? '') . '>' . _s('privacy policy') . '</a>',
|
||||
]));
|
||||
$poweredBySiteWide = (bool) env()['CHEVERETO_ENABLE_POWERED_BY_FOOTER_SITE_WIDE'];
|
||||
$show_powered_by_footer = $poweredBySiteWide
|
||||
?: ($handler->getRoutePath() === 'index' && getSetting('enable_powered_by'));
|
||||
if (in_array($handler->getRoutePath(false), ['settings', 'dashboard'])) {
|
||||
$show_powered_by_footer = false;
|
||||
$show_powered_by_footer = getSetting('enable_powered_by');
|
||||
if (array_key_exists('CHEVERETO_ENABLE_FORCE_POWERED_BY_FOOTER', env())) {
|
||||
if ((bool) env()['CHEVERETO_ENABLE_FORCE_POWERED_BY_FOOTER']) {
|
||||
$show_powered_by_footer = true;
|
||||
}
|
||||
}
|
||||
$handler::setCond('show_powered_by_footer', $show_powered_by_footer);
|
||||
};
|
||||
$hook_after = function (Handler $handler) {
|
||||
if (array_key_exists('deleted', get()) && in_array($handler->template(), ['user', 'album'])) {
|
||||
if (array_key_exists('deleted', get())
|
||||
&& in_array($handler->template(), ['user', 'album'], true)
|
||||
) {
|
||||
set_status_header(303);
|
||||
}
|
||||
if ($handler->template() == '404') {
|
||||
if ($handler->template() === '404') {
|
||||
if (sessionVar()->hasKey('last_url')) {
|
||||
sessionVar()->remove('last_url');
|
||||
}
|
||||
@@ -502,14 +636,19 @@ $hook_after = function (Handler $handler) {
|
||||
if (defined('PUSH_LANG')) {
|
||||
$handler::setVar('doctitle', $handler::var('doctitle') . ' (' . get_enabled_languages()[PUSH_LANG]['name'] . ')');
|
||||
}
|
||||
$handler::setVar('safe_html_website_name', safe_html(getSetting('website_name')));
|
||||
$handler::setVar('safe_html_website_name', getSetting('website_name', true));
|
||||
$handler::setVar('safe_html_doctitle', safe_html($handler::var('doctitle')));
|
||||
if ($handler::var('pre_doctitle')) {
|
||||
$handler::setVar('safe_html_pre_doctitle', safe_html($handler::var('pre_doctitle')));
|
||||
}
|
||||
$handler::setVar('safe_html_meta_description', safe_html($handler::var('meta_description')));
|
||||
if ($handler::var('meta_description')) {
|
||||
$handler::setVar('safe_html_meta_description', safe_html($handler::var('meta_description')));
|
||||
}
|
||||
if ($handler::var('meta_keywords')) {
|
||||
$handler::setVar('safe_html_meta_keywords', safe_html($handler::var('meta_keywords')));
|
||||
}
|
||||
sessionVar()->put('REQUEST_REFERER', get_current_url());
|
||||
header('X-Powered-By: Chevereto 4');
|
||||
};
|
||||
// @phpstan-ignore-next-line
|
||||
new Handler(loadTemplate: !REPL, before: $hook_before, after: $hook_after, );
|
||||
new Handler(loadTemplate: ! REPL, before: $hook_before, after: $hook_after);
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
*/
|
||||
|
||||
use Chevereto\Config\Config;
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use function Chevereto\Legacy\check_hashed_token;
|
||||
use Chevereto\Legacy\Classes\Confirmation;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
@@ -19,12 +17,14 @@ use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\TwoFactor;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use function Chevereto\Legacy\check_hashed_token;
|
||||
use function Chevereto\Legacy\decodeID;
|
||||
use function Chevereto\Legacy\G\datetime;
|
||||
use function Chevereto\Legacy\G\datetime_diff;
|
||||
use function Chevereto\Legacy\G\datetimegmt;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\generate_hashed_token;
|
||||
use function Chevereto\Legacy\get_email_body_str;
|
||||
@@ -43,73 +43,82 @@ return function (Handler $handler) {
|
||||
$handler->setTemplate('404');
|
||||
$route = $handler->requestArray()[0];
|
||||
$doing = $handler->request()[0] ?? false;
|
||||
if (!$doing || !in_array($doing, ['activate', 'password-reset', 'change-email-confirm', 'two-factor']) && $handler->isRequestLevel(3)) {
|
||||
if (! $doing
|
||||
|| ! in_array($doing, ['activate', 'password-reset', 'change-email-confirm', 'two-factor'], true)
|
||||
&& $handler->isRequestLevel(3)
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!Settings::get('enable_signups') && in_array($doing, ['awaiting-confirmation', 'activate', 'email-changed'])) {
|
||||
if (! Settings::get('enable_signups')
|
||||
&& in_array($doing, ['awaiting-confirmation', 'activate', 'email-changed'], true)
|
||||
) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
$loggedStatus = $logged_user['status'] ?? '';
|
||||
if (Login::isLoggedUser() && $doing !== 'email-needed' && $loggedStatus == 'awaiting-email') {
|
||||
redirect('account/email-needed');
|
||||
if (Login::isLoggedUser() && $doing !== 'email-needed' && $loggedStatus === 'awaiting-email') {
|
||||
redirect('account/email-needed', 302);
|
||||
}
|
||||
|
||||
switch ($doing) {
|
||||
case 'email-needed':
|
||||
if (Login::isLoggedUser() && $loggedStatus !== 'awaiting-email') {
|
||||
redirect($logged_user['url']);
|
||||
if (Login::isLoggedUser()) {
|
||||
if ($loggedStatus !== 'awaiting-email') {
|
||||
redirect($logged_user['url'], 302);
|
||||
}
|
||||
} else {
|
||||
redirect('login', 302);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'resend-activation':
|
||||
case 'activate':
|
||||
if (Login::isLoggedUser() && $loggedStatus !== 'awaiting-confirmation') {
|
||||
redirect($logged_user['url'] ?? '');
|
||||
redirect($logged_user['url'] ?? '', 302);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'two-factor':
|
||||
if (!Login::isLoggedUser()) {
|
||||
redirect('');
|
||||
if (! Login::isLoggedUser()) {
|
||||
redirect('login', 302);
|
||||
}
|
||||
if (!TwoFactor::hasFor($logged_user['id'])) {
|
||||
redirect('settings/security');
|
||||
if (! TwoFactor::hasFor($logged_user['id'])) {
|
||||
redirect('settings/security', 302);
|
||||
}
|
||||
if (!sessionVar()->hasKey('challenge_two_factor')) {
|
||||
redirect($logged_user['url'] ?? '');
|
||||
if (! sessionVar()->hasKey('challenge_two_factor')) {
|
||||
redirect($logged_user['url'] ?? '', 302);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
$captcha_needed = false;
|
||||
$request_to_db = [
|
||||
'activate' => 'account-activate',
|
||||
'change-email-confirm' => 'account-change-email',
|
||||
'email-needed' => 'account-email-needed',
|
||||
'password-forgot' => 'account-password-forgot',
|
||||
'password-reset' => 'account-password-forgot',
|
||||
'resend-activation' => 'account-activate',
|
||||
'activate' => 'account-activate',
|
||||
'email-needed' => 'account-email-needed',
|
||||
'change-email-confirm' => 'account-change-email',
|
||||
'two-factor' => 'account-two-factor',
|
||||
];
|
||||
$request_db_field = $request_to_db[$doing] ?? '';
|
||||
$pre_doctitles = [
|
||||
'awaiting-confirmation' => _s('Awaiting confirmation'),
|
||||
'email-changed' => _s('Email changed'),
|
||||
'email-needed' => _s('Add your email address'),
|
||||
'password-forgot' => _s('Forgot password?'),
|
||||
'password-reset' => _s('Reset password'),
|
||||
'resend-activation' => _s('Resend account activation'),
|
||||
'email-needed' => _s('Add your email address'),
|
||||
'awaiting-confirmation' => _s('Awaiting confirmation'),
|
||||
'two-factor' => _s('Two-factor authentication'),
|
||||
'email-changed' => _s('Email changed'),
|
||||
];
|
||||
$keysToCheck = $request_to_db;
|
||||
unset($keysToCheck['change-email-confirm']);
|
||||
$keysToCheck = array_keys($keysToCheck);
|
||||
if (in_array($doing, $keysToCheck)) {
|
||||
if (in_array($doing, $keysToCheck, true)) {
|
||||
$request_log = RequestLog::getCounts($request_db_field, 'fail');
|
||||
$captcha_needed = (getSetting('captcha') ?? false)
|
||||
? must_use_captcha($request_log['day'])
|
||||
@@ -119,9 +128,9 @@ return function (Handler $handler) {
|
||||
$is_error = false;
|
||||
$error_message = null;
|
||||
$input_errors = [];
|
||||
if ($captcha_needed && !empty($POST)) {
|
||||
if ($captcha_needed && ! empty($POST)) {
|
||||
$captcha = captcha_check();
|
||||
if (!$captcha->is_valid) {
|
||||
if (! $captcha->is_valid) {
|
||||
$is_error = true;
|
||||
$error_message = _s('%s says you are a robot', 'CAPTCHA');
|
||||
}
|
||||
@@ -130,33 +139,32 @@ return function (Handler $handler) {
|
||||
switch ($doing) {
|
||||
case 'password-forgot':
|
||||
case 'resend-activation':
|
||||
if ($doing == 'password-forgot' && $loggedStatus == 'valid' || $doing == 'resend-activation' && $loggedStatus == 'awaiting-confirmation') {
|
||||
if ($doing === 'password-forgot' && $loggedStatus === 'valid' || $doing === 'resend-activation' && $loggedStatus === 'awaiting-confirmation') {
|
||||
$POST['user-subject'] = $logged_user['username'];
|
||||
$is_error = false;
|
||||
}
|
||||
if ($POST !== [] && !$is_error) {
|
||||
if ($POST !== [] && ! $is_error) {
|
||||
$subject_type = filter_var($POST['user-subject'] ?? '', FILTER_VALIDATE_EMAIL)
|
||||
? 'email'
|
||||
: 'username';
|
||||
if (trim($POST['user-subject']) == '') {
|
||||
if (trim($POST['user-subject']) === '') {
|
||||
$is_error = true;
|
||||
$input_errors['user-subject'] = _s('Invalid Username/Email');
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
$user = User::getSingle($POST['user-subject'], $subject_type);
|
||||
if ($user !== []) {
|
||||
if (!filter_var($user['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if (! filter_var($user['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$error_message = _s("User doesn't have an email.");
|
||||
$is_error = true;
|
||||
}
|
||||
if ($doing == 'password-forgot') {
|
||||
if ($doing === 'password-forgot') {
|
||||
switch ($user['status']) {
|
||||
case 'banned':
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
case 'awaiting-email':
|
||||
case 'awaiting-confirmation':
|
||||
$is_error = true;
|
||||
@@ -178,11 +186,11 @@ return function (Handler $handler) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($handler->template() == '403') {
|
||||
if ($handler->template() === '403') {
|
||||
RequestLog::insert([
|
||||
'type' => $request_db_field,
|
||||
'result' => 'fail',
|
||||
'user_id' => $user['id']
|
||||
'user_id' => $user['id'],
|
||||
]);
|
||||
|
||||
return;
|
||||
@@ -191,15 +199,24 @@ return function (Handler $handler) {
|
||||
$is_error = true;
|
||||
$input_errors['user-subject'] = _s('Invalid Username/Email');
|
||||
}
|
||||
if (!$is_error) {
|
||||
$confirmation_db = Confirmation::get(['user_id' => $user['id'], 'type' => $request_db_field, 'status' => 'active'], ['field' => 'date', 'order' => 'desc'], 1);
|
||||
if (! $is_error) {
|
||||
$confirmation_db = Confirmation::get([
|
||||
'user_id' => $user['id'],
|
||||
'type' => $request_db_field,
|
||||
'status' => 'active',
|
||||
], [
|
||||
'field' => 'date',
|
||||
'order' => 'desc',
|
||||
], 1);
|
||||
if ($confirmation_db !== false) {
|
||||
$minute_diff = $confirmation_db['confirmation_date_gmt'] ? datetime_diff($confirmation_db['confirmation_date_gmt'], null, 'm') : 15 + 1;
|
||||
$minute_diff = $confirmation_db['confirmation_date_gmt']
|
||||
? datetime_diff($confirmation_db['confirmation_date_gmt'], null, 'm')
|
||||
: 15 + 1;
|
||||
if ($minute_diff < 15) { // Mimic for the already submitted
|
||||
$is_error = true;
|
||||
$is_process_done = false;
|
||||
$activation_email = $user['email'];
|
||||
if ($subject_type == 'username') { // We won't disclose this email address
|
||||
if ($subject_type === 'username') { // We won't disclose this email address
|
||||
$activation_email = preg_replace('/(?<=.).(?=.*@)/u', '*', $activation_email);
|
||||
$explode = explode('@', $activation_email);
|
||||
while (strlen($explode[0]) < 4) {
|
||||
@@ -210,11 +227,14 @@ return function (Handler $handler) {
|
||||
$handler::setVar('resend_activation_email', $activation_email);
|
||||
$error_message = _s('Allow up to 15 minutes for the email. You can try again later.');
|
||||
} else {
|
||||
Confirmation::delete(['user_id' => $user['id'], 'type' => $request_db_field]);
|
||||
Confirmation::delete([
|
||||
'user_id' => $user['id'],
|
||||
'type' => $request_db_field,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
$hashed_token = generate_hashed_token((int) $user['id']);
|
||||
$array_values = [
|
||||
'type' => $request_db_field,
|
||||
@@ -222,35 +242,34 @@ return function (Handler $handler) {
|
||||
'date_gmt' => datetimegmt(),
|
||||
'token_hash' => $hashed_token['hash'],
|
||||
];
|
||||
if (!isset($user['confirmation_id'])) {
|
||||
if (! isset($user['confirmation_id'])) {
|
||||
$array_values['user_id'] = $user['id'];
|
||||
$confirmation_db_query = Confirmation::insert($array_values);
|
||||
} else {
|
||||
$confirmation_db_query = Confirmation::update($user['confirmation_id'], $array_values);
|
||||
}
|
||||
if ($confirmation_db_query) {
|
||||
$recovery_link = get_public_url('account/' . ($doing == 'password-forgot' ? 'password-reset' : 'activate') . '/?token=' . $hashed_token['public_token_format']);
|
||||
$recovery_link = get_public_url('account/' . ($doing === 'password-forgot' ? 'password-reset' : 'activate') . '/?token=' . $hashed_token['public_token_format']);
|
||||
global $theme_mail;
|
||||
$theme_mail = [
|
||||
'user' => $user,
|
||||
'link' => $recovery_link,
|
||||
];
|
||||
if ($doing == 'password-forgot') {
|
||||
$mail['subject'] = _s('Reset your password at %s', getSettings()['website_name']);
|
||||
if ($doing === 'password-forgot') {
|
||||
$mail['subject'] = _s('Reset your password at %s', getSetting('website_name', true));
|
||||
} else {
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSetting('website_name', true));
|
||||
}
|
||||
$mail['message'] = get_email_body_str('mails/account-' . ($doing == 'password-forgot' ? 'password-reset' : 'confirm'));
|
||||
xr($mail);
|
||||
$mail['message'] = get_email_body_str('mails/account-' . ($doing === 'password-forgot' ? 'password-reset' : 'confirm'));
|
||||
if (send_mail($user['email'], $mail['subject'], $mail['message'])) {
|
||||
$is_process_done = true;
|
||||
}
|
||||
if ($doing == 'resend-activation') {
|
||||
if ($doing === 'resend-activation') {
|
||||
Login::setSignup([
|
||||
'status' => 'awaiting-confirmation',
|
||||
'email' => $user['email'],
|
||||
]);
|
||||
redirect('account/awaiting-confirmation');
|
||||
redirect('account/awaiting-confirmation', 302);
|
||||
}
|
||||
$handler::setVar('password_forgot_email', $user['email']);
|
||||
} else {
|
||||
@@ -262,14 +281,14 @@ return function (Handler $handler) {
|
||||
RequestLog::insert([
|
||||
'result' => 'fail',
|
||||
'type' => $request_db_field,
|
||||
'user_id' => $user['id'] ?? null
|
||||
'user_id' => $user['id'] ?? null,
|
||||
]);
|
||||
if ((getSetting('captcha') ?? false)
|
||||
&& isset($request_log)
|
||||
&& must_use_captcha($request_log['day'] + 1)) {
|
||||
$captcha_needed = true;
|
||||
}
|
||||
if (!$error_message) {
|
||||
if (! $error_message) {
|
||||
$error_message = _s('Invalid Username/Email');
|
||||
}
|
||||
}
|
||||
@@ -277,14 +296,12 @@ return function (Handler $handler) {
|
||||
|
||||
break;
|
||||
case 'awaiting-confirmation':
|
||||
if (!Login::hasSignup()) {
|
||||
if (! Login::hasSignup()) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
if (Login::getSignup()['status'] != 'awaiting-confirmation') {
|
||||
if (Login::getSignup()['status'] !== 'awaiting-confirmation') {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -310,7 +327,7 @@ return function (Handler $handler) {
|
||||
RequestLog::insert([
|
||||
'type' => $request_db_field,
|
||||
'result' => 'fail',
|
||||
'user_id' => null
|
||||
'user_id' => null,
|
||||
]);
|
||||
$handler->issueError(403);
|
||||
|
||||
@@ -318,7 +335,10 @@ return function (Handler $handler) {
|
||||
}
|
||||
$user_id = decodeID($get_token_array[0]);
|
||||
$get_token = hashed_token_info(get()['token']);
|
||||
$confirmation_db = Confirmation::get(['type' => $request_db_field, 'user_id' => $get_token['id']]);
|
||||
$confirmation_db = Confirmation::get([
|
||||
'user_id' => $get_token['id'],
|
||||
'type' => $request_db_field,
|
||||
]);
|
||||
if ($confirmation_db === false) {
|
||||
$handler->issueError(403);
|
||||
|
||||
@@ -326,14 +346,16 @@ return function (Handler $handler) {
|
||||
}
|
||||
$hash_match = check_hashed_token($confirmation_db['confirmation_token_hash'], get()['token']);
|
||||
if (datetime_diff($confirmation_db['confirmation_date_gmt'], null, 'h') > 48) {
|
||||
Confirmation::delete(['id' => $confirmation_db['confirmation_id']]);
|
||||
Confirmation::delete([
|
||||
'id' => $confirmation_db['confirmation_id'],
|
||||
]);
|
||||
$confirmation_db = false;
|
||||
}
|
||||
if (!$hash_match || !$confirmation_db) {
|
||||
if (! $hash_match || ! $confirmation_db) {
|
||||
RequestLog::insert([
|
||||
'type' => $request_db_field,
|
||||
'result' => 'fail',
|
||||
'user_id' => $user_id
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
$handler->issueError(403);
|
||||
|
||||
@@ -341,39 +363,49 @@ return function (Handler $handler) {
|
||||
}
|
||||
switch ($doing) {
|
||||
case 'activate':
|
||||
User::update($confirmation_db['confirmation_user_id'], ['status' => 'valid']);
|
||||
Confirmation::delete(['id' => $confirmation_db['confirmation_id']]);
|
||||
User::update($confirmation_db['confirmation_user_id'], [
|
||||
'status' => 'valid',
|
||||
]);
|
||||
Confirmation::delete([
|
||||
'id' => $confirmation_db['confirmation_id'],
|
||||
]);
|
||||
$logged_user = Login::login($confirmation_db['confirmation_user_id']);
|
||||
Login::insertCookie('cookie', $logged_user['id']);
|
||||
global $theme_mail;
|
||||
$theme_mail = [
|
||||
'user' => $logged_user,
|
||||
];
|
||||
$mail['subject'] = _s('Welcome to %s', getSettings()['website_name']);
|
||||
$mail['subject'] = _s('Welcome to %s', getSetting('website_name', true));
|
||||
$mail['message'] = get_email_body_str('mails/account-welcome');
|
||||
if (send_mail($logged_user['email'], $mail['subject'], $mail['message'])) {
|
||||
$is_process_done = true;
|
||||
}
|
||||
Login::unsetSignup();
|
||||
redirect($logged_user !== [] ? User::getUrl($logged_user) : null);
|
||||
$redirectTo = $logged_user !== []
|
||||
? User::getUrl($logged_user)
|
||||
: '';
|
||||
redirect($redirectTo, 302);
|
||||
|
||||
break;
|
||||
case 'password-reset':
|
||||
if ($POST !== []) {
|
||||
if (!preg_match('/' . getSetting('user_password_pattern') . '/', $POST['new-password'] ?? '')) {
|
||||
if (! preg_match('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['new-password'] ?? '')) {
|
||||
$input_errors['new-password'] = _s('Invalid password');
|
||||
}
|
||||
if ($POST['new-password'] !== $POST['new-password-confirm']) {
|
||||
$input_errors['new-password-confirm'] = _s("Passwords don't match");
|
||||
}
|
||||
if (count($input_errors) == 0) {
|
||||
if (count($input_errors) === 0) {
|
||||
if (Login::hasPassword($user_id)) {
|
||||
$is_process_done = Login::changePassword($user_id, $POST['new-password']);
|
||||
} else {
|
||||
$is_process_done = Login::addPassword($user_id, $POST['new-password']);
|
||||
}
|
||||
if ($is_process_done) {
|
||||
Confirmation::delete(['type' => $request_db_field, 'user_id' => $user_id]);
|
||||
Confirmation::delete([
|
||||
'type' => $request_db_field,
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
} else {
|
||||
throw new Exception('Unexpected error', 400);
|
||||
}
|
||||
@@ -385,50 +417,70 @@ return function (Handler $handler) {
|
||||
break;
|
||||
case 'change-email-confirm':
|
||||
$email_candidate = $confirmation_db['confirmation_extra'];
|
||||
$email_db = DB::get('users', ['email' => $email_candidate]);
|
||||
if ($email_db !== []) {
|
||||
if ($email_db['user_status'] == 'valid') {
|
||||
Confirmation::delete(['id' => $confirmation_db['confirmation_id']]);
|
||||
$email_db = DB::get(
|
||||
table: 'users',
|
||||
where: [
|
||||
'email' => $email_candidate,
|
||||
],
|
||||
limit: 1
|
||||
);
|
||||
if (! $email_db) {
|
||||
if ($email_db['user_status'] === 'valid') {
|
||||
Confirmation::delete([
|
||||
'id' => $confirmation_db['confirmation_id'],
|
||||
]);
|
||||
RequestLog::insert([
|
||||
'type' => $request_db_field,
|
||||
'result' => 'fail',
|
||||
'user_id' => $user_id
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
} else {
|
||||
DB::delete('users', ['id' => $email_db['user_id']]);
|
||||
Confirmation::delete(['type' => 'account-change-email', 'user_id' => $email_db['user_id']]);
|
||||
}
|
||||
DB::delete('users', [
|
||||
'id' => $email_db['user_id'],
|
||||
]);
|
||||
Confirmation::delete([
|
||||
'type' => 'account-change-email',
|
||||
'user_id' => $email_db['user_id'],
|
||||
]);
|
||||
}
|
||||
Confirmation::delete(['type' => 'account-change-email', 'user_id' => $user_id]);
|
||||
Confirmation::delete([
|
||||
'type' => 'account-change-email',
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
sessionVar()->put('change-email-confirm', true);
|
||||
User::update($user_id, ['email' => $email_candidate]);
|
||||
User::update($user_id, [
|
||||
'email' => $email_candidate,
|
||||
]);
|
||||
Login::login($user_id);
|
||||
redirect('account/email-changed');
|
||||
redirect('account/email-changed', 302);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'email-needed':
|
||||
if ($POST !== [] && !$is_error) {
|
||||
if (!filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if ($POST !== [] && ! $is_error) {
|
||||
if (! filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$is_error = true;
|
||||
$input_errors['email'] = _s('Invalid email');
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
$user = User::getSingle($POST['email'], 'email');
|
||||
if ($user !== []) {
|
||||
$is_error = true;
|
||||
$input_errors['email'] = _s('Email already being used');
|
||||
}
|
||||
}
|
||||
if (!$is_error) {
|
||||
User::update($logged_user['id'], ['status' => getSetting('require_user_email_confirmation') ? 'awaiting-confirmation' : 'valid', 'email' => trim($POST['email'])]);
|
||||
if (!getSetting('require_user_email_confirmation')) {
|
||||
redirect($logged_user['url']);
|
||||
if (! $is_error) {
|
||||
User::update($logged_user['id'], [
|
||||
'status' => getSetting('require_user_email_confirmation') ? 'awaiting-confirmation' : 'valid',
|
||||
'email' => trim($POST['email']),
|
||||
]);
|
||||
if (! getSetting('require_user_email_confirmation')) {
|
||||
redirect($logged_user['url'], 302);
|
||||
}
|
||||
$hashed_token = generate_hashed_token((int) $logged_user['id']);
|
||||
$array_values = [
|
||||
@@ -445,7 +497,7 @@ return function (Handler $handler) {
|
||||
'user' => $logged_user,
|
||||
'link' => $activation_link,
|
||||
];
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings('website_name', true));
|
||||
$mail['message'] = get_email_body_str('mails/account-confirm');
|
||||
if (send_mail($POST['email'], $mail['subject'], $mail['message'])) {
|
||||
$is_process_done = true;
|
||||
@@ -454,13 +506,13 @@ return function (Handler $handler) {
|
||||
'status' => 'awaiting-confirmation',
|
||||
'email' => $POST['email'],
|
||||
]);
|
||||
redirect('account/awaiting-confirmation');
|
||||
redirect('account/awaiting-confirmation', 302);
|
||||
} else {
|
||||
RequestLog::insert(
|
||||
[
|
||||
'result' => 'fail',
|
||||
'type' => $request_db_field,
|
||||
'user_id' => $user['id'] ?? null
|
||||
'user_id' => $user['id'] ?? null,
|
||||
]
|
||||
);
|
||||
if ((getSetting('captcha') ?? false)
|
||||
@@ -476,7 +528,7 @@ return function (Handler $handler) {
|
||||
|
||||
break;
|
||||
case 'email-changed':
|
||||
if (!isset(session()['change-email-confirm'])) {
|
||||
if (! isset(session()['change-email-confirm'])) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -486,20 +538,20 @@ return function (Handler $handler) {
|
||||
break;
|
||||
case 'two-factor':
|
||||
$handler->setTemplate($route . '/' . 'two-factor');
|
||||
if (!is_null($POST['user-two-factor'] ?? null) && !$is_error) {
|
||||
if (null !== ($POST['user-two-factor'] ?? null) && ! $is_error) {
|
||||
$twoFactor = (new TwoFactor())->withSecret(
|
||||
TwoFactor::getSecretFor(intval($logged_user['id']))
|
||||
);
|
||||
if ($twoFactor->verify($POST['user-two-factor'])) {
|
||||
sessionVar()->remove('challenge_two_factor');
|
||||
redirect($logged_user['url']);
|
||||
redirect($logged_user['url'], 302);
|
||||
} else {
|
||||
$is_error = true;
|
||||
$input_errors['user-two-factor'] = _s('Invalid code');
|
||||
RequestLog::insert([
|
||||
'type' => $request_db_field,
|
||||
'result' => 'fail',
|
||||
'user_id' => $logged_user['id']
|
||||
'user_id' => $logged_user['id'],
|
||||
]);
|
||||
if ((getSetting('captcha') ?? false)
|
||||
&& isset($request_log)
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use Chevereto\Legacy\Classes\Album;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\Tag;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\G\starts_with;
|
||||
@@ -24,10 +28,11 @@ use function Chevereto\Legacy\G\url_to_relative;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getIdFromURLComponent;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Legacy\is_max_invalid_request;
|
||||
use function Chevereto\Legacy\isShowEmbedContent;
|
||||
use function Chevereto\Legacy\must_use_captcha;
|
||||
use function Chevereto\Legacy\redirectIfRouting;
|
||||
use function Chevereto\Legacy\virtualRouteHandleRedirect;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\post;
|
||||
@@ -37,7 +42,7 @@ use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
redirectIfRouting('album', $handler->requestArray()[0]);
|
||||
virtualRouteHandleRedirect('album', $handler->requestArray()[0]);
|
||||
$albumIndex = getSetting('root_route') === 'album'
|
||||
? 0
|
||||
: 1;
|
||||
@@ -60,19 +65,21 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (isset($request_handle[1]) && !in_array($request_handle[1], ['embeds', 'sub', 'info'])) {
|
||||
if (isset($request_handle[1])
|
||||
&& ! in_array($request_handle[1], ['embeds', 'sub', 'info'])
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
if (!isset(session()['album_view_stock'])) {
|
||||
if (! isset(session()['album_view_stock'])) {
|
||||
sessionVar()->put('album_view_stock', []);
|
||||
}
|
||||
$album = Album::getSingle(
|
||||
id: $id,
|
||||
sumview: !in_array($id, session()['album_view_stock']),
|
||||
sumView: ! in_array($id, session()['album_view_stock']),
|
||||
requester: $logged_user
|
||||
);
|
||||
if ($album === []) {
|
||||
@@ -80,26 +87,23 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
&& ($album['user']['id'] ?? 'not-found') != getSetting('website_mode_personal_uid')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!starts_with($album['url'], get_current_url())) {
|
||||
if (! starts_with($album['url'], get_public_url(get_current_url()))) {
|
||||
if (server()['QUERY_STRING'] ?? false) {
|
||||
$redirect = rtrim($album['url'], '/') . '/?' . server()['QUERY_STRING'];
|
||||
} else {
|
||||
$redirect = $album['url'];
|
||||
}
|
||||
redirect($redirect);
|
||||
|
||||
redirect($redirect, 302);
|
||||
}
|
||||
$handler::setVar(
|
||||
'canonical',
|
||||
isset(get()['page']) ? null : $album['url']
|
||||
);
|
||||
$banned = isset($album['user']['status']) && $album['user']['status'] === 'banned';
|
||||
if (!$handler::cond('content_manager') && ($album == false || $banned)) {
|
||||
if (! $handler::cond('content_manager') && ($album == false || $banned)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -109,11 +113,14 @@ return function (Handler $handler) {
|
||||
if ($handler::cond('forced_private_mode')) {
|
||||
$album['privacy'] = getSetting('website_content_privacy_mode');
|
||||
}
|
||||
if (!Login::getUser() && $album['privacy'] != 'private_but_link') {
|
||||
redirect('login');
|
||||
if (! Login::getUser()
|
||||
&& $album['privacy'] != 'private_but_link'
|
||||
) {
|
||||
headersNoCache();
|
||||
redirect('login', 302);
|
||||
}
|
||||
}
|
||||
if (!$handler::cond('content_manager') && !$is_owner && $album['privacy'] == 'password' && isset($album['password'])) {
|
||||
if (! $handler::cond('content_manager') && ! $is_owner && $album['privacy'] == 'password' && isset($album['password'])) {
|
||||
$is_error = false;
|
||||
$error_message = null;
|
||||
$failed_access_requests = RequestLog::getCounts('content-password', 'fail');
|
||||
@@ -125,21 +132,22 @@ return function (Handler $handler) {
|
||||
$captcha_needed = $handler::cond('captcha_needed');
|
||||
if ($captcha_needed && (post()['content-password'] ?? false)) {
|
||||
$captcha = captcha_check();
|
||||
if (!$captcha->is_valid) {
|
||||
if (! $captcha->is_valid) {
|
||||
$is_error = true;
|
||||
$error_message = _s('%s says you are a robot', 'CAPTCHA');
|
||||
}
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
if (isset(post()['content-password']) && hash_equals($album['password'], post()['content-password'])) {
|
||||
Album::storeUserPassword($album['id'], post()['content-password']);
|
||||
} elseif (!Album::checkSessionPassword($album)) {
|
||||
} elseif (! Album::checkSessionPassword($album)) {
|
||||
$is_error = true;
|
||||
if (isset(post()['content-password'])) {
|
||||
RequestLog::insert([
|
||||
'type' => 'content-password',
|
||||
'user_id' => ($logged_user['id'] ?? null),
|
||||
'content_id' => $album['id'], 'result' => 'fail'
|
||||
'content_id' => $album['id'],
|
||||
'result' => 'fail',
|
||||
]);
|
||||
$error_message = _s('Invalid password');
|
||||
}
|
||||
@@ -156,28 +164,77 @@ return function (Handler $handler) {
|
||||
$handler::setVar('pre_doctitle', _s('Password required'));
|
||||
|
||||
return;
|
||||
} else {
|
||||
$redirect_password = session()['redirect_password_to'] ?? null;
|
||||
if (isset($redirect_password)) {
|
||||
sessionVar()->remove('redirect_password_to');
|
||||
redirect($redirect_password);
|
||||
}
|
||||
}
|
||||
$redirect_password = session()['redirect_password_to'] ?? null;
|
||||
if (isset($redirect_password)) {
|
||||
sessionVar()->remove('redirect_password_to', null);
|
||||
headersNoCache();
|
||||
redirect($redirect_password, 302);
|
||||
}
|
||||
}
|
||||
if ($album['user']['is_private'] == 1
|
||||
&& !$handler::cond('content_manager')
|
||||
&& $album["user"]["id"] != ($logged_user['id'] ?? null)
|
||||
&& ! $handler::cond('content_manager')
|
||||
&& $album['user']['id'] != ($logged_user['id'] ?? null)
|
||||
) {
|
||||
unset($album['user']);
|
||||
$album['user'] = User::getPrivate();
|
||||
}
|
||||
if (!$handler::cond('content_manager') && in_array($album['privacy'], ['private', 'custom']) && !$is_owner) {
|
||||
if (! $handler::cond('content_manager')
|
||||
&& in_array($album['privacy'], ['private', 'custom'])
|
||||
&& ! $is_owner
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$tags_id = [];
|
||||
$tags_active = [];
|
||||
$isDisplayUsedTags = true;
|
||||
if ((get()['tag'] ?? '') !== '') {
|
||||
$tags = Tag::get(get()['tag']);
|
||||
if ($tags !== []) {
|
||||
$tags_active = array_column($tags, 'name');
|
||||
$tags_id = array_column($tags, 'id');
|
||||
$tags_id_encoded = array_map(function ($id): string {
|
||||
return encodeID($id);
|
||||
}, $tags_id);
|
||||
$params_hidden['tag_id'] = implode(',', $tags_id_encoded);
|
||||
}
|
||||
}
|
||||
$tag_string = implode(', ', $tags_active);
|
||||
$tag_string_no_spaces = implode(',', $tags_active);
|
||||
$tagsTable = DB::getTable('tags');
|
||||
$tagsAlbumsTable = DB::getTable('tags_albums');
|
||||
$userId = (int) $album['user']['id'];
|
||||
$albumId = (int) $album['id'];
|
||||
$base_album_url = url_to_relative($album['url']);
|
||||
$tags_display = [];
|
||||
if ($isDisplayUsedTags) {
|
||||
$tagsSql = <<<MySQL
|
||||
SELECT t.tag_name name, ta.tag_album_count count
|
||||
FROM `{$tagsTable}` t
|
||||
INNER JOIN `{$tagsAlbumsTable}` ta
|
||||
ON ta.tag_album_tag_id=t.tag_id
|
||||
AND ta.tag_album_album_id={$albumId}
|
||||
AND ta.tag_album_count > 0
|
||||
AND ta.tag_album_user_id={$userId}
|
||||
ORDER BY `tag_album_count` DESC, `tag_name` ASC
|
||||
LIMIT 20;
|
||||
|
||||
MySQL;
|
||||
$tags_display = DB::queryFetchAll($tagsSql);
|
||||
foreach ($tags_display as &$tag) {
|
||||
$base_tag_filter_url = $base_album_url . '/?tag=';
|
||||
$tag = Tag::row($tag['name'], $base_tag_filter_url . '%s');
|
||||
Tag::addUrlFilters($tag, $base_album_url, $tags_active);
|
||||
}
|
||||
}
|
||||
$safe_html_album = safe_html($album);
|
||||
$safe_html_album['description'] = preg_replace('/[ \t]+/', ' ', preg_replace('/\s*$^\s*/m', "\n", $safe_html_album['description'] ?? ''));
|
||||
$safe_html_album['description'] = preg_replace(
|
||||
'/[ \t]+/',
|
||||
' ',
|
||||
preg_replace('/\s*$^\s*/m', "\n", $safe_html_album['description'] ?? '')
|
||||
);
|
||||
$getParams = Listing::getParams(request());
|
||||
$handler::setVar('list_params', $getParams);
|
||||
$type = 'images';
|
||||
@@ -200,11 +257,13 @@ return function (Handler $handler) {
|
||||
$listing->setLimit($getParams['limit']); // how many results?
|
||||
$listing->setSortType($getParams['sort'][0]); // date | size | views
|
||||
$listing->setSortOrder($getParams['sort'][1]); // asc | desc
|
||||
$listing->setOwner((int) $album["user"]["id"]);
|
||||
$listing->setOwner((int) $album['user']['id']);
|
||||
$listing->setTagsIds(...$tags_id);
|
||||
$listing->setTagsString($tag_string_no_spaces);
|
||||
$listing->setRequester(Login::getUser());
|
||||
$listing->setWhere($where);
|
||||
$listing->setPrivacy($album["privacy"]);
|
||||
$listing->bind(":image_album_id", $album["id"]);
|
||||
$listing->setPrivacy($album['privacy']);
|
||||
$listing->bind(':image_album_id', $album['id']);
|
||||
$listing->setOutputTpl($output_tpl);
|
||||
if ($is_owner || $handler::cond('content_manager')) {
|
||||
$listing->setTools(true);
|
||||
@@ -215,8 +274,17 @@ return function (Handler $handler) {
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => 'images',
|
||||
'basename' => $baseUrl,
|
||||
'params_hidden' => ['list' => 'images', 'from' => 'album', 'albumid' => $album['id_encoded']],
|
||||
'tools_available' => $album['user']['id'] ? [] : ['album' => false]
|
||||
'params_hidden' => [
|
||||
'list' => 'images',
|
||||
'from' => 'album',
|
||||
'albumid' => $album['id_encoded'],
|
||||
],
|
||||
'tools_available' => $album['user']['id']
|
||||
? []
|
||||
: [
|
||||
'album' => false,
|
||||
],
|
||||
'tag' => rawurldecode($tag_string_no_spaces),
|
||||
]);
|
||||
if (isShowEmbedContent()) {
|
||||
$tabs[] = [
|
||||
@@ -228,18 +296,28 @@ return function (Handler $handler) {
|
||||
'id' => 'tab-embeds',
|
||||
];
|
||||
}
|
||||
|
||||
$tabsSubAlbum = Listing::getTabs([
|
||||
'listing' => 'albums',
|
||||
'basename' => $baseUrl . '/sub',
|
||||
'params_hidden' => ['list' => 'albums', 'from' => 'album', 'albumid' => $album['id_encoded']],
|
||||
'tools_available' => $album['user']['id'] ? [] : ['album' => false]
|
||||
'params_hidden' => [
|
||||
'list' => 'albums',
|
||||
'from' => 'album',
|
||||
'albumid' => $album['id_encoded'],
|
||||
],
|
||||
'tools_available' => $album['user']['id']
|
||||
? []
|
||||
: [
|
||||
'album' => false,
|
||||
],
|
||||
], $getParams);
|
||||
foreach ($tabsSubAlbum as $array) {
|
||||
if ($array['label'] == 'AZ') {
|
||||
$array['label'] = _s('Sub %s', _s('albums'));
|
||||
$array['id'] = 'tab-sub';
|
||||
$array['url'] = $album['url'] . '/sub';
|
||||
$array = array_merge($array, [
|
||||
'icon' => 'fas fa-folder-tree',
|
||||
'label' => _s('Sub %s', _s('albums')),
|
||||
'id' => 'tab-sub',
|
||||
'url' => $album['url'] . '/sub',
|
||||
]);
|
||||
$tabs[] = $array;
|
||||
|
||||
break;
|
||||
@@ -252,9 +330,10 @@ return function (Handler $handler) {
|
||||
'tools' => false,
|
||||
'label' => _s('Info'),
|
||||
'id' => 'tab-info',
|
||||
'url' => $album['url'] . '/info'
|
||||
'url' => $album['url'] . '/info',
|
||||
];
|
||||
}
|
||||
$currentKey = 0;
|
||||
$handler::setVar('current_tab', 0);
|
||||
foreach ($tabs as $k => &$v) {
|
||||
if (isset($request_handle[1])) {
|
||||
@@ -262,11 +341,12 @@ return function (Handler $handler) {
|
||||
}
|
||||
if (isset($v['current']) && $v['current'] === true) {
|
||||
$handler::setVar('current_tab', $v['id']);
|
||||
$currentKey = $k;
|
||||
}
|
||||
if (!isset($v['params'])) {
|
||||
if (! isset($v['params'])) {
|
||||
continue;
|
||||
}
|
||||
$class_tabs[$k]['disabled'] = $album['image_count'] == 0 ? !$v['current'] : false;
|
||||
$class_tabs[$k]['disabled'] = $album['image_count'] == 0 ? ! $v['current'] : false;
|
||||
}
|
||||
$handler::setCond('owner', $is_owner);
|
||||
$handler::setVars([
|
||||
@@ -275,27 +355,68 @@ return function (Handler $handler) {
|
||||
'album_safe_html' => $safe_html_album,
|
||||
'tabs' => $tabs,
|
||||
'list' => $listing,
|
||||
'owner' => $album['user']
|
||||
'owner' => $album['user'],
|
||||
]);
|
||||
if (isset($album['description'])) {
|
||||
$meta_description = $album['description'];
|
||||
} else {
|
||||
$meta_description = _s('%a album hosted in %w', ['%a' => $album['name'], '%w' => getSetting('website_name')]);
|
||||
$meta_description = _s('%a album hosted in %w', [
|
||||
'%a' => $album['name'],
|
||||
'%w' => getSetting('website_name'),
|
||||
]);
|
||||
}
|
||||
$handler::setVar('meta_description', htmlspecialchars($meta_description));
|
||||
$handler::setVar('meta_description', $meta_description);
|
||||
if ($handler::cond('content_manager') || $is_owner) {
|
||||
$handler::setVar('user_items_editor', [
|
||||
"user_albums" => User::getAlbums((int) $album["user"]["id"]),
|
||||
"type" => "images"
|
||||
'user_albums' => User::getAlbums((int) $album['user']['id']),
|
||||
'type' => $type,
|
||||
]);
|
||||
}
|
||||
$share_element = [
|
||||
"HTML" => '<a href="__url__" title="__title__">__title__ (' . $album['image_count'] . ' ' . _n('image', 'images', $album['user']['image_count_display']) . ')</a>'
|
||||
'HTML' => '<a href="__url__" title="__title__">__title__ ('
|
||||
. $album['image_count']
|
||||
. ' '
|
||||
. _n('image', 'images', $album['user']['image_count_display'])
|
||||
. ')</a>',
|
||||
];
|
||||
$share_links_array = get_share_links($share_element);
|
||||
$handler::setVar('share_links_array', $share_links_array);
|
||||
$handler::setVar('privacy', $album['privacy']);
|
||||
$addValue = session()['album_view_stock'];
|
||||
$addValue[] = $id;
|
||||
sessionVar()->put('album_view_stock', $addValue);
|
||||
$sessionValue = session()['album_view_stock'];
|
||||
$sessionValue[] = $id;
|
||||
sessionVar()->put('album_view_stock', $sessionValue);
|
||||
$handler::setVar('tags_display', $tags_display);
|
||||
$handler::setVar('tags_active', $tags_active);
|
||||
if ($tag_string !== '') {
|
||||
$handler::setVar('meta_keywords', $tag_string);
|
||||
}
|
||||
$canonical = get_public_url($tabs[$currentKey]['url']);
|
||||
$handler::setVar('canonical', $canonical);
|
||||
$ancestors = [];
|
||||
$breadcrumbs = [];
|
||||
if (isset($album['parent_id'])) {
|
||||
$safe_breadcrumbs_limit = 8;
|
||||
|
||||
try {
|
||||
$ancestors = Album::getAncestors(
|
||||
$album['id'],
|
||||
$logged_user,
|
||||
$safe_breadcrumbs_limit + 1
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
$ancestors = [];
|
||||
}
|
||||
if (count($ancestors) > $safe_breadcrumbs_limit - 1) {
|
||||
$ancestors[count($ancestors) - 1]['name_html'] = '...';
|
||||
}
|
||||
foreach ($ancestors as $ancestor) {
|
||||
$breadcrumbs[] = [
|
||||
'url' => $ancestor['url'],
|
||||
'name_html' => $ancestor['name_html'],
|
||||
];
|
||||
}
|
||||
$breadcrumbs = array_reverse($breadcrumbs);
|
||||
}
|
||||
$handler::setVar('ancestors', $ancestors);
|
||||
$handler::setVar('breadcrumbs', $breadcrumbs);
|
||||
};
|
||||
|
||||
21
app/legacy/routes/api-v1.php
Normal file
21
app/legacy/routes/api-v1.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$handler::setVar('pre_doctitle', _s('API version %s', '1.1'));
|
||||
};
|
||||
@@ -23,15 +23,18 @@ use Chevereto\Legacy\Classes\Akismet;
|
||||
use Chevereto\Legacy\Classes\ApiKey;
|
||||
use Chevereto\Legacy\Classes\Image;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\Upload;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\decodeID;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use function Chevereto\Legacy\G\get_mimetype;
|
||||
use function Chevereto\Legacy\G\getQsParams;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\is_image_url;
|
||||
use function Chevereto\Legacy\G\is_url;
|
||||
use function Chevereto\Legacy\G\json_document_output;
|
||||
use function Chevereto\Legacy\G\json_error;
|
||||
use function Chevereto\Legacy\G\json_output;
|
||||
use function Chevereto\Legacy\G\mime_to_extension;
|
||||
use function Chevereto\Legacy\G\random_string;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Vars\env;
|
||||
@@ -46,106 +49,96 @@ return function (Handler $handler) {
|
||||
$FILES = files();
|
||||
$SERVER = server();
|
||||
$format = $REQUEST['format'] ?? 'json';
|
||||
$version = $handler->request()[0] ?? null;
|
||||
$action = $handler->request()[1] ?? null;
|
||||
$key = $SERVER['HTTP_X_API_KEY'] ?? $REQUEST['key'] ?? null;
|
||||
$version = strval($handler->request()[0] ?? '');
|
||||
$action = strval($handler->request()[1] ?? '');
|
||||
$key = strval($SERVER['HTTP_X_API_KEY'] ?? $REQUEST['key'] ?? '');
|
||||
foreach (['version', 'action', 'key'] as $var) {
|
||||
if (${$var} === null) {
|
||||
throw new Exception("No $var provided", 100);
|
||||
if (${$var} === '') {
|
||||
throw new Exception("No {$var} provided", 100);
|
||||
}
|
||||
}
|
||||
if (!in_array($version, ['1'])) {
|
||||
if (! in_array($version, ['1'], true)) {
|
||||
throw new Exception('Invalid API version.', 110);
|
||||
}
|
||||
$verify = ApiKey::verify($key);
|
||||
if ($verify === []) {
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_API_GUEST']) {
|
||||
throw new Exception("Guest API is disabled.", 400);
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_API_GUEST']) {
|
||||
throw new Exception('Invalid API key.', 100);
|
||||
}
|
||||
$apiV1Key = (string) (getSetting('api_v1_key') ?? '');
|
||||
if ($apiV1Key == '') {
|
||||
throw new Exception("API V1 public key can't be null. Go to your dashboard and set the Guest API key.", 0);
|
||||
if ($apiV1Key === '') {
|
||||
throw new Exception("API V1 public key can't be null. Go to /dashboard and set the Guest API key.", 0);
|
||||
}
|
||||
// @var string $key
|
||||
if (!hash_equals($apiV1Key, $key)) {
|
||||
throw new Exception("Invalid guest API key.", 100);
|
||||
if (! hash_equals($apiV1Key, $key)) {
|
||||
throw new Exception('Invalid API key.', 100);
|
||||
}
|
||||
} else {
|
||||
$user = User::getSingle($verify['user_id']);
|
||||
}
|
||||
$isAdmin = boolval(($user['is_admin'] ?? false));
|
||||
if (Settings::get('enable_uploads_url') && !$isAdmin) {
|
||||
if (Settings::get('enable_uploads_url') && ! $isAdmin) {
|
||||
Settings::setValue('enable_uploads_url', 0);
|
||||
}
|
||||
$upload_enabled = $isAdmin ?: getSetting('enable_uploads');
|
||||
$upload_allowed = $upload_enabled;
|
||||
if ($user === []) {
|
||||
if (!getSetting('guest_uploads')
|
||||
|| getSetting('website_privacy_mode') == 'private'
|
||||
|| $handler::cond('maintenance')
|
||||
) {
|
||||
$upload_allowed = false;
|
||||
}
|
||||
} elseif (!$user['is_admin']
|
||||
&& getSetting('website_mode') == 'personal'
|
||||
&& getSetting('website_mode_personal_uid') !== $user['id']
|
||||
) {
|
||||
$upload_allowed = false;
|
||||
}
|
||||
if (!$upload_allowed) {
|
||||
if (! $handler::cond('upload_allowed')) {
|
||||
throw new Exception(_s('Request denied'), 401);
|
||||
}
|
||||
$version_to_actions = [
|
||||
'1' => ['upload']
|
||||
];
|
||||
if (!in_array($action, $version_to_actions[$version])) {
|
||||
throw new Exception('Invalid API action.', 120);
|
||||
'1' => ['upload'],
|
||||
];
|
||||
if (! in_array($action, $version_to_actions[$version], true)) {
|
||||
throw new Exception('Invalid API action', 120);
|
||||
}
|
||||
$source = $FILES['source']
|
||||
?? $REQUEST['source']
|
||||
?? $REQUEST['image']
|
||||
?? null;
|
||||
if (is_null($source)) {
|
||||
throw new Exception('Empty upload source.', 130);
|
||||
if ($source === null) {
|
||||
throw new Exception('Empty upload source', 130);
|
||||
}
|
||||
switch (true) {
|
||||
case isset($FILES['source'], $FILES['source']['tmp_name']):
|
||||
$source = $FILES['source'];
|
||||
|
||||
break;
|
||||
break;
|
||||
case is_image_url($source) || is_url($source):
|
||||
if (($SERVER['REQUEST_METHOD'] ?? '') === 'GET') {
|
||||
$sourceQs = urldecode(getQsParams()['source']);
|
||||
}
|
||||
$source = $sourceQs ?? $source;
|
||||
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
if (($SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
throw new Exception('Upload using base64 source must be done using POST method.', 130);
|
||||
}
|
||||
$source = trim(preg_replace('/\s+/', '', $source));
|
||||
$base64source = base64_encode(base64_decode($source));
|
||||
if (!hash_equals($base64source, $source)) {
|
||||
throw new Exception('Invalid base64 string.', 120);
|
||||
$base64source = base64_encode(base64_decode($source, true));
|
||||
if (! hash_equals($base64source, $source)) {
|
||||
throw new Exception('Invalid base64 string', 120);
|
||||
}
|
||||
$api_temp_file = tempnam(sys_get_temp_dir(), 'chvtemp');
|
||||
if (!$api_temp_file || !is_writable($api_temp_file)) {
|
||||
throw new Exception("Can't get a tempnam.", 200);
|
||||
if ($source === '') {
|
||||
throw new Exception('Empty source', 130);
|
||||
}
|
||||
|
||||
try {
|
||||
$api_temp_file = Upload::getTempNam();
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Can't get a tempnam", 200);
|
||||
}
|
||||
$fh = fopen($api_temp_file, 'w');
|
||||
stream_filter_append($fh, 'convert.base64-decode', STREAM_FILTER_WRITE);
|
||||
fwrite($fh, $source);
|
||||
fclose($fh);
|
||||
$mimetype = get_mimetype($api_temp_file);
|
||||
$source = [
|
||||
'name' => random_string(12) . '.jpg',
|
||||
'type' => 'image/jpeg',
|
||||
'name' => random_string(12) . '.' . mime_to_extension($mimetype),
|
||||
'type' => $mimetype,
|
||||
'tmp_name' => $api_temp_file,
|
||||
'error' => 'UPLOAD_ERR_OK',
|
||||
'size' => '1'
|
||||
'size' => filesize($api_temp_file),
|
||||
];
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$isImgBBSpec = array_key_exists('image', $REQUEST);
|
||||
$albumId = $REQUEST['album_id'] ?? null;
|
||||
@@ -153,8 +146,8 @@ return function (Handler $handler) {
|
||||
$albumId = decodeID($albumId);
|
||||
}
|
||||
$expiration = $REQUEST['expiration'] ?? null;
|
||||
if (!is_null($expiration) && ctype_digit($expiration)) {
|
||||
$expiration = Image::getExpirationFromSeconds($expiration);
|
||||
if ($expiration !== null && ctype_digit($expiration)) {
|
||||
$expiration = (int) $expiration;
|
||||
}
|
||||
$params = [
|
||||
'album_id' => $albumId,
|
||||
@@ -162,12 +155,12 @@ return function (Handler $handler) {
|
||||
'description' => $REQUEST['description'] ?? null,
|
||||
'nsfw' => $REQUEST['nsfw'] ?? null,
|
||||
'title' => $REQUEST['title'] ?? $REQUEST['name'] ?? null,
|
||||
'tags' => $REQUEST['tags'] ?? null,
|
||||
'width' => $REQUEST['width'] ?? null,
|
||||
'expiration' => $expiration,
|
||||
'mimetype' => $REQUEST['mimetype'] ?? 'image/jpeg',
|
||||
];
|
||||
$params = array_filter($params);
|
||||
if (!$handler::cond('content_manager') && getSetting('akismet')) {
|
||||
if (! $handler::cond('content_manager') && getSetting('akismet')) {
|
||||
$user_source_db = [
|
||||
'user_name' => $user['name'] ?? null,
|
||||
'user_username' => $user['username'] ?? null,
|
||||
@@ -178,9 +171,13 @@ return function (Handler $handler) {
|
||||
$uploadToWebsite = Image::uploadToWebsite($source, $user, $params);
|
||||
$uploaded_id = intval($uploadToWebsite[0]);
|
||||
$image = Image::formatArray(Image::getSingle($uploaded_id), true);
|
||||
$image['delete_url'] = Image::getDeleteUrl(encodeID($uploaded_id), $uploadToWebsite[1]);
|
||||
$image['delete_url'] = Image::getDeleteUrl(
|
||||
type: $image['type'],
|
||||
idEncoded: encodeID($uploaded_id),
|
||||
password: $uploadToWebsite[1]
|
||||
);
|
||||
unset($image['user'], $image['album']);
|
||||
if (!$image['is_approved']) {
|
||||
if (! $image['is_approved']) {
|
||||
unset($image['image']['url'], $image['thumb']['url'], $image['medium']['url'], $image['url'], $image['display_url']);
|
||||
}
|
||||
$json_array = [];
|
||||
@@ -189,49 +186,51 @@ return function (Handler $handler) {
|
||||
$json_array['status'] = $json_array['status_code'];
|
||||
$image['id'] = $image['id_encoded'];
|
||||
}
|
||||
$json_array['success'] = ['message' => 'file uploaded', 'code' => 200];
|
||||
$json_array['success'] = [
|
||||
'message' => 'file uploaded',
|
||||
'code' => 200,
|
||||
];
|
||||
$json_array[$isImgBBSpec ? 'data' : 'image'] = $image;
|
||||
|
||||
if ($version == 1) {
|
||||
if ($version === '1') {
|
||||
switch ($format) {
|
||||
default:
|
||||
case 'json':
|
||||
json_output($json_array);
|
||||
json_document_output($json_array);
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'txt':
|
||||
echo $image['url'];
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'redirect':
|
||||
if ($json_array['status_code'] === 200) {
|
||||
$redirect_url = $image['path_viewer'];
|
||||
header("Location: $redirect_url");
|
||||
header("Location: {$redirect_url}");
|
||||
} else {
|
||||
die($json_array['status_code']);
|
||||
exit($json_array['status_code']);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
die();
|
||||
} else {
|
||||
json_output($json_array);
|
||||
exit();
|
||||
}
|
||||
json_document_output($json_array);
|
||||
} catch (Exception $e) {
|
||||
$json_array = json_error($e);
|
||||
if ($version == 1) {
|
||||
if ($version === '1') {
|
||||
switch ($format) {
|
||||
default:
|
||||
case 'json':
|
||||
json_output($json_array);
|
||||
json_document_output($json_array);
|
||||
|
||||
break;
|
||||
case 'txt':
|
||||
case 'redirect':
|
||||
die($json_array['error']['message']);
|
||||
exit($json_array['error']['message']);
|
||||
}
|
||||
} else {
|
||||
json_output($json_array);
|
||||
json_document_output($json_array);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\fetch_url;
|
||||
use function Chevereto\Legacy\G\get_client_ip;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Vars\get;
|
||||
@@ -20,7 +20,7 @@ use function Chevereto\Vars\sessionVar;
|
||||
return function (Handler $handler) {
|
||||
$key = getSetting('captcha_secret') ?? '';
|
||||
if ($key === '') {
|
||||
redirect();
|
||||
redirect('', 302);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -35,7 +35,7 @@ return function (Handler $handler) {
|
||||
$params = [
|
||||
'secret' => getSetting('captcha_secret'),
|
||||
'response' => get()['token'] ?? '',
|
||||
'remoteip' => get_client_ip()
|
||||
'remoteip' => get_client_ip(),
|
||||
];
|
||||
$fetch = fetch_url(
|
||||
url: $endpoint,
|
||||
@@ -47,9 +47,9 @@ return function (Handler $handler) {
|
||||
$object = json_decode($fetch);
|
||||
$isSuccess = (bool) $object->success;
|
||||
sessionVar()->put('isHuman', $isSuccess);
|
||||
sessionVar()->put('isBot', !$isSuccess);
|
||||
die($fetch);
|
||||
sessionVar()->put('isBot', ! $isSuccess);
|
||||
exit($fetch);
|
||||
} catch (Exception) {
|
||||
}
|
||||
die();
|
||||
exit();
|
||||
};
|
||||
|
||||
@@ -11,14 +11,18 @@
|
||||
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!$handler::cond('explore_enabled')) {
|
||||
if (! $handler::cond('explore_enabled')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($handler->isRequestLevel(3)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -26,29 +30,33 @@ return function (Handler $handler) {
|
||||
$category = null;
|
||||
$categories = $handler::var('categories');
|
||||
$category_url_key = $handler->request()[0] ?? false;
|
||||
if (!$category_url_key) {
|
||||
redirect('explore');
|
||||
}
|
||||
if ($category_url_key) {
|
||||
foreach ($categories as $v) {
|
||||
if ($v['url_key'] == $category_url_key) {
|
||||
$category = $v;
|
||||
if (! $category_url_key) {
|
||||
$handler->issueError(404);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$category) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$handler::setVar('pre_doctitle', $category['name']);
|
||||
return;
|
||||
}
|
||||
$category_url_key = urldecode($category_url_key);
|
||||
foreach ($categories as $v) {
|
||||
if ($v['url_key'] == $category_url_key) {
|
||||
$category = $v;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! $category) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$handler::setVar('pre_doctitle', $category['name']);
|
||||
$getParams = Listing::getParams(request());
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => 'images',
|
||||
'basename' => get_route_name() . '/' . $category['url_key'],
|
||||
'params_hidden' => ['category_id' => $category['id'], 'hide_banned' => 1],
|
||||
'params_hidden' => [
|
||||
'category_id' => $category['id'],
|
||||
'hide_banned' => 1,
|
||||
],
|
||||
], $getParams);
|
||||
$handler::setVar('list_params', $getParams);
|
||||
$listing = new Listing();
|
||||
@@ -67,10 +75,9 @@ return function (Handler $handler) {
|
||||
$listing->setRequester(Login::getUser());
|
||||
$listing->exec();
|
||||
$meta_description = $category['description'] ?? '';
|
||||
$handler::setVar('meta_description', htmlspecialchars($meta_description));
|
||||
$handler::setVar('meta_description', $meta_description);
|
||||
$handler::setVar('category', $category);
|
||||
$handler::setVar('tabs', $tabs);
|
||||
$handler::setVar('listing', $listing);
|
||||
$handler->setTemplate('explore');
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
};
|
||||
|
||||
@@ -9,28 +9,29 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevere\Message\message;
|
||||
use Chevereto\Legacy\Classes\HybridauthSession;
|
||||
use Chevereto\Legacy\Classes\L10n;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use Hybridauth\Exception\InvalidAuthorizationStateException;
|
||||
use Hybridauth\Hybridauth;
|
||||
use function Chevere\Message\message;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!version_compare(Settings::get('chevereto_version_installed') ?? '', '4.0.0-beta.11', '>=')) {
|
||||
if (! version_compare(cheveretoVersionInstalled(), '4.0.0-beta.11', '>=')) {
|
||||
echo 'Route not available until the system update gets installed.';
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
$doing = $handler->request()[0] ?? '';
|
||||
$providersEnabled = Login::getProviders('enabled');
|
||||
$doable = array_keys($providersEnabled);
|
||||
if (!in_array($doing, $doable)) {
|
||||
if (! in_array($doing, $doable)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -43,7 +44,7 @@ return function (Handler $handler) {
|
||||
if ($validate['valid']
|
||||
&& in_array($validate['id'], Login::getSession()['login_cookies'] ?? [])
|
||||
) {
|
||||
redirect('settings/connections#' . $doing);
|
||||
redirect('settings/connections#' . $doing, 302);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -58,7 +59,7 @@ return function (Handler $handler) {
|
||||
'keys' => [
|
||||
'id' => $provider['key_id'],
|
||||
'secret' => $provider['key_secret'],
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
$session = new HybridauthSession();
|
||||
@@ -66,13 +67,12 @@ return function (Handler $handler) {
|
||||
$adapter = $hybridauth->getAdapter($doing);
|
||||
|
||||
try {
|
||||
if (!$adapter->isConnected()) {
|
||||
if (! $adapter->isConnected()) {
|
||||
$adapter->authenticate();
|
||||
} else {
|
||||
}
|
||||
} catch (InvalidAuthorizationStateException) {
|
||||
$session->clear();
|
||||
redirect('connect/' . $doing);
|
||||
redirect('connect/' . $doing, 302);
|
||||
}
|
||||
if ($adapter->isConnected()) {
|
||||
$user = $logged_user;
|
||||
@@ -87,11 +87,11 @@ return function (Handler $handler) {
|
||||
}
|
||||
if ($connectedUserId != ($user['id'] ?? 0)) {
|
||||
Login::logout();
|
||||
redirect('connect/' . $doing);
|
||||
redirect('connect/' . $doing, 302);
|
||||
}
|
||||
}
|
||||
if ($user === []) {
|
||||
if (!Settings::get('enable_signups')) {
|
||||
if (! Settings::get('enable_signups')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -101,11 +101,11 @@ return function (Handler $handler) {
|
||||
foreach ($user_matches[0] as $match) {
|
||||
$username .= $match;
|
||||
}
|
||||
$baseUsername = substr(strtolower($username), 0, (int) getSetting('username_max_length'));
|
||||
$baseUsername = substr(strtolower($username), 0, (int) Settings::USERNAME_MAX_LENGTH);
|
||||
$username = $baseUsername;
|
||||
$j = 1;
|
||||
while (!User::isValidUsername($username)) {
|
||||
if (strlen($username) > getSetting('username_max_length')) {
|
||||
while (! User::isValidUsername($username)) {
|
||||
if (strlen($username) > Settings::USERNAME_MAX_LENGTH) {
|
||||
$username = substr($baseUsername, 0, -strlen(strval($j))) . $j;
|
||||
} else {
|
||||
$username .= $j;
|
||||
@@ -114,7 +114,7 @@ return function (Handler $handler) {
|
||||
}
|
||||
$i = 1;
|
||||
while (User::getSingle($username, 'username', false)) {
|
||||
if (strlen($username) > getSetting('username_max_length')) {
|
||||
if (strlen($username) > Settings::USERNAME_MAX_LENGTH) {
|
||||
$username = substr($baseUsername, 0, -strlen(strval($i))) . $i;
|
||||
} else {
|
||||
$username .= $i;
|
||||
@@ -132,9 +132,6 @@ return function (Handler $handler) {
|
||||
'language' => L10n::getLocale(),
|
||||
];
|
||||
$insert_user_values = array_filter($insert_user_values);
|
||||
// if (in_array($doing, ['twitter', 'facebook'])) {
|
||||
// $insert_user_values[$doing . '_username'] = $connectProfile->displayName;
|
||||
// }
|
||||
$inserted_user = User::insert($insert_user_values);
|
||||
$user = User::getSingle($inserted_user, 'id', true);
|
||||
}
|
||||
@@ -169,10 +166,10 @@ return function (Handler $handler) {
|
||||
? $user['url']
|
||||
: 'settings/connections#' . $doing
|
||||
);
|
||||
redirect($redirectTo);
|
||||
redirect($redirectTo, 302);
|
||||
}
|
||||
|
||||
redirect('');
|
||||
redirect('', 302);
|
||||
|
||||
die();
|
||||
exit();
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,34 +12,41 @@
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
$logged_user = Login::getUser();
|
||||
if (!$handler::cond('explore_enabled') && !($logged_user['is_content_manager'] ?? false)) {
|
||||
if (! $handler::cond('explore_enabled') && ! ($logged_user['is_content_manager'] ?? false)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$doing = $handler->request()[0] ?? null;
|
||||
$baseUrlRouteName = get_base_url(get_route_name());
|
||||
if (!isset($doing)
|
||||
if (! isset($doing)
|
||||
&& getSetting('homepage_style') == 'route_explore'
|
||||
&& str_contains(get_current_url(), $baseUrlRouteName)
|
||||
) {
|
||||
$redirect = str_replace_first($baseUrlRouteName, get_base_url(), get_current_url());
|
||||
redirect($redirect);
|
||||
$redirect = str_replace_first(
|
||||
$baseUrlRouteName,
|
||||
get_base_url(),
|
||||
get_current_url()
|
||||
);
|
||||
headersNoCache();
|
||||
redirect($redirect, 302);
|
||||
}
|
||||
$explore_semantics = $handler::var('explore_semantics');
|
||||
if (isset($doing) && !array_key_exists($doing, $explore_semantics)) {
|
||||
$explore_discovery = $handler::var('explore_discovery') + $handler::var('explore_content');
|
||||
if (isset($doing) && ! array_key_exists($doing, $explore_discovery)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -55,30 +62,59 @@ return function (Handler $handler) {
|
||||
if ($doing) {
|
||||
$basename .= ($basename ? '/' : '') . $doing;
|
||||
}
|
||||
$list = isset($doing) ? $explore_semantics[$doing] : ['label' => _s('Explore'), 'icon' => 'fas fa-images'];
|
||||
$list['list'] = is_null($doing) ? get_route_name() : $doing;
|
||||
$list = isset($doing) ? $explore_discovery[$doing] : [
|
||||
'label' => _s('Explore'),
|
||||
'icon' => 'fas fa-compass',
|
||||
];
|
||||
|
||||
$list['list'] = $doing === null
|
||||
? get_route_name()
|
||||
: $doing;
|
||||
$doing ??= 'images';
|
||||
$listingParams = [
|
||||
'listing' => $list['list'],
|
||||
'basename' => $basename,
|
||||
'params_hidden' => [
|
||||
'hide_empty' => 1,
|
||||
'hide_banned' => 1,
|
||||
'album_min_image_count' => getSetting('explore_albums_min_image_count'),
|
||||
],
|
||||
];
|
||||
if ($listingParams['listing'] === 'albums') {
|
||||
$listingParams['params_hidden']['album_min_image_count'] = getSetting('explore_albums_min_image_count');
|
||||
}
|
||||
if ($doing == 'animated') {
|
||||
$listingParams['params_hidden']['is_animated'] = 1;
|
||||
$listingParams['params_hidden'] = array_merge($listingParams['params_hidden'], [
|
||||
'is_animated' => 1,
|
||||
'is_image' => 1,
|
||||
'is_video' => 0,
|
||||
]);
|
||||
}
|
||||
if ($doing == 'videos') {
|
||||
$listingParams['params_hidden']['is_video'] = 1;
|
||||
$listingParams['params_hidden'] = array_merge($listingParams['params_hidden'], [
|
||||
'is_image' => 0,
|
||||
'is_video' => 1,
|
||||
]);
|
||||
}
|
||||
$getParams = Listing::getParams(request());
|
||||
if ($doing == 'images') {
|
||||
$listingParams['params_hidden'] = array_merge($listingParams['params_hidden'], [
|
||||
'is_image' => 1,
|
||||
'is_video' => 0,
|
||||
]);
|
||||
}
|
||||
$request = request();
|
||||
$getParams = Listing::getParams(
|
||||
request: $request,
|
||||
type: $request['list'] ?? $doing
|
||||
);
|
||||
$tabs = Listing::getTabs($listingParams, $getParams, true);
|
||||
$currentKey = $tabs['currentKey'];
|
||||
$type = $tabs['tabs'][$currentKey]['type'];
|
||||
$tabs = $tabs['tabs'];
|
||||
parse_str($tabs[$currentKey]['params'], $tabs_params);
|
||||
$getParams['sort'] = explode('_', $tabs_params['sort']); // Hack this stuff
|
||||
parse_str($tabs[$currentKey]['params'], $tab_params);
|
||||
$fix_sort = explode('_', $tab_params['sort']);
|
||||
if (count($fix_sort) == 2) {
|
||||
$getParams['sort'] = $fix_sort;
|
||||
}
|
||||
$handler::setVar('list_params', $getParams);
|
||||
$listing = new Listing();
|
||||
$listing->setType($type);
|
||||
@@ -109,4 +145,6 @@ return function (Handler $handler) {
|
||||
$handler::setVar('user_items_editor', false);
|
||||
}
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
$canonical = get_public_url($tabs[$currentKey]['url']);
|
||||
$handler::setVar('canonical', $canonical);
|
||||
};
|
||||
|
||||
@@ -11,22 +11,27 @@
|
||||
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (version_compare(getSetting('chevereto_version_installed'), '3.7.0', '<') || !getSetting('enable_followers')) {
|
||||
if (version_compare(cheveretoVersionInstalled(), '3.7.0', '<')
|
||||
|| ! getSetting('enable_followers')
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
if ($logged_user === []) {
|
||||
redirect('login');
|
||||
headersNoCache();
|
||||
redirect('login', 302);
|
||||
}
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
$handler->issueError(404);
|
||||
@@ -37,7 +42,9 @@ return function (Handler $handler) {
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => 'images',
|
||||
'exclude_criterias' => ['most-oldest'],
|
||||
'params_hidden' => ['follow_user_id' => encodeID((int) $logged_user['id'])],
|
||||
'params_hidden' => [
|
||||
'follow_user_id' => encodeID((int) $logged_user['id']),
|
||||
],
|
||||
], $getParams);
|
||||
$where = 'WHERE follow_user_id=:user_id';
|
||||
$handler::setVar('list_params', $getParams);
|
||||
@@ -55,7 +62,7 @@ return function (Handler $handler) {
|
||||
$listing->setSortOrder($getParams['sort'][1]); // asc | desc
|
||||
$listing->setRequester(Login::getUser());
|
||||
$listing->setWhere($where);
|
||||
$listing->bind(":user_id", $logged_user['id']);
|
||||
$listing->bind(':user_id', $logged_user['id']);
|
||||
$listing->exec();
|
||||
$handler::setVar('pre_doctitle', _s('Following'));
|
||||
$handler::setVar('tabs', $tabs);
|
||||
|
||||
@@ -14,29 +14,30 @@ use Chevereto\Legacy\Classes\Image;
|
||||
use Chevereto\Legacy\Classes\IpBan;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
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;
|
||||
use function Chevereto\Legacy\G\include_theme_file;
|
||||
use function Chevereto\Legacy\G\is_animated_image;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\require_theme_file;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getComments;
|
||||
use function Chevereto\Legacy\getFriendlyExif;
|
||||
use function Chevereto\Legacy\getIdFromURLComponent;
|
||||
use function Chevereto\Legacy\getIpButtonsArray;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Legacy\isShowEmbedContent;
|
||||
use function Chevereto\Legacy\redirectIfRouting;
|
||||
use function Chevereto\Legacy\virtualRouteHandleRedirect;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
redirectIfRouting('image', $handler->requestArray()[0]);
|
||||
virtualRouteHandleRedirect('image', $handler->requestArray()[0]);
|
||||
$imageIndex = getSetting('root_route') === 'image'
|
||||
? 0
|
||||
: 1;
|
||||
@@ -54,18 +55,23 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (!isset(session()['image_view_stock'])) {
|
||||
if (! isset(session()['image_view_stock'])) {
|
||||
sessionVar()->put('image_view_stock', []);
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
$image = Image::getSingle($id, !in_array($id, session()['image_view_stock']), true, $logged_user);
|
||||
if ($image === [] || !isset($image['url'])) {
|
||||
$image = Image::getSingle(
|
||||
$id,
|
||||
! in_array($id, session()['image_view_stock']),
|
||||
true,
|
||||
$logged_user
|
||||
);
|
||||
if ($image === [] || ! isset($image['url'])) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
&& ($image['user']['id'] ?? 'not-found') != getSetting('website_mode_personal_uid')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
@@ -76,7 +82,7 @@ return function (Handler $handler) {
|
||||
$password = $request_handle[2] ?? '';
|
||||
if (Image::verifyPassword($id, $password)) {
|
||||
Image::delete($id);
|
||||
redirect($image['path_viewer'] . '?deleted');
|
||||
redirect($image['path_viewer'] . '?deleted', 301);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,56 +90,65 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (!$image['is_approved'] && (!($logged_user['is_manager'] ?? false) && !($logged_user['is_admin'] ?? false))) {
|
||||
if (! $image['is_approved']
|
||||
&& (! ($logged_user['is_manager'] ?? false) && ! ($logged_user['is_admin'] ?? false))
|
||||
) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($image['path_viewer'] != get_current_url(true, ['lang'])) {
|
||||
redirect($image['path_viewer']);
|
||||
redirect($image['path_viewer'], 302);
|
||||
}
|
||||
$handler::setVar('canonical', $image['url_viewer']);
|
||||
if ((!$handler::cond('content_manager')
|
||||
if ((! $handler::cond('content_manager')
|
||||
&& ($image['user']['status'] ?? null) == 'banned')
|
||||
) {
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
sessionVar()->put('last_viewed_image', encodeID((int) $id));
|
||||
if ($image['file_resource']['type'] == 'path' && (!$image['is_animated'] && isset($image['file_resource']['chain']['image']) && is_animated_image($image['file_resource']['chain']['image']))) {
|
||||
Image::update($id, ['is_animated' => 1]);
|
||||
$image['is_animated'] = 1;
|
||||
}
|
||||
|
||||
$is_owner = isset($image['user']['id']) ? ($image['user']['id'] == ($logged_user['id'] ?? null)) : false;
|
||||
if (getSetting('website_privacy_mode') == 'private') {
|
||||
if ($handler::cond('forced_private_mode')) {
|
||||
$image['album']['privacy'] = getSetting('website_content_privacy_mode');
|
||||
}
|
||||
if (!Login::getUser() && ($image['album']['privacy'] ?? null) != 'private_but_link') {
|
||||
redirect('login');
|
||||
if (! Login::getUser()
|
||||
&& ($image['album']['privacy'] ?? null) != 'private_but_link'
|
||||
) {
|
||||
headersNoCache();
|
||||
redirect('login', 302);
|
||||
}
|
||||
}
|
||||
if (!$handler::cond('content_manager') && !$is_owner && ($image['album']['privacy'] ?? null) == 'password' && !Album::checkSessionPassword($image['album'])) {
|
||||
if (! $handler::cond('content_manager')
|
||||
&& ! $is_owner
|
||||
&& ($image['album']['privacy'] ?? null) == 'password'
|
||||
&& ! Album::checkSessionPassword($image['album'])
|
||||
) {
|
||||
sessionVar()->put('redirect_password_to', $image['path_viewer']);
|
||||
redirect($image['album']['url']);
|
||||
headersNoCache();
|
||||
redirect($image['album']['url'], 302);
|
||||
}
|
||||
if (isset($image['user']['is_private'])
|
||||
&& $image['user']['is_private'] == 1
|
||||
&& !$handler::cond('content_manager')
|
||||
&& ! $handler::cond('content_manager')
|
||||
&& $image['user']['id'] != ($logged_user['id'] ?? null)
|
||||
) {
|
||||
unset($image['user']);
|
||||
$image['user'] = User::getPrivate();
|
||||
}
|
||||
if (!$handler::cond('content_manager') && in_array($image['album']['privacy'] ?? null, ['private', 'custom']) && !$is_owner) {
|
||||
if (! $handler::cond('content_manager')
|
||||
&& in_array($image['album']['privacy'] ?? null, ['private', 'custom'])
|
||||
&& ! $is_owner
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (isset($image['user']['id'])) {
|
||||
$image['user']['albums'] = User::getAlbums((int) $image["user"]["id"]);
|
||||
if (isset($image['user']['id'])
|
||||
&& ($handler::cond('content_manager') || $is_owner)) {
|
||||
$image['user']['albums'] = User::getAlbums((int) $image['user']['id']);
|
||||
}
|
||||
$is_album_cover = false;
|
||||
if (isset($image['album']['id'])) {
|
||||
@@ -154,6 +169,7 @@ return function (Handler $handler) {
|
||||
'label' => _s('About'),
|
||||
'id' => 'tab-about',
|
||||
'current' => true,
|
||||
'url' => '#about',
|
||||
];
|
||||
$comments = getComments();
|
||||
if ($comments !== '') {
|
||||
@@ -161,6 +177,7 @@ return function (Handler $handler) {
|
||||
'icon' => 'fas fa-comments',
|
||||
'label' => _s('Comments'),
|
||||
'id' => 'tab-comments',
|
||||
'url' => '#comments',
|
||||
];
|
||||
}
|
||||
$handler::setVar('comments', $comments);
|
||||
@@ -169,17 +186,34 @@ return function (Handler $handler) {
|
||||
'icon' => 'fas fa-code',
|
||||
'label' => _s('Embed codes'),
|
||||
'id' => 'tab-embeds',
|
||||
'url' => '#embeds',
|
||||
];
|
||||
}
|
||||
$image_exif = [];
|
||||
if (getSetting('theme_show_exif_data')) {
|
||||
$image_exif = getFriendlyExif($image['original_exifdata']) ?? [];
|
||||
if ($image_exif !== []) {
|
||||
$tabs[] = [
|
||||
'icon' => 'fas fa-camera',
|
||||
'label' => _s('EXIF data'),
|
||||
'id' => 'tab-exif',
|
||||
'url' => '#exif',
|
||||
];
|
||||
}
|
||||
}
|
||||
$handler::setVar('image_exif', $image_exif);
|
||||
if ($handler::cond('content_manager')) {
|
||||
if ($handler::cond('admin')) {
|
||||
$tabs[] = [
|
||||
'icon' => 'fas fa-info-circle',
|
||||
'label' => _s('Info'),
|
||||
'id' => 'tab-info',
|
||||
'url' => '#info',
|
||||
];
|
||||
}
|
||||
$bannedIp = IpBan::getSingle(['ip' => $image['uploader_ip']]);
|
||||
$bannedIp = IpBan::getSingle([
|
||||
'ip' => $image['uploader_ip'],
|
||||
]);
|
||||
$image_admin_list_values = [
|
||||
[
|
||||
'label' => _s('Image ID'),
|
||||
@@ -199,12 +233,11 @@ return function (Handler $handler) {
|
||||
$handler::setVar('image_admin_list_values', $image_admin_list_values);
|
||||
$handler::setCond('banned_ip', $bannedIp !== []);
|
||||
}
|
||||
// tab-embeds, tab-about, tab-info
|
||||
$firstTabSetting = getSetting('image_first_tab');
|
||||
if (!$handler::cond('admin') && $firstTabSetting == 'info') {
|
||||
if (! $handler::cond('admin') && $firstTabSetting == 'info') {
|
||||
$firstTabSetting = 'embeds';
|
||||
}
|
||||
if (!isShowEmbedContent() && $firstTabSetting == 'embeds') {
|
||||
if (! isShowEmbedContent() && $firstTabSetting == 'embeds') {
|
||||
$firstTabSetting = 'about';
|
||||
}
|
||||
if ($comments === '' && $firstTabSetting == 'comments') {
|
||||
@@ -247,14 +280,14 @@ return function (Handler $handler) {
|
||||
$meta_description = $image['description'];
|
||||
} else {
|
||||
$image_tr = [
|
||||
'%i' => $image[is_null($image['title']) ? 'filename' : 'title'],
|
||||
'%i' => $image[$image['title'] === null ? 'filename' : 'title'],
|
||||
'%a' => $image['album']['name'] ?? '',
|
||||
'%w' => getSetting('website_name'),
|
||||
'%c' => $image['category']['name'] ?? '',
|
||||
];
|
||||
if (isset($image['album']['id'])
|
||||
|| (
|
||||
!((bool) ($image['user']['is_private'] ?? false)) && isset($image['album']['name'])
|
||||
! ((bool) ($image['user']['is_private'] ?? false)) && isset($image['album']['name'])
|
||||
)) {
|
||||
$meta_description = _s('Image %i in %a album', $image_tr);
|
||||
} elseif (isset($image['category']['id'])) {
|
||||
@@ -263,7 +296,7 @@ return function (Handler $handler) {
|
||||
$meta_description = _s('Image %i hosted in %w', $image_tr);
|
||||
}
|
||||
}
|
||||
$handler::setVar('meta_description', htmlspecialchars($meta_description ?? ''));
|
||||
$handler::setVar('meta_description', $meta_description ?? '');
|
||||
if ($handler::cond('content_manager') || $is_owner) {
|
||||
$handler::setVar('user_items_editor', [
|
||||
'user_albums' => $image['user']['albums'] ?? null,
|
||||
@@ -274,7 +307,7 @@ return function (Handler $handler) {
|
||||
}
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
$handler::setVar('privacy', $image['album']['privacy'] ?? '');
|
||||
include_theme_file('snippets/embed');
|
||||
require_theme_file('snippets/embed');
|
||||
$embed_share_tpl = get_global('embed_share_tpl');
|
||||
$sharing = [];
|
||||
foreach (flatten_array($image) as $imageKey => $imageValue) {
|
||||
@@ -291,7 +324,7 @@ return function (Handler $handler) {
|
||||
$groupLabel = $group['label'];
|
||||
foreach ($group['options'] as $option => $optionValue) {
|
||||
foreach ($hasSizes as $sizeKey => $sizeValue) {
|
||||
if (!$sizeValue && str_starts_with($option, $sizeKey . '-')) {
|
||||
if (! $sizeValue && str_starts_with($option, $sizeKey . '-')) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
@@ -309,19 +342,32 @@ return function (Handler $handler) {
|
||||
$label = $optionValue['label'];
|
||||
$label = str_ireplace($groupLabel, '', $label);
|
||||
$label = ucfirst(trim($label));
|
||||
$entries[] = [
|
||||
$entry = [
|
||||
'label' => $label,
|
||||
'value' => $value,
|
||||
'id' => $option
|
||||
'id' => $option,
|
||||
];
|
||||
if ($code === 'links'
|
||||
&& ! in_array($option, ['viewer-links', 'delete-links'])
|
||||
) {
|
||||
$entry['url_download'] = $value;
|
||||
}
|
||||
$entries[] = $entry;
|
||||
}
|
||||
$embed[$code] = [
|
||||
'label' => $group['label'],
|
||||
'entries' => $entries
|
||||
'entries' => $entries,
|
||||
];
|
||||
}
|
||||
$handler::setVar('oembed', [
|
||||
'title' => $handler::var('pre_doctitle'),
|
||||
'url' => $image['url_viewer'],
|
||||
]);
|
||||
$handler::setVar('embed', $embed);
|
||||
$addValue = session()['image_view_stock'] ?? [];
|
||||
$addValue[] = $id;
|
||||
sessionVar()->put('image_view_stock', $addValue);
|
||||
if ($image['tags_string'] !== '') {
|
||||
$handler::setVar('meta_keywords', $image['tags_string']);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!Login::isAdmin()) {
|
||||
if (! Login::isAdmin()) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -25,18 +25,18 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (is_null($handler->request()[0] ?? null) || is_null($handler->request()[1] ?? null)) {
|
||||
if (null === ($handler->request()[0] ?? null) || null === ($handler->request()[1] ?? null)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$filepath = Import::PATH_JOBS . sprintf('%1$s/%2$s.txt', $handler->request()[0], $handler->request()[1]);
|
||||
if (!file_exists($filepath)) {
|
||||
if (! file_exists($filepath)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!headers_sent()) {
|
||||
if (! headers_sent()) {
|
||||
header('Content-Type: text/plain');
|
||||
}
|
||||
readfile($filepath);
|
||||
|
||||
@@ -15,16 +15,17 @@ use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\decodeID;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\random_values;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\starts_with;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\request;
|
||||
@@ -34,7 +35,9 @@ use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
parse_str(server()['QUERY_STRING'] ?? '', $querystr);
|
||||
if (key($querystr) != 'random' && starts_with('route_', Settings::get('homepage_style'))) {
|
||||
if (key($querystr) !== 'random'
|
||||
&& starts_with('route_', Settings::get('homepage_style'))
|
||||
) {
|
||||
$route = str_replace_first('route_', '', Settings::get('homepage_style'));
|
||||
$handler->mapRoute($route);
|
||||
$routeCallable = include PATH_APP_LEGACY_ROUTES . $route . '.php';
|
||||
@@ -46,25 +49,27 @@ return function (Handler $handler) {
|
||||
if (server()['QUERY_STRING'] ?? false) {
|
||||
switch (key($querystr)) {
|
||||
case 'random':
|
||||
if (!$handler::cond('random_enabled')) {
|
||||
redirect('/');
|
||||
headersNoCache();
|
||||
if (! $handler::cond('random_enabled')) {
|
||||
redirect('', 302);
|
||||
}
|
||||
$tables = DB::getTables();
|
||||
$db = DB::getInstance();
|
||||
$db->query('SELECT MIN(image_id) as min, MAX(image_id) as max FROM ' . $tables['images']);
|
||||
$limit = $db->fetchSingle();
|
||||
$random_ids = random_values((int) $limit['min'], (int) $limit['max'], 100);
|
||||
if (count($random_ids) == 1) {
|
||||
if (count($random_ids) === 1) {
|
||||
$random_ids[] = $random_ids[0];
|
||||
}
|
||||
if ($limit['min'] !== $limit['max']) {
|
||||
$last_viewed_image = decodeID(session()['last_viewed_image'] ?? '');
|
||||
if (($key = array_search($last_viewed_image, $random_ids)) !== false) {
|
||||
$key = array_search($last_viewed_image, $random_ids, true);
|
||||
if ($key !== false) {
|
||||
unset($random_ids[$key]);
|
||||
}
|
||||
}
|
||||
$query = 'SELECT image_id FROM ' . $tables['images'] . ' LEFT JOIN ' . $tables['albums'] . ' ON ' . $tables['images'] . '.image_album_id = ' . $tables['albums'] . '.album_id WHERE image_is_approved = 1 AND image_id IN (' . implode(',', $random_ids) . ") AND (album_privacy = 'public' OR album_privacy IS NULL) ";
|
||||
if (!getSetting('show_nsfw_in_random_mode')) {
|
||||
if (! getSetting('show_nsfw_in_random_mode')) {
|
||||
if ($logged_user) {
|
||||
$query .= 'AND (' . $tables['images'] . '.image_nsfw = 0 OR ' . $tables['images'] . '.image_user_id = ' . $logged_user['id'] . ') ';
|
||||
} else {
|
||||
@@ -74,24 +79,24 @@ return function (Handler $handler) {
|
||||
if ($handler::cond('forced_private_mode')) {
|
||||
$query .= 'AND ' . $tables['images'] . '.image_user_id = ' . $logged_user['id'] . ' ';
|
||||
}
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS']) {
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_USERS']) {
|
||||
$query .= 'AND ' . $tables['images'] . '.image_user_id=' . (getSetting('website_mode_personal_uid') ?? 0) . ' ';
|
||||
}
|
||||
$query .= 'ORDER BY RAND() LIMIT 1';
|
||||
$db->query($query);
|
||||
$fetch = $db->fetchSingle();
|
||||
if (!$fetch) {
|
||||
if (! $fetch) {
|
||||
$image = false;
|
||||
} else {
|
||||
$imageId = (int) $fetch['image_id'];
|
||||
$image = Image::getSingle(id: $imageId, pretty: true);
|
||||
if (!isset($image['file_resource']['chain']['image'])) {
|
||||
if (! isset($image['file_resource']['chain']['image'])) {
|
||||
$image = false;
|
||||
}
|
||||
}
|
||||
if (!$image) {
|
||||
if (! $image) {
|
||||
if ((session()['random_failure'] ?? 0) > 3) {
|
||||
redirect();
|
||||
redirect('', 302);
|
||||
} else {
|
||||
sessionVar()->put('random_failure', (session()['random_failure'] ?? 0) + 1);
|
||||
}
|
||||
@@ -100,21 +105,23 @@ return function (Handler $handler) {
|
||||
sessionVar()->remove('random_failure');
|
||||
}
|
||||
}
|
||||
redirect(
|
||||
$image
|
||||
? $image['path_viewer']
|
||||
: '?random'
|
||||
);
|
||||
$redirectTo = $image
|
||||
? $image['path_viewer']
|
||||
: '?random';
|
||||
redirect($redirectTo, 302);
|
||||
|
||||
return;
|
||||
case 'v':
|
||||
if (preg_match('{^\w*\.jpg|png|gif$}', get()['v'] ?? '')) {
|
||||
$explode = array_filter(explode('.', get()['v']));
|
||||
if (count($explode) == 2) {
|
||||
$image = DB::get('images', ['name' => $explode[0], 'extension' => $explode[1]], 'AND', [], 1) ?: [];
|
||||
if (count($explode) === 2) {
|
||||
$image = DB::get('images', [
|
||||
'name' => $explode[0],
|
||||
'extension' => $explode[1],
|
||||
], 'AND', [], 1) ?: [];
|
||||
if ($image !== []) {
|
||||
$image = Image::formatArray($image);
|
||||
redirect($image['path_viewer']);
|
||||
redirect($image['path_viewer'], 301);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +129,6 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
case 'list':
|
||||
$handler->setTemplate('index');
|
||||
|
||||
@@ -138,7 +144,7 @@ return function (Handler $handler) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Settings::get('homepage_style') == 'split') {
|
||||
if (Settings::get('homepage_style') === 'split') {
|
||||
$tabs = [
|
||||
[
|
||||
'tools' => true,
|
||||
@@ -147,22 +153,28 @@ return function (Handler $handler) {
|
||||
'type' => 'image',
|
||||
],
|
||||
];
|
||||
$home_uids = getSetting('homepage_uids');
|
||||
$home_uid_is_null = ($home_uids == '' || $home_uids == '0');
|
||||
$home_uid_arr = $home_uid_is_null ? false : explode(',', $home_uids);
|
||||
$home_uids = getSetting('homepage_uids') ?? '';
|
||||
$home_uids = trim($home_uids);
|
||||
$home_uid_is_null = $home_uids === '' || $home_uids === '0';
|
||||
$home_uid_arr = $home_uid_is_null
|
||||
? false
|
||||
: explode(',', $home_uids);
|
||||
if (is_array($home_uid_arr)) {
|
||||
$home_uid_arr = array_filter($home_uid_arr);
|
||||
$home_uid_bind = [];
|
||||
foreach ($home_uid_arr as $k => $v) {
|
||||
$home_uid_bind[] = ':user_id_' . $k;
|
||||
if ($v == 0) {
|
||||
$home_uid_is_null = true;
|
||||
if (! is_numeric($v)) {
|
||||
continue;
|
||||
}
|
||||
$home_uid_bind[] = ':user_id_' . $k;
|
||||
}
|
||||
$home_uid_bind = implode(',', $home_uid_bind);
|
||||
}
|
||||
$doing = is_array($home_uid_arr) ? 'recent' : 'trending';
|
||||
$explore_semantics = $handler::var('explore_semantics');
|
||||
$list = $explore_semantics[$doing];
|
||||
$doing = is_array($home_uid_arr)
|
||||
? 'recent'
|
||||
: 'trending';
|
||||
$explore_discovery = $handler::var('explore_discovery');
|
||||
$list = $explore_discovery[$doing];
|
||||
$list['list'] = $doing;
|
||||
$getParams = Listing::getParams(request());
|
||||
$listing = new Listing();
|
||||
@@ -187,7 +199,7 @@ return function (Handler $handler) {
|
||||
$listing->setParamsHidden($listingParams['params_hidden']);
|
||||
if (is_array($home_uid_arr)) {
|
||||
foreach ($tabs as $k => &$v) {
|
||||
if ($v['type'] == 'users') {
|
||||
if ($v['type'] === 'users') {
|
||||
unset($tabs[$k]);
|
||||
}
|
||||
}
|
||||
@@ -227,26 +239,29 @@ return function (Handler $handler) {
|
||||
$handler::setVar('user_items_editor', false);
|
||||
}
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
|
||||
$button_color = Settings::get('homepage_cta_color') ?: 'accent';
|
||||
if (getSetting('homepage_cta_outline')) {
|
||||
$button_color .= ' outline';
|
||||
}
|
||||
$homepage_cta = [
|
||||
'<a',
|
||||
getSetting('homepage_cta_fn') == 'cta-upload'
|
||||
getSetting('homepage_cta_fn') === 'cta-upload'
|
||||
? (
|
||||
getSetting('upload_gui') == 'js' && Handler::cond('upload_allowed')
|
||||
getSetting('upload_gui') === 'js' && Handler::cond('upload_allowed')
|
||||
? 'data-trigger="anywhere-upload-input"'
|
||||
: 'href="' . get_base_url('upload') . '"'
|
||||
)
|
||||
: 'href="'
|
||||
. getSetting('homepage_cta_fn_extra')
|
||||
. '"',
|
||||
(getSetting('homepage_cta_fn') == 'cta-upload' && !getSetting('guest_uploads'))
|
||||
(getSetting('homepage_cta_fn') === 'cta-upload' && ! getSetting('guest_uploads'))
|
||||
? 'data-login-needed="true"'
|
||||
: '',
|
||||
'class="btn btn-big accent ' . getSetting('homepage_cta_color') . '">'
|
||||
'class="btn btn-big ' . $button_color . '">'
|
||||
. (getSetting('homepage_cta_html')
|
||||
?: '<i class="fas fa-cloud-upload-alt"></i><span class="btn-text">'
|
||||
. _s('Start uploading') . '</span>')
|
||||
. '</a>'
|
||||
. '</a>',
|
||||
];
|
||||
$handler::setVar('homepage_cta', join(' ', $homepage_cta));
|
||||
$handler::setVar('homepage_cta', implode(' ', $homepage_cta));
|
||||
};
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (Settings::get('chevereto_version_installed') !== null) {
|
||||
if (cheveretoVersionInstalled() !== '') {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,12 +9,12 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\TwoFactor;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\must_use_captcha;
|
||||
@@ -25,7 +25,7 @@ use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (post() !== [] && !$handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
if (post() !== [] && ! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -38,27 +38,30 @@ return function (Handler $handler) {
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
if ($logged_user) {
|
||||
redirect(User::getUrl($logged_user));
|
||||
redirect(User::getUrl($logged_user), 302);
|
||||
}
|
||||
$request_log_insert = ['type' => 'login', 'user_id' => null];
|
||||
$request_log_insert = [
|
||||
'type' => 'login',
|
||||
'user_id' => null,
|
||||
];
|
||||
$failed_access_requests = $handler::var('failed_access_requests');
|
||||
$SAFE_POST = $handler::var('safe_post');
|
||||
$is_error = false;
|
||||
$captcha_needed = $handler::cond('captcha_needed');
|
||||
$error_message = null;
|
||||
if ($captcha_needed && !empty(post())) {
|
||||
if ($captcha_needed && ! empty(post())) {
|
||||
$captcha = captcha_check();
|
||||
if (!$captcha->is_valid) {
|
||||
if (! $captcha->is_valid) {
|
||||
$is_error = true;
|
||||
$error_message = _s('%s says you are a robot', 'CAPTCHA');
|
||||
}
|
||||
}
|
||||
if (post() !== [] && !$is_error) {
|
||||
if (post() !== [] && ! $is_error) {
|
||||
$login_by = filter_var(post()['login-subject'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
|
||||
if (trim(post()['login-subject']) == '' || trim(post()['password']) == '') {
|
||||
$is_error = true;
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
$user = User::getSingle(
|
||||
trim(post()['login-subject']),
|
||||
$login_by,
|
||||
@@ -71,9 +74,9 @@ return function (Handler $handler) {
|
||||
case 'awaiting-confirmation':
|
||||
Login::setSignup([
|
||||
'status' => 'awaiting-confirmation',
|
||||
'email' => $user['email']
|
||||
'email' => $user['email'],
|
||||
]);
|
||||
redirect('account/awaiting-confirmation');
|
||||
redirect('account/awaiting-confirmation', 302);
|
||||
|
||||
break;
|
||||
case 'banned':
|
||||
@@ -81,7 +84,7 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
$is_login = !(bool) env()['CHEVERETO_ENABLE_USERS'] && getSetting('website_mode_personal_uid') != $user['id']
|
||||
$is_login = ! (bool) env()['CHEVERETO_ENABLE_USERS'] && getSetting('website_mode_personal_uid') != $user['id']
|
||||
? false
|
||||
: Login::checkPassword($user['id'], post()['password']);
|
||||
}
|
||||
@@ -90,7 +93,7 @@ return function (Handler $handler) {
|
||||
RequestLog::insert($request_log_insert);
|
||||
$logged_user = Login::login($user['id']);
|
||||
Login::insertCookie('cookie', $user['id']);
|
||||
$redirect_to = User::getUrl(Login::getUser());
|
||||
$redirect_to = User::getUrl(Login::getUser(), true);
|
||||
if (TwoFactor::hasFor($user['id'])) {
|
||||
sessionVar()->put('challenge_two_factor', $user['id']);
|
||||
$redirect_to = 'account/two-factor';
|
||||
@@ -101,7 +104,7 @@ return function (Handler $handler) {
|
||||
$redirect_to = 'account/email-needed';
|
||||
}
|
||||
|
||||
redirect($redirect_to);
|
||||
redirect($redirect_to, 302);
|
||||
} else {
|
||||
$is_error = true;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!$handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
if (! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!$handler::cond('content_manager')) {
|
||||
if (! $handler::cond('content_manager')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_MODERATION']) {
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_MODERATION']) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
$list = ['label' => _s('Moderate'), 'icon' => 'fas fa-check-double'];
|
||||
$list = [
|
||||
'label' => _s('Moderate'),
|
||||
'icon' => 'fas fa-check-double',
|
||||
];
|
||||
$list['list'] = get_route_name();
|
||||
$listingParams = [
|
||||
'listing' => $list['list'],
|
||||
@@ -40,7 +43,7 @@ return function (Handler $handler) {
|
||||
'album_min_image_count' => 0,
|
||||
],
|
||||
'exclude_criterias' => ['most-viewed', 'most-liked'],
|
||||
'order' => ['most-oldest', 'most-recent']
|
||||
'order' => ['most-oldest', 'most-recent'],
|
||||
];
|
||||
$getParams = Listing::getParams(request());
|
||||
$tabs = Listing::getTabs($listingParams, $getParams, true);
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
use Chevereto\Legacy\Classes\Image;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\json_output;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\json_document_output;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\G\set_status_header;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\G\str_replace_last;
|
||||
use function Chevereto\Legacy\G\xml_output;
|
||||
use function Chevereto\Legacy\G\xml_document_output;
|
||||
use function Chevereto\Legacy\getIdFromURLComponent;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Vars\get;
|
||||
@@ -30,32 +30,32 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
$viewer = Image::getUrlViewer('%id');
|
||||
$viewer = str_replace('/', '\/', $viewer);
|
||||
$regex = str_replace_last('%id', '(.*)', $viewer);
|
||||
$viewerImage = Image::getUrlViewer(type: 'image', id_encoded: '%id');
|
||||
$viewerImage = str_replace('/', '\/', $viewerImage);
|
||||
$regex = str_replace_last('%id', '(.*)', $viewerImage);
|
||||
$regex = str_replace_first('https:', 'https?:', $regex);
|
||||
$regex = str_replace_first('http:', 'https?:', $regex);
|
||||
if (!preg_match('#^' . $regex . '$#', get()['url'] ?? '', $matches)) {
|
||||
if (! preg_match('#^' . $regex . '$#', get()['url'] ?? '', $matches)) {
|
||||
set_status_header(403);
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
$id = getIdFromURLComponent($matches[1]);
|
||||
if ($id == 0) {
|
||||
set_status_header(404);
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
$image = Image::getSingle(id: $id, pretty: true);
|
||||
if ($image === []) {
|
||||
set_status_header(404);
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
if (!$image['is_approved']) {
|
||||
if (! $image['is_approved']) {
|
||||
set_status_header(403);
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
if (in_array($image['album']['privacy'] ?? '', ['password', 'private', 'custom'])) {
|
||||
set_status_header(401);
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
if (($image['user']['is_private'] ?? false) == 1) {
|
||||
unset($image['user']);
|
||||
@@ -72,7 +72,15 @@ return function (Handler $handler) {
|
||||
];
|
||||
switch ($image['type']) {
|
||||
case 'video':
|
||||
$data['html'] = '<video src="' . $image['url'] . '" width="' . $image['width'] . '" height="' . $image['height'] . '" controls poster="' . $image['url_frame'] . '"></video>';
|
||||
$data['html'] = '<video src="'
|
||||
. $image['url']
|
||||
. '" width="'
|
||||
. $image['width']
|
||||
. '" height="'
|
||||
. $image['height']
|
||||
. '" controls poster="'
|
||||
. $image['url_frame']
|
||||
. '"></video>';
|
||||
$data['type'] = 'video';
|
||||
|
||||
break;
|
||||
@@ -113,9 +121,16 @@ return function (Handler $handler) {
|
||||
'thumbnail_height' => $display_height,
|
||||
]);
|
||||
}
|
||||
match (get()['format'] ?? '') {
|
||||
'xml' => xml_output(['oembed' => $data]),
|
||||
default => json_output($data),
|
||||
};
|
||||
die();
|
||||
$format = get()['format'] ?? '';
|
||||
if ($format === 'xml') {
|
||||
if (isset($data['html'])) {
|
||||
$data['html'] = htmlentities($data['html']);
|
||||
}
|
||||
xml_document_output([
|
||||
'oembed' => $data,
|
||||
]);
|
||||
} else {
|
||||
json_document_output($data);
|
||||
}
|
||||
exit();
|
||||
};
|
||||
|
||||
@@ -10,29 +10,29 @@
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\Page;
|
||||
use function Chevereto\Legacy\G\add_ending_slash;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\add_ending_slash;
|
||||
use function Chevereto\Vars\env;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_PAGES']) {
|
||||
$this->issueError(404);
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_PAGES']) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$request_url_key = implode('/', $handler->request());
|
||||
$page = Page::getSingle($request_url_key);
|
||||
if (!$page || !$page['is_active'] || $page['type'] !== 'internal') {
|
||||
if (! $page || ! $page['is_active'] || $page['type'] !== 'internal') {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!$page['file_path_absolute']) {
|
||||
if (! $page['file_path_absolute']) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!file_exists($page['file_path_absolute'])) {
|
||||
if (! file_exists($page['file_path_absolute'])) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -43,7 +43,7 @@ return function (Handler $handler) {
|
||||
$page_metas = [
|
||||
'pre_doctitle' => $page['title'],
|
||||
'meta_description' => htmlspecialchars($page['description'] ?? ''),
|
||||
'meta_keywords' => htmlspecialchars($page['keywords'] ?? '')
|
||||
'meta_keywords' => htmlspecialchars($page['keywords'] ?? ''),
|
||||
];
|
||||
foreach ($page_metas as $k => $v) {
|
||||
if ($v === null) {
|
||||
|
||||
@@ -10,22 +10,27 @@
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\get_global;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\include_theme_file;
|
||||
use function Chevereto\Legacy\G\require_theme_file;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!getSetting('enable_plugin_route') && !Login::isAdmin()) {
|
||||
if (! getSetting('enable_plugin_route') && ! Login::isAdmin()) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$src = getSetting('sdk_pup_url') ?: get_public_url('sdk/pup.js');
|
||||
$src = str_replace_first('https:', '', $src);
|
||||
include_theme_file('snippets/embed');
|
||||
require_theme_file('snippets/embed');
|
||||
$embed_share_tpl = get_global('embed_share_tpl');
|
||||
$embed = [];
|
||||
foreach ($embed_share_tpl as $vGroup) {
|
||||
@@ -39,7 +44,7 @@ return function (Handler $handler) {
|
||||
$tagAttrs = [
|
||||
'async' => '',
|
||||
'src' => $src,
|
||||
'data-url' => get_public_url('upload')
|
||||
'data-url' => get_public_url('upload'),
|
||||
];
|
||||
$tagCode = '<script';
|
||||
foreach ($tagAttrs as $k => $v) {
|
||||
@@ -71,7 +76,7 @@ return function (Handler $handler) {
|
||||
'Vanilla Forums',
|
||||
'vBulletin',
|
||||
'WoltLab',
|
||||
'XenForo'
|
||||
'XenForo',
|
||||
],
|
||||
'palettes' => [
|
||||
'default' => ['#ececec', '#000', '#2980b9', '#fff'],
|
||||
@@ -85,7 +90,7 @@ return function (Handler $handler) {
|
||||
'orange' => ['#d35400', '#fff', '#e67e22', '#fff'],
|
||||
'red' => ['#c0392b', '#fff', '#e74c3c', '#fff'],
|
||||
'grey' => ['#ececec', '#000', '#e0e0e0', '#000'],
|
||||
'black' => ['#333', '#fff', '#666', '#fff']
|
||||
'black' => ['#333', '#fff', '#666', '#fff'],
|
||||
],
|
||||
'button' => '<div class="%cClass"><button id="pup-preview" class="%bClass %bClass--palette-default"><span class="%iClass">%iconSvg</span><span class="%tClass">' . _s('Upload images') . '</span></button></div>',
|
||||
'baseCss' => '.%cClass{display:inline-block;margin-top:5px;margin-bottom:5px}.%bClass{-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;outline:0;border:none;cursor:pointer;border:1px solid rgba(0,0,0,.05);border-radius:.2em;padding:.5em 1em;font-size:12px;font-weight:700;text-shadow:none}.%bClass:hover{border-top-color:rgba(255,255,255,.1);border-right-color:rgba(0,0,0,.05);border-bottom-color:rgba(0,0,0,.1);border-left-color:rgba(0,0,0,.05);}.%iClass{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-ms-flex-item-align:center;align-self:center;position:relative;height:1em;width:1em;margin-right:.25em}.%iClass img,.%iClass svg{width:1em;height:1em;bottom:-.125em;position:absolute}.%iClass svg{fill:currentColor}',
|
||||
@@ -101,7 +106,7 @@ return function (Handler $handler) {
|
||||
}
|
||||
$palette_css_rules .= strtr($plugin['paletteCss'], $paletteTable);
|
||||
}
|
||||
foreach (['button', 'baseCss'] as $v) {
|
||||
foreach (['button', 'baseCss'] as $v) {
|
||||
$plugin[$v] = strtr($plugin[$v], $plugin['table']);
|
||||
}
|
||||
$plugin['stylesheet'] = '<style type="text/css" id="chevereto-pup-style">' . $plugin['baseCss'] . $palette_css_rules . '</style>';
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\decryptString;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\decryptString;
|
||||
use function Chevereto\Legacy\G\is_url_web;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Vars\get;
|
||||
@@ -34,7 +34,7 @@ return function (Handler $handler) {
|
||||
$url = decryptString($encrypted);
|
||||
$validations = [
|
||||
is_url_web($url),
|
||||
$handler::checkAuthToken(get()['auth_token'] ?? '')
|
||||
$handler::checkAuthToken(get()['auth_token'] ?? ''),
|
||||
];
|
||||
if (in_array(false, $validations)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
@@ -13,27 +13,20 @@ use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Search;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevereto\Legacy\G\check_value;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\post;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS']) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($handler::cond('search_enabled') == false) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (post() !== [] && !$handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
if (post() !== [] && ! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -43,14 +36,14 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
} // Allow only 3 levels
|
||||
if (is_null($handler->request()[0] ?? null)) {
|
||||
if (null === ($handler->request()[0] ?? null)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
if (!in_array($handler->request()[0], ['images', 'albums', 'users'])) {
|
||||
if (! in_array($handler->request()[0], ['images', 'albums', 'users'])) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -61,8 +54,8 @@ return function (Handler $handler) {
|
||||
$search->request = request();
|
||||
$search->requester = Login::getUser();
|
||||
$search->build();
|
||||
if (!check_value($search->q)) {
|
||||
redirect();
|
||||
if ($search->q === '') {
|
||||
redirect('', 302);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +90,10 @@ return function (Handler $handler) {
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => 'search',
|
||||
'basename' => 'search',
|
||||
'params' => ['q' => $safe_html_search['q'], 'page' => '1'],
|
||||
'params' => [
|
||||
'q' => $safe_html_search['q'],
|
||||
'page' => '1',
|
||||
],
|
||||
'params_remove_keys' => ['sort'],
|
||||
], $getParams);
|
||||
foreach ($tabs as &$v) {
|
||||
@@ -106,17 +102,23 @@ return function (Handler $handler) {
|
||||
$meta_description = '';
|
||||
switch ($search->type) {
|
||||
case 'images':
|
||||
$meta_description = _s('%t search results for %s', ['%t' => _n('Image', 'Images', 1)]);
|
||||
$meta_description = _s('%t search results for %s', [
|
||||
'%t' => _n('Image', 'Images', 1),
|
||||
]);
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'albums':
|
||||
$meta_description = _s('%t search results for %s', ['%t' => _n('Album', 'Albums', 1)]);
|
||||
$meta_description = _s('%t search results for %s', [
|
||||
'%t' => _n('Album', 'Albums', 1),
|
||||
]);
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'users':
|
||||
$meta_description = _s('%t search results for %s', ['%t' => _n('User', 'Users', 1)]);
|
||||
$meta_description = _s('%t search results for %s', [
|
||||
'%t' => _n('User', 'Users', 1),
|
||||
]);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$handler::setVar('pre_doctitle', $search->q . ' - ' . _s('Search'));
|
||||
$handler::setVar('meta_description', sprintf($meta_description, $safe_html_search['q']));
|
||||
@@ -127,4 +129,5 @@ return function (Handler $handler) {
|
||||
$handler::setVar('user_items_editor', false);
|
||||
}
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
$handler::setVar('meta_robots', 'noindex, follow');
|
||||
};
|
||||
|
||||
@@ -21,12 +21,12 @@ use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\TwoFactor;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\array_filter_array;
|
||||
use function Chevereto\Legacy\G\dateinterval;
|
||||
use function Chevereto\Legacy\G\datetime_diff;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\is_url_web;
|
||||
use function Chevereto\Legacy\G\nullify_string;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
@@ -45,27 +45,44 @@ use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
$POST = post();
|
||||
if ($POST !== [] and !$handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
if ($POST !== [] and ! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
if ($logged_user === []) {
|
||||
redirect('login');
|
||||
redirect('login', 302);
|
||||
}
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
$handler->setTemplate('settings');
|
||||
$is_dashboard_user = $handler::cond('dashboard_user');
|
||||
if (!$is_dashboard_user) {
|
||||
if (! $is_dashboard_user) {
|
||||
RequestLog::getCounts('account-edit', 'fail');
|
||||
}
|
||||
$allowed_to_edit = ['name', 'username', 'email', 'avatar_filename', 'website', 'background_filename', 'timezone', 'language', 'image_keep_exif', 'image_expiration', 'newsletter_subscribe', 'bio', 'show_nsfw_listings', 'is_private', 'status'];
|
||||
$allowed_to_edit = [
|
||||
'name',
|
||||
'username',
|
||||
'email',
|
||||
'avatar_filename',
|
||||
'website',
|
||||
'background_filename',
|
||||
'timezone',
|
||||
'language',
|
||||
'image_keep_exif',
|
||||
'file_meta_tag_camera_model',
|
||||
'image_expiration',
|
||||
'newsletter_subscribe',
|
||||
'bio',
|
||||
'show_nsfw_listings',
|
||||
'is_private',
|
||||
'status',
|
||||
];
|
||||
if ($is_dashboard_user) {
|
||||
$allowed_to_edit = array_merge($allowed_to_edit, ['is_admin', 'is_manager']);
|
||||
}
|
||||
if (!getSetting('enable_expirable_uploads')) {
|
||||
$key = array_search('image_expiration', $allowed_to_edit);
|
||||
if (! getSetting('enable_expirable_uploads')) {
|
||||
$key = array_search('image_expiration', $allowed_to_edit, true);
|
||||
unset($allowed_to_edit[$key]);
|
||||
}
|
||||
$user = $is_dashboard_user
|
||||
@@ -76,16 +93,16 @@ return function (Handler $handler) {
|
||||
|
||||
return;
|
||||
}
|
||||
$is_owner = $user['id'] == Login::getUser()['id'];
|
||||
if ($is_dashboard_user && $user['is_content_manager'] && Login::isAdmin() == false) {
|
||||
$is_owner = $user['id'] === Login::getUser()['id'];
|
||||
if ($is_dashboard_user && $user['is_content_manager'] && Login::isAdmin() === false) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (in_array('language', $allowed_to_edit)
|
||||
if (in_array('language', $allowed_to_edit, true)
|
||||
&& isset($POST['language'])
|
||||
&& $logged_user['language'] !== $POST['language']
|
||||
&& $logged_user['id'] == $user['id']
|
||||
&& $logged_user['id'] === $user['id']
|
||||
&& array_key_exists($POST['language'], L10n::getEnabledLanguages())
|
||||
) {
|
||||
L10n::processTranslation($POST['language']);
|
||||
@@ -112,15 +129,18 @@ return function (Handler $handler) {
|
||||
];
|
||||
$default_route = 'account';
|
||||
$route_homepage = false;
|
||||
if (getSetting('website_mode') == 'personal' and getSetting('website_mode_personal_routing') !== '/' and $logged_user['id'] == getSetting('website_mode_personal_uid')) {
|
||||
if (getSetting('website_mode') === 'personal'
|
||||
&& getSetting('website_mode_personal_routing') !== '/'
|
||||
&& $logged_user['id'] === getSetting('website_mode_personal_uid')
|
||||
) {
|
||||
$route_homepage = true;
|
||||
}
|
||||
$is_email_required = (bool) getSetting('require_user_email_confirmation');
|
||||
if ($handler::cond('content_manager') && $is_owner == false) {
|
||||
if ($handler::cond('content_manager') && $is_owner === false) {
|
||||
$is_email_required = false;
|
||||
}
|
||||
$providersEnabled = Login::getProviders('enabled');
|
||||
if ($is_email_required && getSetting('require_user_email_social_signup') == false) {
|
||||
if ($is_email_required && getSetting('require_user_email_social_signup') === false) {
|
||||
foreach (array_keys($providersEnabled) as $k) {
|
||||
if (array_key_exists($k, $user['login'])) {
|
||||
$is_email_required = false;
|
||||
@@ -131,22 +151,26 @@ return function (Handler $handler) {
|
||||
}
|
||||
$doing_level = $is_dashboard_user ? 2 : 0;
|
||||
$doing = $handler->request()[$doing_level] ?? $default_route;
|
||||
if (!$user || isset($handler->request()[$doing_level + 1]) || (!is_null($doing) and !array_key_exists($doing, $routes))) {
|
||||
if (isset($handler->request()[$doing_level + 1])
|
||||
|| ($doing != null && ! array_key_exists($doing, $routes))
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($doing == '') {
|
||||
if ($doing === '') { // @phpstan-ignore-line
|
||||
$doing = $default_route;
|
||||
}
|
||||
$tabs = [];
|
||||
foreach ($routes as $route => $label) {
|
||||
$aux = str_replace('_', '-', $route);
|
||||
$handler::setCond('settings_' . $aux, $doing == $aux);
|
||||
$handler::setCond('settings_' . $aux, $doing === $aux);
|
||||
if ($handler::cond('settings_' . $aux)) {
|
||||
$handler::setVar('setting', $aux);
|
||||
}
|
||||
if ($aux == 'homepage' and !$route_homepage) {
|
||||
if ($aux === 'homepage' and ! $route_homepage) {
|
||||
unset($routes[$aux]);
|
||||
|
||||
continue;
|
||||
}
|
||||
$tabs[$aux] = [
|
||||
@@ -154,18 +178,18 @@ return function (Handler $handler) {
|
||||
'label' => $label,
|
||||
'url' => get_base_url(
|
||||
($is_dashboard_user ? ('dashboard/user/' . $user['id']) : 'settings')
|
||||
. ($route == $default_route ? '' : '/' . $route)
|
||||
. ($route === $default_route ? '' : '/' . $route)
|
||||
),
|
||||
'current' => $handler::cond('settings_' . $aux)
|
||||
'current' => $handler::cond('settings_' . $aux),
|
||||
];
|
||||
}
|
||||
if (count($providersEnabled) == 0 || ($is_dashboard_user && Login::isAdmin() == false)) {
|
||||
if (count($providersEnabled) === 0 || ($is_dashboard_user && Login::isAdmin() === false)) {
|
||||
unset($routes['connections']);
|
||||
$tabs = array_filter_array($tabs, ['connections'], 'rest');
|
||||
}
|
||||
$handler::setVar('tabs', $tabs);
|
||||
|
||||
if (!array_key_exists($doing, $routes)) {
|
||||
if (! array_key_exists($doing, $routes)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -189,63 +213,85 @@ return function (Handler $handler) {
|
||||
case 'account':
|
||||
$checkboxes = ['upload_image_exif', 'newsletter_subscribe', 'show_nsfw_listings', 'is_private'];
|
||||
foreach ($checkboxes as $k) {
|
||||
if (!isset($POST[$k])) {
|
||||
if (! isset($POST[$k])) {
|
||||
continue;
|
||||
}
|
||||
$POST[$k] = in_array($POST[$k], ['On', 1]) ? 1 : 0;
|
||||
$POST[$k] = in_array($POST[$k], ['On', 1], false)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
nullify_string($POST['image_expiration']);
|
||||
$__post = [];
|
||||
$__safe_post = [];
|
||||
foreach (['username', 'email'] as $v) {
|
||||
if (isset($POST[$v])) {
|
||||
$POST[$v] = $v == 'email' ? trim($POST[$v]) : strtolower(trim($POST[$v]));
|
||||
$POST[$v] = $v === 'email'
|
||||
? trim($POST[$v])
|
||||
: strtolower(trim($POST[$v]));
|
||||
$__post[$v] = $POST[$v];
|
||||
$__safe_post[$v] = safe_html($POST[$v]);
|
||||
}
|
||||
}
|
||||
$handler::updateVar('post', $__post);
|
||||
$handler::updateVar('safe_post', $__safe_post);
|
||||
if (!User::isValidUsername($POST['username'])) {
|
||||
if (! User::isValidUsername($POST['username'])) {
|
||||
$input_errors['username'] = _s('Invalid username');
|
||||
}
|
||||
if ($is_email_required and !filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if ($is_email_required and ! filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$input_errors['email'] = _s('Invalid email');
|
||||
}
|
||||
if (getSetting('enable_expirable_uploads')) {
|
||||
if ($POST['image_expiration'] !== null && (!dateinterval($POST['image_expiration']) || !array_key_exists($POST['image_expiration'], Image::getAvailableExpirations()))) {
|
||||
if (isset($POST['image_expiration'])
|
||||
&& (
|
||||
! dateinterval($POST['image_expiration'])
|
||||
|| ! array_key_exists($POST['image_expiration'], Image::getAvailableExpirations())
|
||||
)
|
||||
) {
|
||||
$input_errors['image_expiration'] = _s('Invalid image expiration: %s', $POST['image_expiration']);
|
||||
}
|
||||
}
|
||||
if (getSetting('language_chooser_enable') && !array_key_exists($POST['language'], get_available_languages())) {
|
||||
$POST['language'] = getSetting('default_language');
|
||||
if (getSetting('language_chooser_enable')) {
|
||||
if (isset($POST['language'])
|
||||
&& ! array_key_exists($POST['language'], get_available_languages())
|
||||
) {
|
||||
$POST['language'] = getSetting('default_language');
|
||||
}
|
||||
}
|
||||
if (!in_array($POST['timezone'], timezone_identifiers_list())) {
|
||||
if (! in_array($POST['timezone'], timezone_identifiers_list(), false)) {
|
||||
$POST['timezone'] = date_default_timezone_get();
|
||||
}
|
||||
if (is_array($input_errors) && count($input_errors) > 0) {
|
||||
$is_error = true;
|
||||
}
|
||||
if (!$is_error) {
|
||||
$user_db = DB::get('users', ['username' => $POST['username'], 'email' => $POST['email']], 'OR', []);
|
||||
if (! $is_error) {
|
||||
$user_db = DB::get('users', [
|
||||
'username' => $POST['username'],
|
||||
'email' => $POST['email'],
|
||||
], 'OR', []);
|
||||
if ($user_db) {
|
||||
foreach ($user_db as $row) {
|
||||
if ($row['user_id'] == $user['id']) {
|
||||
if ($row['user_id'] === $user['id']) {
|
||||
continue;
|
||||
} // Same guy?
|
||||
if (!in_array($row['user_status'], ['valid', 'banned'])) { // Don't touch the valid and banned users
|
||||
if (! in_array($row['user_status'], ['valid', 'banned'], true)) { // Don't touch the valid and banned users
|
||||
$must_delete_old_user = false;
|
||||
$confirmation_db = Confirmation::get(['user_id' => $row['user_id']]);
|
||||
$confirmation_db = Confirmation::get([
|
||||
'user_id' => $row['user_id'],
|
||||
]);
|
||||
if ($confirmation_db !== false) {
|
||||
if (datetime_diff($confirmation_db['confirmation_date_gmt'], null, 'h') > 48) {
|
||||
Confirmation::delete(['id' => $confirmation_db['confirmation_id']]);
|
||||
Confirmation::delete([
|
||||
'id' => $confirmation_db['confirmation_id'],
|
||||
]);
|
||||
$must_delete_old_user = true;
|
||||
}
|
||||
} else {
|
||||
$must_delete_old_user = true;
|
||||
}
|
||||
if ($must_delete_old_user) {
|
||||
DB::delete('users', ['id' => $row['user_id']]);
|
||||
DB::delete('users', [
|
||||
'id' => $row['user_id'],
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -255,7 +301,7 @@ return function (Handler $handler) {
|
||||
) {
|
||||
$input_errors['username'] = 'Username already being used';
|
||||
}
|
||||
if (!empty($POST['email'])
|
||||
if (! empty($POST['email'])
|
||||
&& hash_equals((string) $row['user_email'], (string) $POST['email'])
|
||||
&& $user['email'] !== $row['user_email']
|
||||
) {
|
||||
@@ -267,22 +313,25 @@ return function (Handler $handler) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$is_error
|
||||
if (! $is_error
|
||||
&& $is_email_required
|
||||
&& !empty($POST['email'])
|
||||
&& !hash_equals(
|
||||
&& ! empty($POST['email'])
|
||||
&& ! hash_equals(
|
||||
(string) ($user['email'] ?? ''),
|
||||
(string) $POST['email']
|
||||
)
|
||||
) {
|
||||
Confirmation::delete(['type' => 'account-change-email', 'user_id' => $user['id']]);
|
||||
Confirmation::delete([
|
||||
'type' => 'account-change-email',
|
||||
'user_id' => $user['id'],
|
||||
]);
|
||||
$hashed_token = generate_hashed_token((int) $user['id']);
|
||||
Confirmation::insert([
|
||||
'type' => 'account-change-email',
|
||||
'user_id' => $user['id'],
|
||||
'token_hash' => $hashed_token['hash'],
|
||||
'status' => 'active',
|
||||
'extra' => $POST['email']
|
||||
'extra' => $POST['email'],
|
||||
]);
|
||||
$email_confirm_link = get_public_url(
|
||||
'account/change-email-confirm/?token='
|
||||
@@ -292,13 +341,13 @@ return function (Handler $handler) {
|
||||
global $theme_mail;
|
||||
$theme_mail = [
|
||||
'user' => $user,
|
||||
'link' => $email_confirm_link
|
||||
'link' => $email_confirm_link,
|
||||
];
|
||||
ob_start();
|
||||
require_once PATH_PUBLIC_LEGACY_THEME . 'mails/account-change-email.php';
|
||||
$mail_body = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings('website_name', true));
|
||||
$mail['message'] = $mail_body;
|
||||
send_mail($POST['email'], $mail['subject'], $mail['message']);
|
||||
unset($POST['email']);
|
||||
@@ -306,15 +355,15 @@ return function (Handler $handler) {
|
||||
|
||||
break;
|
||||
case 'profile':
|
||||
if (!preg_match('/^.{1,60}$/', $POST['name'] ?? '')) {
|
||||
if (! preg_match('/^.{1,60}$/', $POST['name'] ?? '')) {
|
||||
$input_errors['name'] = _s('Invalid name');
|
||||
}
|
||||
if (!empty($POST['website'])) {
|
||||
if (!is_url_web($POST['website'])) {
|
||||
if (! empty($POST['website'])) {
|
||||
if (! is_url_web($POST['website'])) {
|
||||
$input_errors['website'] = _s('Invalid website');
|
||||
}
|
||||
}
|
||||
if (!$handler::cond('content_manager') && getSetting('akismet')) {
|
||||
if (! $handler::cond('content_manager') && getSetting('akismet')) {
|
||||
$akismet = new Akismet();
|
||||
$isSpam = $akismet->isSpam($POST['bio'], $POST['name'], $user['email'], $POST['website']);
|
||||
$is_error = $isSpam;
|
||||
@@ -324,18 +373,20 @@ return function (Handler $handler) {
|
||||
break;
|
||||
|
||||
case 'password':
|
||||
if (!$is_dashboard_user) {
|
||||
if (! $is_dashboard_user) {
|
||||
if (isset($POST['current-password'])) {
|
||||
if (!Login::checkPassword($user['id'], $POST['current-password'])) {
|
||||
if (! Login::checkPassword($user['id'], $POST['current-password'])) {
|
||||
$input_errors['current-password'] = _s('Wrong password');
|
||||
}
|
||||
if ($POST['current-password'] == ($POST['new-password'] ?? null)) {
|
||||
if ($POST['current-password'] === ($POST['new-password'] ?? null)) {
|
||||
$input_errors['new-password'] = _s('Use a new password');
|
||||
$handler::updateVar('safe_post', ['current-password' => null]);
|
||||
$handler::updateVar('safe_post', [
|
||||
'current-password' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!preg_match('/' . getSetting('user_password_pattern') . '/', $POST['new-password'] ?? '')) {
|
||||
if (! preg_match('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['new-password'] ?? '')) {
|
||||
$input_errors['new-password'] = _s('Invalid password');
|
||||
}
|
||||
if ($POST['new-password'] !== $POST['new-password-confirm']) {
|
||||
@@ -345,11 +396,11 @@ return function (Handler $handler) {
|
||||
break;
|
||||
|
||||
case 'security':
|
||||
if (!TwoFactor::hasFor($user['id']) && sessionVar()->hasKey('two_factor_secret')) {
|
||||
if (! TwoFactor::hasFor($user['id']) && sessionVar()->hasKey('two_factor_secret')) {
|
||||
$twoFactor = new TwoFactor();
|
||||
$twoFactor = $twoFactor->withSecret(session()['two_factor_secret']);
|
||||
sessionVar()->remove('two_factor_secret');
|
||||
if (!$twoFactor->verify($POST['two-factor-code'])) {
|
||||
if (! $twoFactor->verify($POST['two-factor-code'])) {
|
||||
$input_errors['two-factor-code'] = _s('Invalid code');
|
||||
} else {
|
||||
$twoFactor->insert($user['id']);
|
||||
@@ -359,7 +410,7 @@ return function (Handler $handler) {
|
||||
break;
|
||||
|
||||
case 'homepage':
|
||||
if (!array_key_exists($doing, $routes)) {
|
||||
if (! array_key_exists($doing, $routes)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -368,7 +419,7 @@ return function (Handler $handler) {
|
||||
$editing_array = array_filter_array($POST, $allowed_to_edit, 'exclusion');
|
||||
$update_settings = [];
|
||||
foreach ($allowed_to_edit as $k) {
|
||||
if (!array_key_exists($k, Settings::get()) or Settings::get($k) == $editing_array[$k]) {
|
||||
if (! array_key_exists($k, Settings::get()) or Settings::get($k) == $editing_array[$k]) {
|
||||
continue;
|
||||
}
|
||||
$update_settings[$k] = $editing_array[$k];
|
||||
@@ -396,14 +447,12 @@ return function (Handler $handler) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
if (is_array($input_errors) && count($input_errors) > 0) {
|
||||
$is_error = true;
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (in_array($doing, [null, 'account', 'profile'])) {
|
||||
if (! $is_error) {
|
||||
if (in_array($doing, [null, 'account', 'profile'], false)) {
|
||||
foreach ($POST as $k => $v) {
|
||||
if (($user[$k] ?? null) !== $v) {
|
||||
$is_changed = true;
|
||||
@@ -411,10 +460,10 @@ return function (Handler $handler) {
|
||||
}
|
||||
if ($is_changed) {
|
||||
$editing_array = array_filter_array($POST, $allowed_to_edit, 'exclusion');
|
||||
if (!$is_dashboard_user) {
|
||||
if (! $is_dashboard_user) {
|
||||
unset($editing_array['status'], $editing_array['is_admin'], $editing_array['is_manager']);
|
||||
} else {
|
||||
if (!in_array($editing_array['status'] ?? null, ['valid', 'banned', 'awaiting-confirmation', 'awaiting-email'])) {
|
||||
if (! in_array($editing_array['status'] ?? null, ['valid', 'banned', 'awaiting-confirmation', 'awaiting-email'], true)) {
|
||||
unset($editing_array['status']);
|
||||
}
|
||||
if ($logged_user['is_manager']) {
|
||||
@@ -435,13 +484,13 @@ return function (Handler $handler) {
|
||||
break;
|
||||
}
|
||||
if ($user['is_admin'] != $is_admin) {
|
||||
$handler::setCond('admin', (bool) $is_admin);
|
||||
$pushAdmin = true;
|
||||
$editing_array['is_admin'] = $is_admin;
|
||||
}
|
||||
if ($user['is_manager'] != $is_manager) {
|
||||
$editing_array['is_manager'] = $is_manager;
|
||||
}
|
||||
if ($POST['role'] == 'admin') {
|
||||
if ($POST['role'] === 'admin') {
|
||||
$editing_array['status'] = 'valid';
|
||||
}
|
||||
unset($POST['role']);
|
||||
@@ -449,14 +498,25 @@ return function (Handler $handler) {
|
||||
if (empty($POST['email'])) {
|
||||
unset($editing_array['email']);
|
||||
}
|
||||
if (User::update($user['id'], $editing_array)) {
|
||||
|
||||
try {
|
||||
$userUpdate = User::update($user['id'], $editing_array);
|
||||
} catch (Throwable $e) {
|
||||
$userUpdate = false;
|
||||
$is_error = true;
|
||||
$is_changed = false;
|
||||
$error_message = $e->getMessage();
|
||||
}
|
||||
if ($userUpdate) {
|
||||
if (isset($isAdmin) && ($pushAdmin ?? false)) {
|
||||
$handler::setCond('admin', (bool) $is_admin);
|
||||
}
|
||||
$user = array_merge($user, $editing_array);
|
||||
$handler::updateVar('safe_post', [
|
||||
'name' => safe_html($user['name']),
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$is_dashboard_user) {
|
||||
if (! $is_dashboard_user) {
|
||||
$logged_user = User::getSingle($user['id']);
|
||||
} else {
|
||||
$user = User::getSingle($user['id'], 'id');
|
||||
@@ -464,38 +524,38 @@ return function (Handler $handler) {
|
||||
$changed_message = _s('Changes have been saved.');
|
||||
}
|
||||
}
|
||||
if ($doing == 'password') {
|
||||
if ($doing === 'password') {
|
||||
if (Login::hasPassword($user['id'])) {
|
||||
Login::deleteCookies('cookie', ['user_id' => $user['id']]);
|
||||
Login::deleteCookies('session', ['user_id' => $user['id']]);
|
||||
$is_changed = Login::changePassword((int) $user['id'], $POST['new-password']); // This inserts the session login
|
||||
$changed_message = _s('Password has been changed');
|
||||
} else {
|
||||
$is_changed = Login::addPassword((int) $user['id'], $POST['new-password']);
|
||||
$changed_message = _s('Password has been created.');
|
||||
if (!$is_dashboard_user || $logged_user['id'] == $user['id']) {
|
||||
if (! $is_dashboard_user || $logged_user['id'] === $user['id']) {
|
||||
$logged_user = Login::login($user['id']);
|
||||
}
|
||||
}
|
||||
if (!$is_dashboard_user) {
|
||||
if (! $is_dashboard_user) {
|
||||
Login::insertCookie('cookie', $user['id']);
|
||||
}
|
||||
$unsets = ['current-password', 'new-password', 'new-password-confirm'];
|
||||
foreach ($unsets as $unset) {
|
||||
$handler::updateVar('safe_post', [$unset => null]);
|
||||
$handler::updateVar('safe_post', [
|
||||
$unset => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (in_array($doing, ['', 'account']) && !$is_dashboard_user) {
|
||||
if (in_array($doing, ['', 'account'], false) && ! $is_dashboard_user) {
|
||||
RequestLog::insert([
|
||||
'type' => 'account-edit',
|
||||
'result' => 'fail'
|
||||
'result' => 'fail',
|
||||
]);
|
||||
$error_message = _s('Wrong Username/Email values');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($doing == 'connections') {
|
||||
if ($doing === 'connections') {
|
||||
$connections = Login::getUserConnections($user['id']);
|
||||
$has_password = Login::hasPassword($user['id']);
|
||||
$handler::setCond('has_password', $has_password);
|
||||
@@ -503,7 +563,7 @@ return function (Handler $handler) {
|
||||
$handler::setVar('providers_enabled', $providersEnabled);
|
||||
}
|
||||
if ($doing === 'api') {
|
||||
if (!ApiKey::has(intval($user['id']))) {
|
||||
if (! ApiKey::has(intval($user['id']))) {
|
||||
$apiCreated = ApiKey::insert(intval($user['id']));
|
||||
$handler::setVar('api_v1_key', $apiCreated);
|
||||
}
|
||||
@@ -512,7 +572,7 @@ return function (Handler $handler) {
|
||||
$handler::setVar('api_v1_date_created', $apiPub['date_gmt']);
|
||||
}
|
||||
$hasTwoFactor = TwoFactor::hasFor($user['id']);
|
||||
if ($doing === 'security' && !$hasTwoFactor) {
|
||||
if ($doing === 'security' && ! $hasTwoFactor) {
|
||||
$twoFactor = new TwoFactor();
|
||||
$twoFactorArgs = [
|
||||
'company' => Settings::get('website_name') . ' ' . env()['CHEVERETO_HOSTNAME'],
|
||||
@@ -542,36 +602,38 @@ return function (Handler $handler) {
|
||||
$handler::setVar('user', $is_dashboard_user ? $user : $logged_user);
|
||||
$handler::setVar('safe_html_user', safe_html($handler::var('user')));
|
||||
if ($doing === 'account') {
|
||||
$bannedIp = IpBan::getSingle(['ip' => $handler::var('user')['registration_ip']]);
|
||||
$bannedIp = IpBan::getSingle([
|
||||
'ip' => $handler::var('user')['registration_ip'],
|
||||
]);
|
||||
$user_list_values = [
|
||||
[
|
||||
'label' => _s('Username'),
|
||||
'content' => '<a href="' . $handler::var('user')['url'] . '" class="btn btn-small default"><span class="icon fas fa-user-circle"></span><span class="margin-left-5">' . $handler::var('user')['username'] . '</span></a>' . (
|
||||
$handler::cond('dashboard_user')
|
||||
? (' <a class="btn btn-small default" data-confirm="' . _s("Do you really want to delete this %s?", _n('user', 'users', 1)) . ' ' . _s("This can't be undone.") . '" data-submit-fn="CHV.fn.user.delete.submit" data-ajax-deferred="CHV.fn.complete_resource_delete" data-ajax-url="' . get_base_url("json") . '"><span class="icon fas fa-trash-alt"></span><span class="phone-hide margin-left-5">' . _s('Delete user') . '</span></a>')
|
||||
? (' <a class="btn btn-small default" data-confirm="' . _s('Do you really want to delete this %s?', _n('user', 'users', 1)) . ' ' . _s("This can't be undone.") . '" data-submit-fn="CHV.fn.user.delete.submit" data-ajax-deferred="CHV.fn.complete_resource_delete" data-ajax-url="' . get_base_url('json') . '"><span class="icon fas fa-trash-alt"></span><span class="phone-hide margin-left-5">' . _s('Delete user') . '</span></a>')
|
||||
: ''
|
||||
)
|
||||
),
|
||||
],
|
||||
[
|
||||
'label' => _s('User ID'),
|
||||
'content' => $handler::var('user')['id'] . ' (' . $handler::var('user')['id_encoded'] . ')'
|
||||
'content' => $handler::var('user')['id'] . ' (' . $handler::var('user')['id_encoded'] . ')',
|
||||
],
|
||||
[
|
||||
'label' => _s('Images'),
|
||||
'content' => $handler::var('user')['image_count']
|
||||
'content' => $handler::var('user')['image_count'],
|
||||
],
|
||||
[
|
||||
'label' => _n('Album', 'Albums', 20),
|
||||
'content' => $handler::var('user')['album_count']
|
||||
'content' => $handler::var('user')['album_count'],
|
||||
],
|
||||
[
|
||||
'label' => _s('Register date'),
|
||||
'content' => $handler::var('user')['date']
|
||||
'content' => $handler::var('user')['date'],
|
||||
],
|
||||
[
|
||||
'label' => '<span class="visibility-hidden">' . _s('Register date') . '</span>',
|
||||
'content' => $handler::var('user')['date_gmt'] . ' (GMT)'
|
||||
]
|
||||
'content' => $handler::var('user')['date_gmt'] . ' (GMT)',
|
||||
],
|
||||
];
|
||||
if ($handler::var('user')['registration_ip']) {
|
||||
$user_list_values[] = getIpButtonsArray($bannedIp, $handler::var('user')['registration_ip']);
|
||||
|
||||
@@ -9,24 +9,24 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use Chevereto\Legacy\Classes\Confirmation;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\L10n;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\RequestLog;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\StopForumSpam;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\captcha_check;
|
||||
use function Chevereto\Legacy\G\datetime_diff;
|
||||
use function Chevereto\Legacy\G\get_client_ip;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\generate_hashed_token;
|
||||
use function Chevereto\Legacy\get_email_body_str;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\getSettings;
|
||||
use function Chevereto\Legacy\must_use_captcha;
|
||||
use function Chevereto\Legacy\send_mail;
|
||||
use function Chevereto\Vars\post;
|
||||
@@ -35,12 +35,12 @@ use function Chevereto\Vars\request;
|
||||
return function (Handler $handler) {
|
||||
$POST = post();
|
||||
$SAFE_POST = $handler::var('safe_post');
|
||||
if (!getSetting('enable_signups')) {
|
||||
if (! getSetting('enable_signups')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($POST !== [] && !$handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
if ($POST !== [] && ! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
@@ -52,12 +52,12 @@ return function (Handler $handler) {
|
||||
} // Allow only 1 level
|
||||
if (Login::hasSignup()) {
|
||||
$SAFE_POST['email'] = Login::getSignup()['email'];
|
||||
redirect('account/awaiting-confirmation');
|
||||
redirect('account/awaiting-confirmation', 302);
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
if ($logged_user) {
|
||||
redirect(User::getUrl($logged_user));
|
||||
redirect(User::getUrl($logged_user), 302);
|
||||
}
|
||||
$failed_access_requests = $handler::var('failed_access_requests');
|
||||
$is_error = false;
|
||||
@@ -66,13 +66,13 @@ return function (Handler $handler) {
|
||||
$captcha_needed = $handler::cond('captcha_needed');
|
||||
if ($captcha_needed && $POST !== []) {
|
||||
$captcha = captcha_check();
|
||||
if (!$captcha->is_valid) {
|
||||
if (! $captcha->is_valid) {
|
||||
$is_error = true;
|
||||
$error_message = _s('%s says you are a robot', 'CAPTCHA');
|
||||
}
|
||||
}
|
||||
$handler::setCond('show_resend_activation', false);
|
||||
if ($POST !== [] && !$is_error && !Login::hasSignup()) {
|
||||
if ($POST !== [] && ! $is_error && ! Login::hasSignup()) {
|
||||
$__post = [];
|
||||
$__safe_post = [];
|
||||
foreach (['username', 'email'] as $v) {
|
||||
@@ -84,22 +84,22 @@ return function (Handler $handler) {
|
||||
}
|
||||
$handler::updateVar('post', $__post);
|
||||
$handler::updateVar('safe_post', $__safe_post);
|
||||
if (!filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if (! filter_var($POST['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
|
||||
$input_errors['email'] = _s('Invalid email');
|
||||
}
|
||||
if (!User::isValidUsername($POST['username'])) {
|
||||
if (! User::isValidUsername($POST['username'] ?? '')) {
|
||||
$input_errors['username'] = _s('Invalid username');
|
||||
}
|
||||
if (!preg_match('/' . getSetting('user_password_pattern') . '/', $POST['password'] ?? '')) {
|
||||
if (! preg_match('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['password'] ?? '')) {
|
||||
$input_errors['password'] = _s('Invalid password');
|
||||
}
|
||||
if (!filter_var($POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
if (! filter_var($POST['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
|
||||
$input_errors['email'] = _s('Invalid email');
|
||||
}
|
||||
if ($POST['signup-accept-terms-policies'] != 1) {
|
||||
if (($POST['signup-accept-terms-policies'] ?? 0) != 1) {
|
||||
$input_errors['signup-accept-terms-policies'] = _s('You must agree to the terms and privacy policy');
|
||||
}
|
||||
if (getSetting('user_minimum_age') > 0 && !isset($POST['minimum-age-signup'])) {
|
||||
if (getSetting('user_minimum_age') > 0 && ! isset($POST['minimum-age-signup'])) {
|
||||
$input_errors['minimum-age-signup'] = _s('You must be at least %s years old to use this website.', getSetting('user_minimum_age'));
|
||||
}
|
||||
if (count($input_errors) > 0) {
|
||||
@@ -111,26 +111,35 @@ return function (Handler $handler) {
|
||||
$error_message = _s('Spam detected');
|
||||
}
|
||||
}
|
||||
if (!$is_error) {
|
||||
$user_db = DB::get('users', ['username' => $POST['username'], 'email' => $POST['email']], 'OR', []);
|
||||
if (! $is_error) {
|
||||
$user_db = DB::get('users', [
|
||||
'username' => $POST['username'],
|
||||
'email' => $POST['email'],
|
||||
], 'OR', []);
|
||||
if ($user_db !== []) {
|
||||
$is_error = true;
|
||||
$show_resend_activation = false;
|
||||
foreach ($user_db as $row) {
|
||||
if (!in_array($row['user_status'], ['valid', 'banned'])) { // Don't touch the valid and banned users
|
||||
if (! in_array($row['user_status'], ['valid', 'banned'])) { // Don't touch the valid and banned users
|
||||
$must_delete_old_user = false;
|
||||
$confirmation_db = Confirmation::get(['user_id' => $row['user_id']]);
|
||||
$confirmation_db = Confirmation::get([
|
||||
'user_id' => $row['user_id'],
|
||||
]);
|
||||
if ($confirmation_db !== false) {
|
||||
// 24x2 = 48 tic tac tic tac
|
||||
if (datetime_diff($confirmation_db['confirmation_date_gmt'], null, 'h') > 48) {
|
||||
Confirmation::delete(['id' => $confirmation_db['confirmation_id']]);
|
||||
Confirmation::delete([
|
||||
'id' => $confirmation_db['confirmation_id'],
|
||||
]);
|
||||
$must_delete_old_user = true;
|
||||
}
|
||||
} else {
|
||||
$must_delete_old_user = true;
|
||||
}
|
||||
if ($must_delete_old_user) {
|
||||
DB::delete('users', ['id' => $row['user_id']]);
|
||||
DB::delete('users', [
|
||||
'id' => $row['user_id'],
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -141,7 +150,7 @@ return function (Handler $handler) {
|
||||
if (hash_equals((string) $row['user_email'], (string) $POST['email'])) {
|
||||
$input_errors['email'] = _s('Email already being used');
|
||||
}
|
||||
if (!$show_resend_activation) {
|
||||
if (! $show_resend_activation) {
|
||||
$show_resend_activation = $row['user_status'] == 'awaiting-confirmation';
|
||||
}
|
||||
}
|
||||
@@ -152,7 +161,7 @@ return function (Handler $handler) {
|
||||
'email' => $POST['email'],
|
||||
'timezone' => getSetting('default_timezone'),
|
||||
'language' => L10n::getLocale(),
|
||||
'status' => getSetting('require_user_email_confirmation') ? 'awaiting-confirmation' : 'valid'
|
||||
'status' => getSetting('require_user_email_confirmation') ? 'awaiting-confirmation' : 'valid',
|
||||
];
|
||||
|
||||
try {
|
||||
@@ -169,11 +178,11 @@ return function (Handler $handler) {
|
||||
throw new Exception($e, $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
if (!$is_error) {
|
||||
if (! $is_error) {
|
||||
if ($inserted_user !== 0) {
|
||||
$insert_password = Login::addPassword($inserted_user, $POST['password']);
|
||||
}
|
||||
if (!$inserted_user || !$insert_password) {
|
||||
if (! $inserted_user || ! $insert_password) {
|
||||
throw new Exception("Can't insert user to the DB", 400);
|
||||
} elseif (getSetting('require_user_email_confirmation')) {
|
||||
$hashed_token = generate_hashed_token($inserted_user);
|
||||
@@ -181,7 +190,7 @@ return function (Handler $handler) {
|
||||
'user_id' => $inserted_user,
|
||||
'type' => 'account-activate',
|
||||
'token_hash' => $hashed_token['hash'],
|
||||
'status' => 'active'
|
||||
'status' => 'active',
|
||||
]);
|
||||
$activation_link = get_public_url(
|
||||
'account/activate/?token='
|
||||
@@ -190,9 +199,12 @@ return function (Handler $handler) {
|
||||
global $theme_mail;
|
||||
$theme_mail = [
|
||||
'user' => $user_array,
|
||||
'link' => $activation_link
|
||||
'link' => $activation_link,
|
||||
];
|
||||
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
|
||||
$mail['subject'] = _s(
|
||||
'Confirmation required at %s',
|
||||
getSetting('website_name', true)
|
||||
);
|
||||
$mail['message'] = get_email_body_str('mails/account-confirm');
|
||||
send_mail($POST['email'], $mail['subject'], $mail['message']);
|
||||
} else {
|
||||
@@ -205,25 +217,25 @@ return function (Handler $handler) {
|
||||
$theme_mail = [
|
||||
'user' => $logged_user,
|
||||
];
|
||||
$mail['subject'] = _s('Welcome to %s', getSetting('website_name'));
|
||||
$mail['subject'] = _s('Welcome to %s', getSetting('website_name', true));
|
||||
$mail['message'] = get_email_body_str('mails/account-welcome');
|
||||
send_mail($logged_user['email'], $mail['subject'], $mail['message']);
|
||||
} catch (Exception) {
|
||||
} // Silence
|
||||
redirect($user['url']);
|
||||
redirect($user['url'], 302);
|
||||
}
|
||||
Login::setSignup([
|
||||
'status' => 'awaiting-confirmation',
|
||||
'email' => $SAFE_POST['email']
|
||||
'email' => $SAFE_POST['email'],
|
||||
]);
|
||||
redirect('account/awaiting-confirmation');
|
||||
redirect('account/awaiting-confirmation', 302);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($is_error) {
|
||||
RequestLog::insert([
|
||||
'type' => 'signup',
|
||||
'result' => 'fail'
|
||||
'result' => 'fail',
|
||||
]);
|
||||
$error_message ??= _s('Check the errors in the form to continue.');
|
||||
if ((getSetting('captcha') ?? false) && must_use_captcha($failed_access_requests['day'] + 1)) {
|
||||
|
||||
46
app/legacy/routes/tag-autocomplete.php
Normal file
46
app/legacy/routes/tag-autocomplete.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\Tag;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\json_output;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
header('Content-type: application/json; charset=UTF-8');
|
||||
if (! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
json_output(401, [
|
||||
'error' => [
|
||||
'error_msg' => _s('Request denied'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
json_output(404);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$q = get()['q'] ?? '';
|
||||
$q = trim($q);
|
||||
if ($q === ''
|
||||
|| str_contains($q, ',')
|
||||
) {
|
||||
json_output(400);
|
||||
|
||||
return;
|
||||
}
|
||||
$array = [
|
||||
'items' => Tag::autocomplete($q),
|
||||
];
|
||||
json_output(200, $array);
|
||||
};
|
||||
160
app/legacy/routes/tag.php
Normal file
160
app/legacy/routes/tag.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Tag;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\G\get_route_name;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\request;
|
||||
use function Chevereto\Vars\server;
|
||||
use function Chevereto\Vars\session;
|
||||
use function Chevereto\Vars\sessionVar;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (! $handler::cond('explore_enabled')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$tagKey = $handler->request()[0] ?? '';
|
||||
$tagKey = rawurldecode($tagKey);
|
||||
if ($tagKey === '') {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$tagsPathAsIs = explode(',', $tagKey);
|
||||
$tagsParsed = Tag::parse($tagKey);
|
||||
if ($tagsParsed === []) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (count($tagsParsed) !== count($tagsPathAsIs)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (! in_array(get()['match'] ?? '', ['', 'all'])) {
|
||||
$handler->issueError(400);
|
||||
|
||||
return;
|
||||
}
|
||||
if (env()['CHEVERETO_MAX_TAGS_PER_LISTING'] !== '0'
|
||||
&& count($tagsParsed) > (int) env()['CHEVERETO_MAX_TAGS_PER_LISTING']
|
||||
) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
}
|
||||
$tags = Tag::get($tagKey, 'id', 'name', 'description');
|
||||
if (count($tags) !== count($tagsPathAsIs)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (! $tags) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (! isset(session()['tag_view_stock'])) {
|
||||
sessionVar()->put('tag_view_stock', []);
|
||||
}
|
||||
$sessionValue = session()['tag_view_stock'];
|
||||
$sumViews = [];
|
||||
foreach ($tags as &$tag) {
|
||||
$tag = array_merge($tag, Tag::row($tag['name']));
|
||||
if (! in_array($tag['id'], session()['tag_view_stock'])) {
|
||||
$sessionValue[] = $tag['id'];
|
||||
$sumViews[] = $tag['id'];
|
||||
}
|
||||
}
|
||||
$tags_names = array_column($tags, 'name');
|
||||
$tag_string = implode(', ', $tags_names);
|
||||
$tag_string_no_spaces = implode(',', $tags_names);
|
||||
$tags_id = array_column($tags, 'id');
|
||||
$tags_id_encoded = array_map(function ($id): string {
|
||||
return encodeID($id);
|
||||
}, $tags_id);
|
||||
$tags_key_display = $tag_string;
|
||||
$tags_key_url = $tag_string_no_spaces;
|
||||
$tags_basename = get_route_name() . '/' . rawurlencode($tags_key_url);
|
||||
$canonical = get_base_url($tags_basename, true);
|
||||
$queryString = server()['QUERY_STRING'] ?? '';
|
||||
$tags_descriptions = array_column($tags, 'description');
|
||||
$tags_descriptions = array_filter($tags_descriptions);
|
||||
if ($queryString !== '') {
|
||||
parse_str($queryString, $parse);
|
||||
unset($parse['lang']);
|
||||
$queryString = http_build_query($parse ?? []);
|
||||
if ($queryString !== '') {
|
||||
$canonical .= '/?' . $queryString;
|
||||
}
|
||||
}
|
||||
$handler::setVar('canonical', $canonical);
|
||||
$handler::setVar('pre_doctitle', $tags_key_display);
|
||||
$getParams = Listing::getParams(request());
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => 'images',
|
||||
'basename' => $tags_basename,
|
||||
'params_hidden' => [
|
||||
'tag_id' => implode(',', $tags_id_encoded),
|
||||
'tag_match' => get()['match'] ?? 'any',
|
||||
'hide_banned' => 1,
|
||||
],
|
||||
], $getParams);
|
||||
$handler::setVar('list_params', $getParams);
|
||||
$listing = new Listing();
|
||||
$listing->setType('images');
|
||||
if (isset($getParams['reverse'])) {
|
||||
$listing->setReverse($getParams['reverse']);
|
||||
}
|
||||
if (isset($getParams['seek'])) {
|
||||
$listing->setSeek($getParams['seek']);
|
||||
}
|
||||
$listing->setOffset($getParams['offset']);
|
||||
$listing->setLimit($getParams['limit']); // how many results?
|
||||
$listing->setSortType($getParams['sort'][0]); // date | size | views
|
||||
$listing->setSortOrder($getParams['sort'][1]); // asc | desc
|
||||
$listing->setTagsIds(...$tags_id);
|
||||
$listing->setTagsString($tag_string_no_spaces);
|
||||
$listing->setTagsMatch(get()['match'] ?? 'any');
|
||||
$listing->setRequester(Login::getUser());
|
||||
$listing->exec();
|
||||
$tags_descriptions = implode(' — ', $tags_descriptions);
|
||||
$handler::setVar('tags_descriptions', $tags_descriptions);
|
||||
$handler::setVar('meta_description', $tags_descriptions);
|
||||
$handler::setVar('tags', $tags);
|
||||
$handler::setVar('tabs', $tabs);
|
||||
$handler::setVar('listing', $listing);
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
if ($sumViews !== []) {
|
||||
$tagsTable = DB::getTable('tags');
|
||||
$tagsIds = implode(',', $sumViews);
|
||||
$sumViewsSql = <<<MySQL
|
||||
UPDATE {$tagsTable} SET `tag_views` = `tag_views` + 1 WHERE `tag_id` IN ({$tagsIds});
|
||||
|
||||
MySQL;
|
||||
$db = DB::getInstance();
|
||||
$db->query($sumViewsSql);
|
||||
$db->exec();
|
||||
sessionVar()->put('tag_view_stock', $sessionValue);
|
||||
}
|
||||
$handler::setVar('meta_keywords', $tag_string);
|
||||
};
|
||||
@@ -10,19 +10,19 @@
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\cheveretoVersionInstalled;
|
||||
use function Chevereto\Vars\env;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_UPDATE_HTTP']
|
||||
|| Settings::get('chevereto_version_installed') === null
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_UPDATE_HTTP']
|
||||
|| cheveretoVersionInstalled() === ''
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!Login::isAdmin()) {
|
||||
if (! Login::isAdmin()) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
|
||||
@@ -13,22 +13,21 @@ use Chevereto\Legacy\Classes\Album;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Settings;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\decodeID;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Vars\get;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if (!$handler::cond('upload_allowed')) {
|
||||
if (! $handler::cond('upload_allowed')) {
|
||||
if (Login::isLoggedUser()) {
|
||||
$handler->issueError(403);
|
||||
|
||||
return;
|
||||
} else {
|
||||
redirect('login');
|
||||
}
|
||||
redirect('login', 302);
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
User::statusRedirect($logged_user['status'] ?? null);
|
||||
@@ -37,7 +36,7 @@ return function (Handler $handler) {
|
||||
$toAlbumId = decodeID(get()['toAlbum']);
|
||||
$album = Album::getSingle(id: $toAlbumId, requester: $logged_user);
|
||||
$is_owner = isset($album['user']['id']) && $album['user']['id'] == $logged_user['id'];
|
||||
if (!$is_owner) {
|
||||
if (! $is_owner) {
|
||||
$album = [];
|
||||
}
|
||||
}
|
||||
|
||||
85
app/legacy/routes/user-albums.php
Normal file
85
app/legacy/routes/user-albums.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\getSettings;
|
||||
use function Chevereto\Legacy\json_output;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\request;
|
||||
|
||||
return function (Handler $handler) {
|
||||
header('Content-type: application/json; charset=UTF-8');
|
||||
json_output(404);
|
||||
if (! $handler::checkAuthToken(request()['auth_token'] ?? '')) {
|
||||
json_output(401, [
|
||||
'error' => [
|
||||
'error_msg' => _s('Request denied'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
json_output(404);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$q = get()['q'] ?? '';
|
||||
$q = trim($q);
|
||||
if ($q === ''
|
||||
|| str_contains($q, ',')
|
||||
) {
|
||||
json_output(400);
|
||||
|
||||
return;
|
||||
}
|
||||
$logged_user = Login::getUser();
|
||||
if ($logged_user === []) {
|
||||
json_output(401);
|
||||
|
||||
return;
|
||||
}
|
||||
$user = User::getSingle($q, 'username', false);
|
||||
$user = DB::formatRow($user);
|
||||
$user['url'] = User::getUrl($user);
|
||||
if (! $user
|
||||
|| ($user['status'] ?? '') !== 'valid'
|
||||
&& ($logged_user === [] || ! $handler::cond('content_manager'))
|
||||
) {
|
||||
json_output(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$is_owner = false;
|
||||
if (isset($user['id'], $logged_user['id'])) {
|
||||
$is_owner = $user['id'] === $logged_user['id'];
|
||||
}
|
||||
if (! $is_owner
|
||||
&& ! $handler::cond('content_manager')
|
||||
&& (bool) $user['is_private']
|
||||
) {
|
||||
json_output(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_USERS']
|
||||
&& $user['id'] !== getSettings('website_mode_personal_uid')
|
||||
) {
|
||||
json_output(404);
|
||||
|
||||
return;
|
||||
}
|
||||
$array = User::getAlbums($user);
|
||||
json_output(200, $array);
|
||||
};
|
||||
@@ -9,27 +9,33 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevere\String\ModifyString;
|
||||
use Chevereto\Legacy\Classes\DB;
|
||||
use Chevereto\Legacy\Classes\Follow;
|
||||
use Chevereto\Legacy\Classes\Listing;
|
||||
use Chevereto\Legacy\Classes\Login;
|
||||
use Chevereto\Legacy\Classes\Tag;
|
||||
use Chevereto\Legacy\Classes\User;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\encodeID;
|
||||
use function Chevereto\Legacy\G\get_current_url;
|
||||
use function Chevereto\Legacy\G\get_public_url;
|
||||
use function Chevereto\Legacy\G\redirect;
|
||||
use function Chevereto\Legacy\G\safe_html;
|
||||
use function Chevereto\Legacy\G\str_replace_first;
|
||||
use function Chevereto\Legacy\get_share_links;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
use function Chevereto\Legacy\redirectIfRouting;
|
||||
use function Chevereto\Legacy\headersNoCache;
|
||||
use function Chevereto\Legacy\virtualRouteHandleRedirect;
|
||||
use function Chevereto\Vars\env;
|
||||
use function Chevereto\Vars\get;
|
||||
use function Chevereto\Vars\request;
|
||||
use function Chevereto\Vars\server;
|
||||
|
||||
return function (Handler $handler) {
|
||||
$currentUrl = get_current_url();
|
||||
redirectIfRouting('user', $handler->requestArray()[0]);
|
||||
virtualRouteHandleRedirect('user', $handler->requestArray()[0]);
|
||||
$userIndex = (getSetting('root_route') === 'user'
|
||||
|| getSetting('website_mode') == 'personal')
|
||||
|| getSetting('website_mode') === 'personal')
|
||||
? 0
|
||||
: 1;
|
||||
if ($handler->isRequestLevel($handler::cond('mapped_route') ? 4 : 5)) {
|
||||
@@ -41,14 +47,14 @@ return function (Handler $handler) {
|
||||
? $handler->requestArray()
|
||||
: $handler->request();
|
||||
$userMapPaths = ['search', 'following', 'followers'];
|
||||
$userMapPaths[] = getSetting('user_profile_view') == 'files'
|
||||
$userMapPaths[] = getSetting('user_profile_view') === 'files'
|
||||
? 'albums'
|
||||
: 'files';
|
||||
if (getSetting('website_mode') == 'personal'
|
||||
&& getSetting('website_mode_personal_routing') == '/'
|
||||
if (getSetting('website_mode') === 'personal'
|
||||
&& getSetting('website_mode_personal_routing') === '/'
|
||||
&& $request_handle[0] !== '/'
|
||||
) {
|
||||
if (!in_array($request_handle[0], $userMapPaths)) {
|
||||
if (! in_array($request_handle[0], $userMapPaths, true)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -56,12 +62,14 @@ return function (Handler $handler) {
|
||||
$personal_mode_user = User::getSingle(getSetting('website_mode_personal_uid'));
|
||||
if ($personal_mode_user !== []) {
|
||||
$request_handle = [
|
||||
0 => $personal_mode_user['username'],
|
||||
1 => $request_handle[0]
|
||||
];
|
||||
0 => $personal_mode_user['username'],
|
||||
1 => $request_handle[0],
|
||||
];
|
||||
}
|
||||
}
|
||||
if ($request_handle[0] === getSetting('route_user') && getSetting('root_route') !== 'user') {
|
||||
if (($request_handle[0] ?? false) === getSetting('route_user')
|
||||
&& getSetting('root_route') !== 'user'
|
||||
) {
|
||||
array_shift($request_handle);
|
||||
}
|
||||
$username = $request_handle[0] ?? null;
|
||||
@@ -71,7 +79,7 @@ return function (Handler $handler) {
|
||||
if (isset($mapped_args['id'])) {
|
||||
$id = $handler::mappedArgs()['id'];
|
||||
}
|
||||
if (!isset($username) && isset($id)) {
|
||||
if (! isset($username) && isset($id)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -83,31 +91,32 @@ return function (Handler $handler) {
|
||||
?? User::getSingle(${$userHandle}, $userHandle);
|
||||
$is_owner = false;
|
||||
if (isset($user['id'], $logged_user['id'])) {
|
||||
$is_owner = $user['id'] == $logged_user['id'];
|
||||
$is_owner = $user['id'] === $logged_user['id'];
|
||||
}
|
||||
if (!$user
|
||||
if (! $user
|
||||
|| ($user['status'] ?? '') !== 'valid'
|
||||
&& ($logged_user === [] || !$handler::cond('content_manager'))) {
|
||||
&& ($logged_user === [] || ! $handler::cond('content_manager'))) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!$is_owner && !$handler::cond('content_manager') && (bool) $user['is_private']) {
|
||||
if (! $is_owner && ! $handler::cond('content_manager') && (bool) $user['is_private']) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!(bool) env()['CHEVERETO_ENABLE_USERS'] && $user['id'] != getSetting('website_mode_personal_uid')) {
|
||||
if (! (bool) env()['CHEVERETO_ENABLE_USERS'] && $user['id'] !== getSetting('website_mode_personal_uid')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (getSetting('website_mode') == 'personal' && getSetting('website_mode_personal_routing') === '/') {
|
||||
if (getSetting('website_mode') === 'personal'
|
||||
&& getSetting('website_mode_personal_routing') === '/'
|
||||
) {
|
||||
if (str_starts_with($currentUrl, '/' . $user['username'])) {
|
||||
$redirectTo = (new ModifyString($currentUrl))
|
||||
->withReplaceFirst('/' . $user['username'], '')
|
||||
->__toString();
|
||||
redirect($redirectTo);
|
||||
$redirectTo = str_replace_first('/' . $user['username'], '', $currentUrl);
|
||||
headersNoCache();
|
||||
redirect($redirectTo, 302);
|
||||
}
|
||||
}
|
||||
$pre_doctitle = '';
|
||||
@@ -118,16 +127,18 @@ return function (Handler $handler) {
|
||||
$user_views = [
|
||||
'files' => [
|
||||
'title' => _s(
|
||||
"%t by %s",
|
||||
'%t by %s',
|
||||
[
|
||||
'%t' => _n('File', 'Files', 20)
|
||||
'%t' => _n('File', 'Files', 20),
|
||||
]
|
||||
),
|
||||
'title_short' => _s("Images"),
|
||||
'title_short' => _s('Files'),
|
||||
],
|
||||
'albums' => [
|
||||
'title' => _s("%t by %s", ['%t' => _n('Album', 'Albums', 20)]),
|
||||
'title_short' => _s("Albums"),
|
||||
'title' => _s('%t by %s', [
|
||||
'%t' => _n('Album', 'Albums', 20),
|
||||
]),
|
||||
'title_short' => _s('Albums'),
|
||||
],
|
||||
'search' => [
|
||||
'title' => _s('Search'),
|
||||
@@ -135,7 +146,7 @@ return function (Handler $handler) {
|
||||
],
|
||||
];
|
||||
foreach (array_keys($user_views) as $k) {
|
||||
$user_routes[] = $k == $userHome
|
||||
$user_routes[] = $k === $userHome
|
||||
? $username
|
||||
: $k;
|
||||
}
|
||||
@@ -143,18 +154,22 @@ return function (Handler $handler) {
|
||||
// images: admin, albums, search
|
||||
if (getSetting('enable_likes')) {
|
||||
$user_views['liked'] = [
|
||||
'title' => _s("Liked by %s"),
|
||||
'title_short' => _s("Liked"),
|
||||
'title' => _s('Liked by %s'),
|
||||
'title_short' => _s('Liked'),
|
||||
];
|
||||
$user_routes[] = 'liked';
|
||||
}
|
||||
if (getSetting('enable_followers')) {
|
||||
$user_views['following'] = [
|
||||
'title' => _s("%t followed by %s", ['%t' => _n('User', 'Users', 20)]),
|
||||
'title' => _s('%t followed by %s', [
|
||||
'%t' => _n('User', 'Users', 20),
|
||||
]),
|
||||
'title_short' => _s('Following'),
|
||||
];
|
||||
$user_views['followers'] = [
|
||||
'title' => _s("%t following %s", ['%t' => _n('User', 'Users', 20)]),
|
||||
'title' => _s('%t following %s', [
|
||||
'%t' => _n('User', 'Users', 20),
|
||||
]),
|
||||
'title_short' => _s('Followers'),
|
||||
];
|
||||
$user_routes[] = 'following';
|
||||
@@ -164,33 +179,37 @@ return function (Handler $handler) {
|
||||
$user_views[$k]['current'] = false;
|
||||
}
|
||||
if (isset($request_handle[1])) {
|
||||
if ($request_handle[1] == 'search') {
|
||||
if (!$handler::cond('search_enabled')) {
|
||||
if ($request_handle[1] === 'search') {
|
||||
if (! $handler::cond('search_enabled')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!(request()['q'] ?? false)) {
|
||||
redirect($user['url']);
|
||||
if (! (request()['q'] ?? false)) {
|
||||
redirect($user['url'], 302);
|
||||
}
|
||||
$user['search'] = [
|
||||
'type' => empty(request()['list']) ? 'images' : request()['list'],
|
||||
'q' => request()['q'],
|
||||
'd' => strlen(request()['q']) >= 25 ? (substr(request()['q'], 0, 22) . '...') : request()['q']
|
||||
'd' => strlen(request()['q']) >= 25 ? (substr(request()['q'], 0, 22) . '...') : request()['q'],
|
||||
];
|
||||
}
|
||||
if ($request_handle[1] !== server()['QUERY_STRING'] && !in_array($request_handle[1], $user_routes)) {
|
||||
if ($request_handle[1] !== server()['QUERY_STRING']
|
||||
&& ! in_array($request_handle[1], $user_routes, true)
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($request_handle[1] == 'search') {
|
||||
if (!server()['QUERY_STRING']) {
|
||||
if ($request_handle[1] === 'search') {
|
||||
if (! server()['QUERY_STRING']) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!empty(request()['list']) && !in_array(request()['list'], ['images', 'albums', 'users'])) {
|
||||
if (! empty(request()['list'])
|
||||
&& ! in_array(request()['list'], ['images', 'albums', 'users'], true)
|
||||
) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -204,17 +223,17 @@ return function (Handler $handler) {
|
||||
}
|
||||
$user['followed'] = false;
|
||||
$show_follow_button = false;
|
||||
if (getSetting('website_mode') != 'personal') {
|
||||
if (getSetting('website_mode') !== 'personal') {
|
||||
$user['followed'] = false;
|
||||
$show_follow_button = false;
|
||||
if ($logged_user !== []) {
|
||||
$user['followed'] = ($user['id'] == $logged_user['id'])
|
||||
$user['followed'] = ($user['id'] === $logged_user['id'])
|
||||
? false
|
||||
: Follow::doesFollow(
|
||||
(int) $logged_user['id'],
|
||||
(int) $user['id']
|
||||
);
|
||||
$show_follow_button = $user['id'] != $logged_user['id']
|
||||
$show_follow_button = $user['id'] !== $logged_user['id']
|
||||
&& $logged_user['is_private'] == 0;
|
||||
}
|
||||
}
|
||||
@@ -228,40 +247,66 @@ return function (Handler $handler) {
|
||||
if ($v['current']) {
|
||||
$current_view = $k;
|
||||
if ($current_view !== $userHome) {
|
||||
$base_user_url .= "/$k";
|
||||
$base_user_url .= "/{$k}";
|
||||
}
|
||||
}
|
||||
}
|
||||
$currentKey = 0;
|
||||
$safe_html_user = safe_html($user);
|
||||
$sub_tabs = [];
|
||||
if ($current_view === 'liked') {
|
||||
$type = (get()['list'] ?? '') === 'albums'
|
||||
? 'albums'
|
||||
: 'images';
|
||||
$sub_tabs = [
|
||||
[
|
||||
'icon' => 'fas fa-photo-film',
|
||||
'label' => _s('Files'),
|
||||
'url' => $base_user_url . '/?list=images',
|
||||
'current' => $type === 'images',
|
||||
],
|
||||
[
|
||||
'icon' => 'fas fa-images',
|
||||
'label' => _s('Albums'),
|
||||
'url' => $base_user_url . '/?list=albums',
|
||||
'current' => $type === 'albums',
|
||||
],
|
||||
];
|
||||
}
|
||||
if ($type === 'files') {
|
||||
$type = 'images';
|
||||
}
|
||||
switch ($current_view) {
|
||||
case 'files':
|
||||
case 'liked':
|
||||
$type = "images";
|
||||
$tools = $is_owner || $handler::cond('content_manager');
|
||||
if ($current_view == 'liked') {
|
||||
$tools_available = $handler::cond('content_manager') ? ['delete', 'category', 'flag'] : ['embed'];
|
||||
if ($current_view === 'liked') {
|
||||
$tools_available = $handler::cond('content_manager')
|
||||
? ['delete', 'category', 'flag']
|
||||
: ['embed'];
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'following':
|
||||
case 'followers':
|
||||
$type = 'users';
|
||||
$tools = false;
|
||||
$params_hidden = [$current_view . '_user_id' => $user['id_encoded']];
|
||||
$params_hidden = [
|
||||
$current_view . '_user_id' => $user['id_encoded'],
|
||||
];
|
||||
$params_remove_keys = ['list'];
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'albums':
|
||||
$icon = 'fas fa-images';
|
||||
$type = "albums";
|
||||
$type = 'albums';
|
||||
$tools = true;
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'search':
|
||||
$icon = 'fas fa-search';
|
||||
$type = $user['search']['type'];
|
||||
$currentKey = (isset(request()['list']) && request()['list'] == 'images') || !isset(request()['list'])
|
||||
$currentKey = (isset(request()['list']) && request()['list'] === 'images') || ! isset(request()['list'])
|
||||
? 0 : 1;
|
||||
$tabs = [
|
||||
[
|
||||
@@ -277,7 +322,7 @@ return function (Handler $handler) {
|
||||
'label' => _n('Album', 'Albums', 20),
|
||||
'id' => 'list-user-albums',
|
||||
'current' => $currentKey === 1,
|
||||
]
|
||||
],
|
||||
];
|
||||
foreach ($tabs as $k => $v) {
|
||||
$params = [
|
||||
@@ -290,7 +335,7 @@ return function (Handler $handler) {
|
||||
$tabs[$k]['url'] = $base_user_url . '/?' . $tabs[$k]['params'];
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$icon = [
|
||||
'files' => 'fas fa-photo-film',
|
||||
@@ -303,34 +348,91 @@ return function (Handler $handler) {
|
||||
if ($user_views['albums']['current']) {
|
||||
$params_hidden['list'] = 'albums';
|
||||
}
|
||||
$params_hidden[$current_view == 'liked' ? 'like_user_id' : 'userid'] = $user['id_encoded'];
|
||||
$params_hidden[$current_view === 'liked' ? 'like_user_id' : 'userid'] = $user['id_encoded'];
|
||||
$params_hidden['from'] = 'user';
|
||||
if (!isset($tabs)) {
|
||||
$tags_id = [];
|
||||
$tags_active = [];
|
||||
$isDisplayUsedTags = in_array($current_view, ['files', 'albums']);
|
||||
if (in_array($type, ['images', 'albums'])
|
||||
&& $isDisplayUsedTags
|
||||
&& (get()['tag'] ?? '') !== ''
|
||||
) {
|
||||
$tags = Tag::get(get()['tag']);
|
||||
if ($tags !== []) {
|
||||
$tags_active = array_column($tags, 'name');
|
||||
$tags_id = array_column($tags, 'id');
|
||||
$tags_id_encoded = array_map(function ($id): string {
|
||||
return encodeID($id);
|
||||
}, $tags_id);
|
||||
$params_hidden['tag_id'] = implode(',', $tags_id_encoded);
|
||||
}
|
||||
}
|
||||
$tag_string = implode(', ', $tags_active);
|
||||
$tag_string_no_spaces = implode(',', $tags_active);
|
||||
$tagsTable = DB::getTable('tags');
|
||||
$tagsUsersTable = DB::getTable('tags_users');
|
||||
$tagsAlbumsTable = DB::getTable('tags_albums');
|
||||
$userId = (int) $user['id'];
|
||||
$tags_display = [];
|
||||
if ($isDisplayUsedTags) {
|
||||
$tagsSql = <<<MySQL
|
||||
SELECT t.tag_name name, tu.tag_user_count count
|
||||
FROM `{$tagsTable}` t
|
||||
INNER JOIN `{$tagsUsersTable}` tu
|
||||
ON tu.tag_user_tag_id=t.tag_id
|
||||
AND tu.tag_user_user_id={$userId}
|
||||
AND tu.tag_user_count > 0
|
||||
ORDER BY `tag_user_count` DESC, `tag_name` ASC
|
||||
LIMIT 20;
|
||||
|
||||
MySQL;
|
||||
if ($type === 'albums') {
|
||||
$tagsSql = <<<MySQL
|
||||
SELECT t.tag_name name, ta.tag_album_count count
|
||||
FROM `{$tagsTable}` t
|
||||
INNER JOIN `{$tagsAlbumsTable}` ta
|
||||
ON ta.tag_album_tag_id=t.tag_id
|
||||
AND ta.tag_album_user_id={$userId}
|
||||
AND ta.tag_album_count > 0
|
||||
ORDER BY `tag_album_count` DESC, `tag_name` ASC
|
||||
LIMIT 20;
|
||||
|
||||
MySQL;
|
||||
}
|
||||
$tags_display = DB::queryFetchAll($tagsSql);
|
||||
foreach ($tags_display as &$tag) {
|
||||
$base_tag_filter_url = $base_user_url . '/?tag=';
|
||||
$tag = Tag::row($tag['name'], $base_tag_filter_url . '%s');
|
||||
Tag::addUrlFilters($tag, $base_user_url, $tags_active);
|
||||
}
|
||||
}
|
||||
if (! isset($tabs)) {
|
||||
$tabs = Listing::getTabs([
|
||||
'listing' => $type,
|
||||
'basename' => $base_user_url,
|
||||
'tools' => $tools,
|
||||
'tools_available' => $tools_available ?? null,
|
||||
'tools_available' => $tools_available ?? [],
|
||||
'params_hidden' => $params_hidden,
|
||||
'params_remove_keys' => $params_remove_keys ?? null,
|
||||
'tag' => rawurldecode($tag_string_no_spaces),
|
||||
], [], true);
|
||||
$currentKey = $tabs['currentKey'];
|
||||
$tabs = $tabs['tabs'];
|
||||
}
|
||||
foreach ($tabs as $k => &$v) {
|
||||
if (!array_key_exists('params_hidden', $tabs)) {
|
||||
if (! array_key_exists('params_hidden', $tabs)) {
|
||||
$tabs[$k]['params_hidden'] = http_build_query($params_hidden);
|
||||
}
|
||||
$v['disabled'] = $user[($user_views['files']['current'] ? 'image' : 'album') . '_count'] == 0 ? !$v['current'] : false;
|
||||
$v['disabled'] = $user[($user_views['files']['current'] ? 'image' : 'album') . '_count'] === 0 ? ! $v['current'] : false;
|
||||
}
|
||||
$listing = new Listing();
|
||||
if ($user["image_count"] > 0
|
||||
|| $user["album_count"] > 0
|
||||
|| in_array($current_view, ['liked', 'following', 'followers'])) {
|
||||
if ($user['image_count'] > 0
|
||||
|| $user['album_count'] > 0
|
||||
|| in_array($current_view, ['liked', 'following', 'followers'], true)) {
|
||||
$getParams = Listing::getParams(request());
|
||||
Listing::fillCurrentTabPeekSeek($tabs, $currentKey, $getParams);
|
||||
$handler::setVar('list_params', $getParams);
|
||||
if ($getParams['sort'][0] == 'likes' && !getSetting('enable_likes')) {
|
||||
if ($getParams['sort'][0] === 'likes' && ! getSetting('enable_likes')) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
@@ -339,31 +441,37 @@ return function (Handler $handler) {
|
||||
switch ($current_view) {
|
||||
case 'liked':
|
||||
$where = 'WHERE like_user_id=:user_id';
|
||||
$tpl = 'liked';
|
||||
$tpl = 'liked/' . match ($type) {
|
||||
'images' => 'image',
|
||||
'albums' => 'album',
|
||||
};
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'following':
|
||||
$where = 'WHERE follow_user_id=:user_id';
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'followers':
|
||||
$where = 'WHERE follow_followed_user_id=:user_id';
|
||||
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
$where = $type == 'images'
|
||||
$where = $type === 'images'
|
||||
? 'WHERE image_user_id=:user_id'
|
||||
: 'WHERE album_user_id=:user_id AND album_parent_id IS NULL';
|
||||
: 'WHERE album_user_id=:user_id';
|
||||
// if ($type === 'albums' && $tags_active === []) {
|
||||
// $where .= ' AND album_parent_id IS NULL';
|
||||
// }
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$output_tpl = 'user/' . $tpl;
|
||||
if ($user_views['search']['current']) {
|
||||
$type = $user["search"]["type"];
|
||||
$where = $user["search"]["type"] == "images" ? "WHERE image_user_id=:user_id AND MATCH(image_name, image_title, image_description, image_original_filename) AGAINST (:q)" : "WHERE album_user_id=:user_id AND MATCH(album_name, album_description) AGAINST (:q)";
|
||||
$type = $user['search']['type'];
|
||||
$where = $user['search']['type'] === 'images' ? 'WHERE image_user_id=:user_id AND MATCH(image_name, image_title, image_description, image_original_filename) AGAINST (:q)' : 'WHERE album_user_id=:user_id AND MATCH(album_name, album_description) AGAINST (:q)';
|
||||
}
|
||||
$show_user_items_editor = Login::isLoggedUser();
|
||||
if ($type == 'albums') {
|
||||
if ($type === 'albums') {
|
||||
$show_user_items_editor = false;
|
||||
}
|
||||
|
||||
@@ -381,15 +489,17 @@ return function (Handler $handler) {
|
||||
$listing->setSortType($getParams['sort'][0]); // date | size | views | likes
|
||||
$listing->setSortOrder($getParams['sort'][1]); // asc | desc
|
||||
$listing->setWhere($where);
|
||||
$listing->setOwner((int) $user["id"]);
|
||||
$listing->setOwner((int) $user['id']);
|
||||
$listing->setTagsIds(...$tags_id);
|
||||
$listing->setTagsString($tag_string_no_spaces);
|
||||
$listing->setRequester(Login::getUser());
|
||||
if ($is_owner || $handler::cond('content_manager')) {
|
||||
if ($type == 'users') {
|
||||
if ($type === 'users') {
|
||||
$listing->setTools(false);
|
||||
$show_user_items_editor = false;
|
||||
} elseif ($current_view == 'liked') {
|
||||
} elseif ($current_view === 'liked') {
|
||||
$listing->setTools(
|
||||
$user['id'] == $logged_user['id']
|
||||
$user['id'] === $logged_user['id']
|
||||
? ['embed']
|
||||
: false
|
||||
);
|
||||
@@ -397,8 +507,9 @@ return function (Handler $handler) {
|
||||
$listing->setTools(true);
|
||||
}
|
||||
}
|
||||
$listing->bind(":user_id", $user["id"]);
|
||||
if ($user_views['search']['current'] && !empty($user['search']['q'])) {
|
||||
$listing->bind(':user_id', $user['id']);
|
||||
if ($user_views['search']['current'] && ! empty($user['search']['q'])) {
|
||||
$handler::setVar('meta_robots', 'noindex, follow');
|
||||
$listing->bind(':q', $user['search']['q']);
|
||||
}
|
||||
$listing->setOutputTpl($output_tpl);
|
||||
@@ -413,7 +524,7 @@ return function (Handler $handler) {
|
||||
$pre_doctitle .= $user['search']['d'] . ' - ';
|
||||
}
|
||||
$pre_doctitle .= sprintf($user_views[$current_view]['title'], $user['name_html']);
|
||||
if (getSetting('website_mode') == 'community' || $user['id'] !== getSetting('website_mode_personal_uid')) {
|
||||
if (getSetting('website_mode') === 'community' || $user['id'] !== getSetting('website_mode_personal_uid')) {
|
||||
$pre_doctitle .= ' (' . $user['username'] . ')';
|
||||
}
|
||||
$handler::setVar('pre_doctitle', $pre_doctitle);
|
||||
@@ -433,12 +544,24 @@ return function (Handler $handler) {
|
||||
} else {
|
||||
$meta_description = _s('%n (%u) on %w');
|
||||
}
|
||||
$handler::setVar('meta_description', strtr($meta_description, ['%n' => $user['name'], '%u' => $user['username'], '%w' => getSetting('website_name')]));
|
||||
$handler::setVar('meta_description', strtr($meta_description, [
|
||||
'%n' => $user['name'],
|
||||
'%u' => $user['username'],
|
||||
'%w' => getSetting('website_name'),
|
||||
]));
|
||||
if ($handler::cond('content_manager') || $is_owner) {
|
||||
$handler::setVar('user_items_editor', [
|
||||
"user_albums" => User::getAlbums($user),
|
||||
"type" => $user_views['albums']['current'] ? "albums" : "images"
|
||||
'user_albums' => User::getAlbums($user),
|
||||
'type' => $user_views['albums']['current'] ? 'albums' : 'images',
|
||||
]);
|
||||
}
|
||||
$handler::setVar('share_links_array', get_share_links());
|
||||
$handler::setVar('tags_display', $tags_display);
|
||||
$handler::setVar('tags_active', $tags_active);
|
||||
if ($tag_string !== '') {
|
||||
$handler::setVar('meta_keywords', $tag_string);
|
||||
}
|
||||
$canonical = get_public_url($tabs[$currentKey]['url']);
|
||||
$handler::setVar('canonical', $canonical);
|
||||
$handler::setVar('sub_tabs', $sub_tabs);
|
||||
};
|
||||
|
||||
22
app/legacy/routes/video.php
Normal file
22
app/legacy/routes/video.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\virtualRouteHandleRedirect;
|
||||
|
||||
return function (Handler $handler) {
|
||||
$route = 'image';
|
||||
virtualRouteHandleRedirect($route, $handler->requestArray()[0], 'video');
|
||||
$handler->mapRoute($route);
|
||||
$routeCallable = include PATH_APP_LEGACY_ROUTES . $route . '.php';
|
||||
|
||||
return $routeCallable($handler);
|
||||
};
|
||||
38
app/legacy/routes/webmanifest.php
Normal file
38
app/legacy/routes/webmanifest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Chevereto.
|
||||
*
|
||||
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Chevereto\Legacy\G\Handler;
|
||||
use function Chevereto\Legacy\G\get_base_url;
|
||||
use function Chevereto\Legacy\getSetting;
|
||||
|
||||
return function (Handler $handler) {
|
||||
if ($handler->isRequestLevel(2)) {
|
||||
$handler->issueError(404);
|
||||
|
||||
return;
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
$manifest = [
|
||||
'name' => getSetting('website_doctitle'),
|
||||
'short_name' => getSetting('website_name'),
|
||||
'description' => getSetting('website_description'),
|
||||
// 'lang' => 'en-US',
|
||||
// 'dir' => 'ltr',
|
||||
'display' => 'standalone',
|
||||
'scope' => get_base_url(''),
|
||||
'id' => get_base_url('?_pwa=1'),
|
||||
'start_url' => get_base_url('?_pwa=1'),
|
||||
// 'background_color' => '#FFFFFF',
|
||||
// 'theme_color' => '#FFFFFF',
|
||||
];
|
||||
echo json_encode($manifest, JSON_PRETTY_PRINT);
|
||||
exit();
|
||||
};
|
||||
@@ -4,6 +4,7 @@ parameters:
|
||||
- phpstan-bootstrap.php
|
||||
paths:
|
||||
- bin
|
||||
- legacy
|
||||
- src/Legacy
|
||||
- src/Encryption
|
||||
- ../content/
|
||||
|
||||
@@ -7,16 +7,16 @@ CREATE TABLE `%table_prefix%albums` (
|
||||
`album_date_gmt` datetime NOT NULL,
|
||||
`album_creation_ip` varchar(255) NOT NULL,
|
||||
`album_privacy` enum('public','password','private','private_but_link','custom') DEFAULT 'public',
|
||||
`album_privacy_extra` mediumtext,
|
||||
`album_password` mediumtext,
|
||||
`album_privacy_extra` text,
|
||||
`album_password` text,
|
||||
`album_image_count` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_description` mediumtext,
|
||||
`album_description` text,
|
||||
`album_likes` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_cover_id` bigint(32) DEFAULT NULL,
|
||||
`album_parent_id` bigint(32) DEFAULT NULL,
|
||||
`album_cta_enable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`album_cta` longtext,
|
||||
`album_cta` text,
|
||||
PRIMARY KEY (`album_id`),
|
||||
KEY `album_name` (`album_name`),
|
||||
KEY `album_user_id` (`album_user_id`),
|
||||
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE `%table_prefix%api_keys` (
|
||||
`api_key_user_id` bigint(32) DEFAULT NULL,
|
||||
`api_key_name` varchar(100) DEFAULT NULL,
|
||||
`api_key_date_gmt` datetime NOT NULL,
|
||||
`api_key_hash` mediumtext NOT NULL,
|
||||
`api_key_hash` text NOT NULL,
|
||||
PRIMARY KEY (`api_key_id`),
|
||||
KEY `api_key_user_id` (`api_key_user_id`),
|
||||
KEY `api_key_name` (`api_key_name`),
|
||||
|
||||
@@ -8,7 +8,6 @@ CREATE TABLE `%table_prefix%assets` (
|
||||
`asset_blob` blob,
|
||||
PRIMARY KEY (`asset_id`),
|
||||
UNIQUE KEY `key` (`asset_key`(191)) USING BTREE,
|
||||
KEY `md5` (`asset_md5`),
|
||||
KEY `filename` (`asset_filename`),
|
||||
KEY `file_path` (`asset_file_path`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -2,8 +2,8 @@ DROP TABLE IF EXISTS `%table_prefix%categories`;
|
||||
CREATE TABLE `%table_prefix%categories` (
|
||||
`category_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`category_name` varchar(32) NOT NULL,
|
||||
`category_url_key` varchar(32) NOT NULL,
|
||||
`category_description` mediumtext,
|
||||
`category_url_key` varchar(32) COLLATE utf8mb4_bin NOT NULL,
|
||||
`category_description` text,
|
||||
PRIMARY KEY (`category_id`),
|
||||
UNIQUE KEY `url_key` (`category_url_key`) USING BTREE
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -8,5 +8,8 @@ CREATE TABLE `%table_prefix%confirmations` (
|
||||
`confirmation_token_hash` varchar(255) NOT NULL,
|
||||
`confirmation_status` enum('active','valid','invalid') NOT NULL,
|
||||
`confirmation_extra` mediumtext,
|
||||
PRIMARY KEY (`confirmation_id`)
|
||||
PRIMARY KEY (`confirmation_id`),
|
||||
KEY `confirmation_user` (`confirmation_user_id`),
|
||||
KEY `confirmation_user_type` (`confirmation_user_id`, `confirmation_type`),
|
||||
KEY `confirmation_user_type_status_date` (`confirmation_user_id`, `confirmation_type`, `confirmation_status`, `confirmation_date_gmt`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -9,7 +9,7 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_date` datetime NOT NULL,
|
||||
`image_date_gmt` datetime NOT NULL,
|
||||
`image_title` varchar(100) DEFAULT NULL,
|
||||
`image_description` mediumtext,
|
||||
`image_description` text,
|
||||
`image_nsfw` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`image_user_id` bigint(32) DEFAULT NULL,
|
||||
`image_album_id` bigint(32) DEFAULT NULL,
|
||||
@@ -20,7 +20,7 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_md5` varchar(32) NOT NULL,
|
||||
`image_source_md5` varchar(32) DEFAULT NULL,
|
||||
`image_original_filename` varchar(255) NOT NULL,
|
||||
`image_original_exifdata` longtext,
|
||||
`image_original_exifdata` text,
|
||||
`image_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`image_category_id` bigint(32) DEFAULT NULL,
|
||||
`image_chain` tinyint(3) NOT NULL,
|
||||
@@ -34,10 +34,10 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_is_360` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`image_duration` int(11) NOT NULL DEFAULT '0',
|
||||
`image_type` tinyint(3) UNSIGNED as (case
|
||||
when `image_extension` in ('pdf', 'doc', 'md') then 4
|
||||
when `image_extension` in ('mp3', 'm4a', 'wav') then 3
|
||||
when `image_extension` in ('mp4', 'webm') then 2
|
||||
when `image_extension` in ('jpg', 'jpeg', 'gif', 'png', 'webp') then 1
|
||||
when `image_extension` in ('pdf','doc','md') then 4
|
||||
when `image_extension` in ('mp3','m4a','wav') then 3
|
||||
when `image_extension` in ('mp4','webm','mov') then 2
|
||||
when `image_extension` in ('avif','jpg','jpeg','gif','png','webp') then 1
|
||||
else 0 end) stored,
|
||||
PRIMARY KEY (`image_id`),
|
||||
KEY `image_name` (`image_name`),
|
||||
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE `%table_prefix%importing` (
|
||||
`importing_import_id` bigint(32) NOT NULL,
|
||||
`importing_path` varchar(4096) NOT NULL,
|
||||
`importing_content_type` enum('user','album','image') NOT NULL,
|
||||
`importing_content_id` bigint(32) NOT NULL DEFAULT '0',
|
||||
`importing_content_id` bigint(32) DEFAULT NULL,
|
||||
PRIMARY KEY (`importing_id`),
|
||||
UNIQUE KEY `importing_path` (`importing_path`(191))
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -5,8 +5,8 @@ CREATE TABLE `%table_prefix%login_connections` (
|
||||
`login_connection_provider_id` bigint(32) NOT NULL,
|
||||
`login_connection_date_gmt` datetime NOT NULL,
|
||||
`login_connection_resource_id` varchar(255) NOT NULL,
|
||||
`login_connection_resource_name` mediumtext,
|
||||
`login_connection_token` mediumtext NOT NULL COMMENT 'Ciphertext',
|
||||
`login_connection_resource_name` text,
|
||||
`login_connection_token` text NOT NULL COMMENT 'Ciphertext',
|
||||
PRIMARY KEY (`login_connection_id`),
|
||||
UNIQUE KEY `login_connection_unique` (`login_connection_user_id`,`login_connection_provider_id`),
|
||||
KEY `login_connection_user_id` (`login_connection_user_id`),
|
||||
|
||||
@@ -5,8 +5,8 @@ CREATE TABLE `%table_prefix%login_cookies` (
|
||||
`login_cookie_connection_id` bigint(32) DEFAULT 0,
|
||||
`login_cookie_date_gmt` datetime NOT NULL,
|
||||
`login_cookie_ip` varchar(255) DEFAULT NULL,
|
||||
`login_cookie_user_agent` mediumtext NOT NULL,
|
||||
`login_cookie_hash` mediumtext NOT NULL,
|
||||
`login_cookie_user_agent` text NOT NULL,
|
||||
`login_cookie_hash` text NOT NULL,
|
||||
PRIMARY KEY (`login_cookie_id`),
|
||||
UNIQUE KEY `login_cookie_unique` (`login_cookie_user_id`,`login_cookie_connection_id`,`login_cookie_date_gmt`),
|
||||
KEY `login_cookie_user_id_date_gmt` (`login_cookie_user_id`, `login_cookie_date_gmt`),
|
||||
|
||||
@@ -3,7 +3,7 @@ CREATE TABLE `%table_prefix%login_passwords` (
|
||||
`login_password_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`login_password_user_id` bigint(32) NOT NULL,
|
||||
`login_password_date_gmt` datetime NOT NULL,
|
||||
`login_password_hash` mediumtext NOT NULL,
|
||||
`login_password_hash` text NOT NULL,
|
||||
PRIMARY KEY (`login_password_id`),
|
||||
UNIQUE KEY `login_password_user_id` (`login_password_user_id`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -3,8 +3,8 @@ CREATE TABLE `%table_prefix%login_providers` (
|
||||
`login_provider_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`login_provider_name` varchar(255) DEFAULT NULL,
|
||||
`login_provider_label` varchar(255) DEFAULT NULL,
|
||||
`login_provider_key_id` mediumtext DEFAULT NULL,
|
||||
`login_provider_key_secret` mediumtext DEFAULT NULL,
|
||||
`login_provider_key_id` text DEFAULT NULL,
|
||||
`login_provider_key_secret` text DEFAULT NULL,
|
||||
`login_provider_is_enabled` tinyint(1) NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`login_provider_id`),
|
||||
UNIQUE KEY `login_provider_name` (`login_provider_name`(191)),
|
||||
|
||||
@@ -4,15 +4,15 @@ CREATE TABLE `%table_prefix%logins` (
|
||||
`login_user_id` bigint(32) NOT NULL,
|
||||
`login_type` enum('password','session','cookie','facebook','twitter','google','vk','cookie_facebook','cookie_twitter','cookie_google','cookie_vk') NOT NULL,
|
||||
`login_ip` varchar(255) DEFAULT NULL,
|
||||
`login_hostname` mediumtext,
|
||||
`login_hostname` text,
|
||||
`login_date` datetime NOT NULL,
|
||||
`login_date_gmt` datetime NOT NULL,
|
||||
`login_resource_id` varchar(255) DEFAULT NULL,
|
||||
`login_resource_name` mediumtext,
|
||||
`login_resource_avatar` mediumtext,
|
||||
`login_resource_url` mediumtext,
|
||||
`login_secret` mediumtext DEFAULT NULL COMMENT 'The secret part',
|
||||
`login_token_hash` mediumtext COMMENT 'Hashed complement to secret if needed',
|
||||
`login_resource_name` text,
|
||||
`login_resource_avatar` text,
|
||||
`login_resource_url` text,
|
||||
`login_secret` text DEFAULT NULL COMMENT 'The secret part',
|
||||
`login_token_hash` text COMMENT 'Hashed complement to secret if needed',
|
||||
PRIMARY KEY (`login_id`),
|
||||
KEY `login_user_id` (`login_user_id`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -4,18 +4,18 @@ CREATE TABLE `%table_prefix%pages` (
|
||||
`page_url_key` varchar(32) DEFAULT NULL,
|
||||
`page_type` enum('internal','link') NOT NULL DEFAULT 'internal',
|
||||
`page_file_path` varchar(255) DEFAULT NULL,
|
||||
`page_link_url` mediumtext,
|
||||
`page_link_url` text,
|
||||
`page_icon` varchar(255) DEFAULT NULL,
|
||||
`page_title` varchar(255) NOT NULL,
|
||||
`page_description` mediumtext,
|
||||
`page_keywords` mediumtext,
|
||||
`page_description` text,
|
||||
`page_keywords` text,
|
||||
`page_is_active` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`page_is_link_visible` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`page_attr_target` enum('_self','_blank') DEFAULT '_self',
|
||||
`page_attr_rel` varchar(255) DEFAULT NULL,
|
||||
`page_sort_display` int(11) DEFAULT NULL,
|
||||
`page_internal` varchar(255) DEFAULT NULL,
|
||||
`page_code` mediumtext,
|
||||
`page_code` text,
|
||||
PRIMARY KEY (`page_id`),
|
||||
UNIQUE KEY `page_internal` (`page_internal`(191)),
|
||||
KEY `page_url_key` (`page_url_key`),
|
||||
|
||||
@@ -3,7 +3,7 @@ CREATE TABLE `%table_prefix%queues` (
|
||||
`queue_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`queue_type` enum('storage-delete') NOT NULL,
|
||||
`queue_date_gmt` datetime NOT NULL,
|
||||
`queue_args` longtext NOT NULL,
|
||||
`queue_args` text NOT NULL,
|
||||
`queue_join` bigint(32) NOT NULL,
|
||||
`queue_attempts` varchar(255) DEFAULT '0',
|
||||
`queue_status` enum('pending','failed') NOT NULL DEFAULT 'pending',
|
||||
|
||||
@@ -2,9 +2,9 @@ DROP TABLE IF EXISTS `%table_prefix%settings`;
|
||||
CREATE TABLE `%table_prefix%settings` (
|
||||
`setting_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`setting_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`setting_value` mediumtext,
|
||||
`setting_default` mediumtext,
|
||||
`setting_value` text,
|
||||
`setting_default` text,
|
||||
`setting_typeset` enum('string','bool') DEFAULT 'string',
|
||||
PRIMARY KEY (`setting_id`),
|
||||
KEY `setting_name` (`setting_name`)
|
||||
UNIQUE KEY `setting_name` (`setting_name`) USING BTREE
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -3,14 +3,17 @@ CREATE TABLE `%table_prefix%stats` (
|
||||
`stat_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`stat_type` enum('total','date') NOT NULL,
|
||||
`stat_date_gmt` date DEFAULT NULL,
|
||||
`stat_users` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_images` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_albums` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_image_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_album_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_image_likes` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_album_likes` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_disk_used` bigint(32) NOT NULL DEFAULT '0',
|
||||
`stat_users` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_images` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_albums` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_tags` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_cron_runs` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_cron_time` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_image_views` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_album_views` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_image_likes` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_album_likes` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`stat_disk_used` bigint(32) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`stat_id`),
|
||||
UNIQUE KEY `stat_date_gmt` (`stat_date_gmt`) USING BTREE,
|
||||
KEY `stat_type` (`stat_type`)
|
||||
|
||||
@@ -10,14 +10,17 @@ CREATE TABLE `%table_prefix%storages` (
|
||||
`storage_server` varchar(255) DEFAULT NULL,
|
||||
`storage_account_id` varchar(255) DEFAULT NULL,
|
||||
`storage_account_name` varchar(255) DEFAULT NULL,
|
||||
`storage_key` mediumtext,
|
||||
`storage_secret` mediumtext,
|
||||
`storage_key` text,
|
||||
`storage_secret` text,
|
||||
`storage_is_https` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`storage_is_active` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`storage_capacity` bigint(32) DEFAULT NULL,
|
||||
`storage_space_used` bigint(32) DEFAULT '0',
|
||||
`storage_type_chain` tinyint(3) NOT NULL DEFAULT '1',
|
||||
`storage_use_path_style_endpoint` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`storage_deleted_at` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`storage_id`),
|
||||
KEY `storage_api_id` (`storage_api_id`),
|
||||
KEY `storage_is_active` (`storage_is_active`)
|
||||
KEY `storage_is_active` (`storage_is_active`),
|
||||
KEY `storage_deleted_at` (`storage_deleted_at`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
19
app/schemas/mysql-5/tags.sql
Normal file
19
app/schemas/mysql-5/tags.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%tags`;
|
||||
CREATE TABLE `%table_prefix%tags` (
|
||||
`tag_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`tag_name` varchar(32) COLLATE utf8mb4_bin NOT NULL,
|
||||
`tag_description` text,
|
||||
`tag_user_id` bigint(32) NOT NULL,
|
||||
`tag_date_gmt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`tag_files` bigint(32) NOT NULL DEFAULT 0,
|
||||
`tag_views` bigint(32) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`tag_id`),
|
||||
UNIQUE KEY `tag_name` (`tag_name`) USING BTREE,
|
||||
KEY `tag_user_id` (`tag_user_id`),
|
||||
KEY `tag_date_gmt` (`tag_date_gmt`),
|
||||
KEY `tag_files` (`tag_files`),˝
|
||||
KEY `tag_views` (`tag_views`),
|
||||
KEY `tag_user_id_date_gmt` (`tag_user_id`,`tag_date_gmt`),
|
||||
KEY `tag_user_id_files` (`tag_user_id`,`tag_files`),
|
||||
KEY `tag_user_id_views` (`tag_user_id`,`tag_views`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
14
app/schemas/mysql-5/tags_albums.sql
Normal file
14
app/schemas/mysql-5/tags_albums.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%tags_albums`;
|
||||
CREATE TABLE `%table_prefix%tags_albums` (
|
||||
`tag_album_tag_id` bigint(32) NOT NULL,
|
||||
`tag_album_album_id` bigint(32) NOT NULL,
|
||||
`tag_album_user_id` bigint(32) NOT NULL,
|
||||
`tag_album_count` int(11) NOT NULL DEFAULT 0,
|
||||
`tag_album_last_used_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tag_album_tag_id) REFERENCES `%table_prefix%tags` (tag_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tag_album_album_id) REFERENCES `%table_prefix%albums` (album_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tag_album_user_id) REFERENCES `%table_prefix%users` (user_id) ON DELETE CASCADE,
|
||||
UNIQUE INDEX `tag_album_UNIQUE` (`tag_album_tag_id` ASC, `tag_album_album_id` ASC, `tag_album_user_id` ASC) VISIBLE,
|
||||
KEY `tag_album_count` (`tag_album_count`),
|
||||
KEY `tag_album_last_used_datetime` (`tag_album_last_used_datetime`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
8
app/schemas/mysql-5/tags_files.sql
Normal file
8
app/schemas/mysql-5/tags_files.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%tags_files`;
|
||||
CREATE TABLE `%table_prefix%tags_files` (
|
||||
`tag_file_tag_id` bigint(32) NOT NULL,
|
||||
`tag_file_file_id` bigint(32) NOT NULL,
|
||||
FOREIGN KEY (tag_file_tag_id) REFERENCES `%table_prefix%tags` (tag_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tag_file_file_id) REFERENCES `%table_prefix%images` (image_id) ON DELETE CASCADE,
|
||||
UNIQUE INDEX `tag_file_UNIQUE` (`tag_file_tag_id` ASC, `tag_file_file_id` ASC) VISIBLE
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
12
app/schemas/mysql-5/tags_users.sql
Normal file
12
app/schemas/mysql-5/tags_users.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%tags_users`;
|
||||
CREATE TABLE `%table_prefix%tags_users` (
|
||||
`tag_user_tag_id` bigint(32) NOT NULL,
|
||||
`tag_user_user_id` bigint(32) NOT NULL,
|
||||
`tag_user_count` int(11) NOT NULL DEFAULT 0,
|
||||
`tag_user_last_used_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tag_user_tag_id) REFERENCES `%table_prefix%tags` (tag_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tag_user_user_id) REFERENCES `%table_prefix%users` (user_id) ON DELETE CASCADE,
|
||||
UNIQUE INDEX `tag_user_UNIQUE` (`tag_user_tag_id` ASC, `tag_user_user_id` ASC) VISIBLE,
|
||||
KEY `tag_user_count` (`tag_user_count`),
|
||||
KEY `tag_user_last_used_datetime` (`tag_user_last_used_datetime`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
@@ -3,7 +3,7 @@ CREATE TABLE `%table_prefix%two_factors` (
|
||||
`two_factor_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`two_factor_user_id` bigint(32) DEFAULT NULL,
|
||||
`two_factor_date_gmt` datetime NOT NULL,
|
||||
`two_factor_secret` mediumtext NOT NULL,
|
||||
`two_factor_secret` text NOT NULL,
|
||||
PRIMARY KEY (`two_factor_id`),
|
||||
KEY `two_factor_user_id` (`two_factor_user_id`),
|
||||
KEY `two_factor_date_gmt` (`two_factor_date_gmt`)
|
||||
|
||||
@@ -24,6 +24,7 @@ CREATE TABLE `%table_prefix%users` (
|
||||
`user_image_count` bigint(32) NOT NULL DEFAULT '0',
|
||||
`user_album_count` bigint(32) NOT NULL DEFAULT '0',
|
||||
`user_image_keep_exif` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`user_file_meta_tag_camera_model` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`user_image_expiration` varchar(255) DEFAULT NULL,
|
||||
`user_registration_ip` varchar(255) NOT NULL,
|
||||
`user_likes` bigint(32) NOT NULL DEFAULT '0' COMMENT 'Likes made to content owned by this user',
|
||||
@@ -46,6 +47,7 @@ CREATE TABLE `%table_prefix%users` (
|
||||
KEY `user_image_count` (`user_image_count`),
|
||||
KEY `user_album_count` (`user_album_count`),
|
||||
KEY `user_image_keep_exif` (`user_image_keep_exif`),
|
||||
KEY `user_file_meta_tag_camera_model` (`user_file_meta_tag_camera_model`),
|
||||
KEY `user_image_expiration` (`user_image_expiration`),
|
||||
KEY `user_registration_ip` (`user_registration_ip`),
|
||||
KEY `user_likes` (`user_likes`),
|
||||
|
||||
10
app/schemas/mysql-5/variables.sql
Normal file
10
app/schemas/mysql-5/variables.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%variables`;
|
||||
CREATE TABLE `%table_prefix%variables` (
|
||||
`variable_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`variable_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`variable_datetime_utc` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`variable_value` text,
|
||||
`variable_type` enum('string','bool','int','float','array','object') DEFAULT 'string',
|
||||
PRIMARY KEY (`variable_id`),
|
||||
UNIQUE KEY `variable_name` (`variable_name`) USING BTREE
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
|
||||
@@ -7,16 +7,16 @@ CREATE TABLE `%table_prefix%albums` (
|
||||
`album_date_gmt` datetime NOT NULL,
|
||||
`album_creation_ip` varchar(255) NOT NULL,
|
||||
`album_privacy` enum('public','password','private','private_but_link','custom') DEFAULT 'public',
|
||||
`album_privacy_extra` mediumtext,
|
||||
`album_password` mediumtext,
|
||||
`album_privacy_extra` text,
|
||||
`album_password` text,
|
||||
`album_image_count` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_description` mediumtext,
|
||||
`album_description` text,
|
||||
`album_likes` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`album_cover_id` bigint(32) DEFAULT NULL,
|
||||
`album_parent_id` bigint(32) DEFAULT NULL,
|
||||
`album_cta_enable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`album_cta` longtext,
|
||||
`album_cta` text,
|
||||
PRIMARY KEY (`album_id`),
|
||||
KEY `album_name` (`album_name`),
|
||||
KEY `album_user_id` (`album_user_id`),
|
||||
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE `%table_prefix%api_keys` (
|
||||
`api_key_user_id` bigint(32) DEFAULT NULL,
|
||||
`api_key_name` varchar(100) DEFAULT NULL,
|
||||
`api_key_date_gmt` datetime NOT NULL,
|
||||
`api_key_hash` mediumtext NOT NULL,
|
||||
`api_key_hash` text NOT NULL,
|
||||
PRIMARY KEY (`api_key_id`),
|
||||
KEY `api_key_user_id` (`api_key_user_id`),
|
||||
KEY `api_key_name` (`api_key_name`),
|
||||
|
||||
@@ -8,7 +8,6 @@ CREATE TABLE `%table_prefix%assets` (
|
||||
`asset_blob` blob,
|
||||
PRIMARY KEY (`asset_id`),
|
||||
UNIQUE KEY `key` (`asset_key`) USING BTREE,
|
||||
KEY `md5` (`asset_md5`),
|
||||
KEY `filename` (`asset_filename`),
|
||||
KEY `file_path` (`asset_file_path`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -2,8 +2,8 @@ DROP TABLE IF EXISTS `%table_prefix%categories`;
|
||||
CREATE TABLE `%table_prefix%categories` (
|
||||
`category_id` bigint(32) NOT NULL AUTO_INCREMENT,
|
||||
`category_name` varchar(32) NOT NULL,
|
||||
`category_url_key` varchar(32) NOT NULL,
|
||||
`category_description` mediumtext,
|
||||
`category_url_key` varchar(32) COLLATE utf8mb4_bin NOT NULL,
|
||||
`category_description` text,
|
||||
PRIMARY KEY (`category_id`),
|
||||
UNIQUE KEY `url_key` (`category_url_key`) USING BTREE
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -7,6 +7,9 @@ CREATE TABLE `%table_prefix%confirmations` (
|
||||
`confirmation_date_gmt` datetime NOT NULL,
|
||||
`confirmation_token_hash` varchar(255) NOT NULL,
|
||||
`confirmation_status` enum('active','valid','invalid') NOT NULL,
|
||||
`confirmation_extra` mediumtext,
|
||||
PRIMARY KEY (`confirmation_id`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8;
|
||||
`confirmation_extra` text,
|
||||
PRIMARY KEY (`confirmation_id`),
|
||||
KEY `confirmation_user` (`confirmation_user_id`),
|
||||
KEY `confirmation_user_type` (`confirmation_user_id`, `confirmation_type`),
|
||||
KEY `confirmation_user_type_status_date` (`confirmation_user_id`, `confirmation_type`, `confirmation_status`, `confirmation_date_gmt`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8;
|
||||
|
||||
@@ -9,7 +9,7 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_date` datetime NOT NULL,
|
||||
`image_date_gmt` datetime NOT NULL,
|
||||
`image_title` varchar(100) DEFAULT NULL,
|
||||
`image_description` mediumtext,
|
||||
`image_description` text,
|
||||
`image_nsfw` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`image_user_id` bigint(32) DEFAULT NULL,
|
||||
`image_album_id` bigint(32) DEFAULT NULL,
|
||||
@@ -20,7 +20,7 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_md5` varchar(32) NOT NULL,
|
||||
`image_source_md5` varchar(32) DEFAULT NULL,
|
||||
`image_original_filename` varchar(255) NOT NULL,
|
||||
`image_original_exifdata` longtext,
|
||||
`image_original_exifdata` text,
|
||||
`image_views` bigint(32) NOT NULL DEFAULT '0',
|
||||
`image_category_id` bigint(32) DEFAULT NULL,
|
||||
`image_chain` tinyint(3) NOT NULL,
|
||||
@@ -34,10 +34,10 @@ CREATE TABLE `%table_prefix%images` (
|
||||
`image_is_360` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`image_duration` int(11) NOT NULL DEFAULT '0',
|
||||
`image_type` tinyint(3) UNSIGNED as (case
|
||||
when `image_extension` in ('pdf', 'doc', 'md') then 4
|
||||
when `image_extension` in ('mp3', 'm4a', 'wav') then 3
|
||||
when `image_extension` in ('mp4', 'webm') then 2
|
||||
when `image_extension` in ('jpg', 'jpeg', 'gif', 'png', 'webp') then 1
|
||||
when `image_extension` in ('pdf','doc','md') then 4
|
||||
when `image_extension` in ('mp3','m4a','wav') then 3
|
||||
when `image_extension` in ('mp4','webm','mov') then 2
|
||||
when `image_extension` in ('avif','jpg','jpeg','gif','png','webp') then 1
|
||||
else 0 end) stored,
|
||||
PRIMARY KEY (`image_id`),
|
||||
KEY `image_name` (`image_name`),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DROP TABLE IF EXISTS `%table_prefix%images_hash`;
|
||||
CREATE TABLE `%table_prefix%images_hash` (
|
||||
`image_hash_image_id` bigint(32) NOT NULL,
|
||||
`image_hash_hash` mediumtext NOT NULL,
|
||||
`image_hash_hash` text NOT NULL,
|
||||
PRIMARY KEY (`image_hash_image_id`)
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE `%table_prefix%importing` (
|
||||
`importing_import_id` bigint(32) NOT NULL,
|
||||
`importing_path` varchar(4096) NOT NULL,
|
||||
`importing_content_type` enum('user','album','image') NOT NULL,
|
||||
`importing_content_id` bigint(32) NOT NULL DEFAULT '0',
|
||||
`importing_content_id` bigint(32) DEFAULT NULL,
|
||||
PRIMARY KEY (`importing_id`),
|
||||
UNIQUE KEY `importing_path` (`importing_path`(767))
|
||||
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -5,8 +5,8 @@ CREATE TABLE `%table_prefix%login_connections` (
|
||||
`login_connection_provider_id` bigint(32) NOT NULL,
|
||||
`login_connection_date_gmt` datetime NOT NULL,
|
||||
`login_connection_resource_id` varchar(255) NOT NULL,
|
||||
`login_connection_resource_name` mediumtext,
|
||||
`login_connection_token` mediumtext NOT NULL COMMENT 'Ciphertext',
|
||||
`login_connection_resource_name` text,
|
||||
`login_connection_token` text NOT NULL COMMENT 'Ciphertext',
|
||||
PRIMARY KEY (`login_connection_id`),
|
||||
UNIQUE KEY `login_connection_unique` (`login_connection_user_id`,`login_connection_provider_id`),
|
||||
KEY `login_connection_user_id` (`login_connection_user_id`),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user