Compare commits

..

No commits in common. "4.2" and "4.1.1" have entirely different histories.
4.2 ... 4.1.1

369 changed files with 35326 additions and 58034 deletions

View file

@ -1,9 +1,9 @@
<?php
/*
* This file is part of Chevereto.
* This file is part of Chevere.
*
* (c) Rodolfo Berrios <rodolfo@chevereto.com>
* (c) Rodolfo Berrios <rodolfo@chevere.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,113 +11,202 @@
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\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\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\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\NoAlternativeSyntaxFixer;
use PhpCsFixer\Fixer\FunctionNotation\LambdaNotUsedImportFixer;
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\Import\OrderedImportsFixer;
use PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer;
use PhpCsFixer\Fixer\Import\SingleLineAfterImportsFixer;
use PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveUnsetsFixer;
use PhpCsFixer\Fixer\LanguageConstruct\SingleSpaceAroundConstructFixer;
use PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer;
use PhpCsFixer\Fixer\NamespaceNotation\CleanNamespaceFixer;
use PhpCsFixer\Fixer\Operator\NoSpaceAroundDoubleColonFixer;
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\Operator\ObjectOperatorWithoutWhitespaceFixer;
use PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer;
use PhpCsFixer\Fixer\PhpTag\LinebreakAfterOpeningTagFixer;
use PhpCsFixer\Fixer\ReturnNotation\NoUselessReturnFixer;
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\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\TypesSpacesFixer;
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 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 $ecsConfig): void {
$ecsConfig->parallel();
return static function (ECSConfig $containerConfigurator): void {
$headerFile = __DIR__ . '/.header';
$ecsConfig->sets([SetList::PSR_12, SetList::COMMON]);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
SetList::COMMON,
]);
$services = $containerConfigurator->services();
if (file_exists($headerFile)) {
$ecsConfig->ruleWithConfiguration(HeaderCommentFixer::class, [
'header' => file_get_contents($headerFile),
'location' => 'after_open',
]);
$services->set(HeaderCommentFixer::class)
->call('configure', [[
'header' => file_get_contents($headerFile),
'location' => 'after_open',
]]);
}
$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([
$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, [
SingleImportPerStatementFixer::class => null,
]);
};

View file

@ -10,15 +10,13 @@
*/
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig;
use Symplify\EasyCodingStandard\ValueObject\Option;
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/',
]);
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, []);
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 KiB

View file

@ -14,10 +14,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
php: ["8.1"]
env:
tools: composer
ini-values: default_charset='UTF-8'
php: ["8.2"]
name: Build on PHP ${{ matrix.php }} ${{ matrix.os }}
steps:
- name: Checkout
@ -30,14 +27,6 @@ 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
@ -53,7 +42,7 @@ jobs:
type=semver,pattern={{major}}
labels: |
org.opencontainers.image.title=Chevereto V4
org.opencontainers.image.description=Ultimate image and video sharing software
org.opencontainers.image.description=Ultimate image sharing software
org.opencontainers.image.vendor=Chevereto
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@ -84,7 +73,6 @@ jobs:
rm -rf README.md chevereto.svg rector.php
rm -rf app/tests app/phpunit*.xml
rm -rf app/.editions app/bin/edition
mkdir images/_assets
mkdir importing/{parse-users,parse-albums,no-parse}
mv .package ..
ls -la ../.package

View file

@ -1,4 +1,4 @@
name: Release Free edition
name: Release
on:
push:
@ -54,7 +54,6 @@ jobs:
rm -rf README.md chevereto.svg rector.php
rm -rf app/tests app/phpunit*.xml
rm -rf app/.editions app/bin/edition
mkdir images/_assets
mkdir importing/{parse-users,parse-albums,no-parse}
mv .package ..
ls -la ../.package

2
.gitignore vendored
View file

@ -2,7 +2,7 @@
/.env
/.idea
/app/.upgrading
/app/CHEVERETO_LICENSE_KEY**
/app/CHEVERETO_LICENSE_KEY
/app/vendor
/app/build
/app/.phpunit.cache

View file

@ -20,12 +20,12 @@ Options -MultiViews
#RewriteRule images/.+\.(gif|jpe?g|a?png|bmp|webp) content/images/system/default/404.gif [NC,L]
RewriteRule images/.+\.(gif|jpe?g|png|bmp|webp) - [NC,L,R=404]
# PHP front controller
# PHP front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
# Single PHP-entrypoint
RewriteCond %{THE_REQUEST} ^.+?\ [^?]+\.php[?\ ] [NC]
RewriteRule \.php$ - [NC,L,F,R=404]
</IfModule>
# Single PHP-entrypoint
RewriteCond %{THE_REQUEST} ^.+?\ [^?]+\.php[?\ ] [NC]
RewriteRule \.php$ - [NC,L,F,R=404]
</IfModule>

19
.package/4.1.1.txt Normal file
View file

@ -0,0 +1,19 @@
Chevereto 4.1.1 (2024-04-27)
- 🎥 Added FFmpeg detection on Dashboard
- 🎥 Added support for MOV files (video/quicktime)
- 🎥 Improved detection of FFmpeg required functions proc_open and proc_close
- 🎥 Improved FFprobe handling when processing video
- 🎥 Improved video display for listing viewer
- 💅 Added display title to listing viewer
- 💅 Fixed files remark on Dashboard
- 💅 Fixed file remarks on Bulk importer stats
- 💅 Improved image viewer & natural zoom
- 💅 Improved menu display for mobile
- 💅 Updated homepage cover image
- 🔑 Improved feedback on license key handling
- 🐞 Fixed bug with missing scroll behavior
- 🐞 Fixed bug with not working URL upload
- 🐞 Fixed bug with video upload not working on iOS
- 🐞 Fixed bug with file-upload documentation link
- 🇨🇱 Updated Spanish translation

View file

@ -1,8 +0,0 @@
Chevereto 4.2.4 (2024-12-05)
- Added Chevereto Lite edition
- Added placeholders for comments code
- Improved comment code page id
- Improved ENV handling
- Fixed bug affecting CLI runtime
- Fixed bug affecting MariaDB 10.4 compatibility

View file

@ -9,7 +9,6 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\getCheveretoEnv;
use function Chevereto\Legacy\loaderHandler;
class CustomTinkerwellDriver extends TinkerwellDriver
@ -26,7 +25,7 @@ class CustomTinkerwellDriver extends TinkerwellDriver
require $projectPath . '/app/legacy/load/loader.php';
include loaderHandler(
_cookie: [],
_env: getCheveretoEnv(),
_env: $_ENV,
_files: [],
_get: [],
_post: [],

177
README.md
View file

@ -1,71 +1,144 @@
# Chevereto: Ultimate image and video sharing software
> 🔔 [Subscribe](https://chv.to/newsletter) to don't miss any update regarding Chevereto.
<p align="center">
<a href="https://chevereto.com"><img alt="Chevereto" src="chevereto.svg" width="80%"></a>
</p>
[![Chevereto](.github/banner/chevereto-ultimate-remix.png)](https://chevereto.com)
[![Chevereto Docs](https://img.shields.io/badge/chevereto-docs-50C878?style=flat-square)](https://v4-docs.chevereto.com/)
[![Chevereto Community](https://img.shields.io/badge/chevereto-community-blue?style=flat-square)](https://chevereto.com/community)
[![Chevereto Demo](https://img.shields.io/badge/chevereto-demo-d4af37?style=flat-square&color=red)](https://demo.chevereto.com)
[![Community](https://img.shields.io/badge/chevereto-community-blue?style=flat-square)](https://chevereto.com/community)
[![Discord](https://img.shields.io/badge/chevereto-discord-5865F2?style=flat-square)](https://chevereto.com/go/discord)
[![AGPL-3.0-only](https://img.shields.io/github/license/chevereto/chevereto?style=flat-square)](LICENSE)
[![Legacy stars](https://img.shields.io/github/stars/rodber/chevereto-free?style=flat-square&logo=github&label=Legacy%20stars&color=gold)](https://github.com/rodber/chevereto-free)
[![Legacy stars](https://img.shields.io/github/stars/rodber/chevereto-free?style=flat-square&logo=github&label=Legacy%20stars&color=red)](https://github.com/rodber/chevereto-free)
[![Awesome F/OSS](https://img.shields.io/badge/Awesome_F%2FOSS-Certified-black?colorA=&colorB=874efe&style=flat-square)](https://awsmfoss.com/chevereto/)
> 🔔 [Subscribe](https://chevereto.com/go/newsletter) to don't miss any update regarding Chevereto.
Chevereto enables to create a media sharing website on your own server. It's your hosting and your rules, say goodbye to closures and restrictions. ⭐️ [Live demo](https://demo.chevereto.com)
Chevereto is a 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.
Chevereto is a turnkey system which main use case is to provide a self-hosted platform for content creators, communities and businesses. It's features are all about media sharing, with a strong focus on user experience, privacy and security. On its pro edition Chevereto excels as a content management system with heavy business related features that you won't get on other systems.
This is the repository for **Chevereto Free** edition. You can [compare editions](https://v4-docs.chevereto.com/introduction/editions/compare.html) to find the Chevereto edition that best suits your needs.
![screen](.github/screen/user-profile.jpeg)
![screen](.github/screen/user-listing-selected.webp)
## Files supported
## Requirements
With Chevereto you can upload and share the following media types from device file browser, drag and drop, on-the-fly device camera (video and photos), clipboard, URL, ShareX and via API.
* A [webserver](https://v4-docs.chevereto.com/application/stack/web-server.html) (Apache recommended)
* [PHP](https://v4-docs.chevereto.com/application/stack/php.html) 8.1+ with [extensions](https://v4-docs.chevereto.com/application/stack/php.html#extensions)
* [MySQL Server](https://v4-docs.chevereto.com/application/stack/mysql-server.html) 8.0.1+ or MariaDB Server 10.2.2+
## Install
Chevereto runs anywhere, system requirements are minimal and it can run on any server.
Install Chevereto following our guides for:
* [Docker](https://github.com/chevereto/docker) (Multi-arch image compatible with `x86_64` and `arm64`)
* [Pure Docker](https://v4-docs.chevereto.com/guides/docker/pure-docker)
* [Chevereto Docker](https://v4-docs.chevereto.com/guides/docker/)
* [VPS](https://v4-docs.chevereto.com/guides/server/vps) (DigitalOcean, Linode, Vultr, etc)
* [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), [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
* Follow the [Updating guide](https://v4-docs.chevereto.com/application/installing/updating.html) to keep your Chevereto V4 system updated.
## Upgrading
For Chevereto V3 users:
* Follow the [Upgrading guide](https://v4-docs.chevereto.com/application/installing/upgrading.html) to upgrade to Chevereto V4.
* Check the [Welcome Back](https://v4-docs.chevereto.com/introduction/changelog/welcome-back.html#from-chevereto-v3) reference.
For Chevereto V2 users:
* Follow the [Upgrading guide](https://v3-docs.chevereto.com/setup/server/upgrading.html) but skip directly to Chevereto V4.
- image/jpeg
- image/gif
- image/png
- image/webp
- image/bmp
- video/quicktime
- video/mp4
- video/webm
## Documentation
Chevereto [Documentation](https://v4-docs.chevereto.com) covers the system requirements, installation, configuration, and usage of the software. It also includes a [User manual](https://v4-user.chevereto.com/) and an [Admin manual](https://v4-admin.chevereto.com/).
Chevereto is so **feature-rich**, mature and robust that we need three layers of documentation for it. The project started on 2007 and it has been actively maintained since then.
## Contributing
- [Documentation](https://v4-docs.chevereto.com)
- [User manual](https://v4-user.chevereto.com/)
- [Admin manual](https://v4-admin.chevereto.com/)
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.
## Compare features
**Note:** This is the repository for Chevereto free edition. This software is intended for **personal usage** as it doesn't contain [all the features](https://chevereto.com/features) of commercial editions. 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.
| Feature | Free | Pro |
| ------------------------------------------------------------------------------- | -------- | --------------------- |
| Image & Video uploads | ✅ | ✅ |
| ShareX support | ✅ | ✅ |
| Supports 360° images | ✅ | ✅ |
| User profiles | ✅ | ✅ |
| Albums & Sub-albums | ✅ | ✅ |
| Categories | ✅ | ✅ |
| Search | ✅ | ✅ |
| Direct links | ✅ | ✅ |
| Delete link | ✅ | ✅ |
| Sharing | ✅ | ✅ |
| oEmbed | ✅ | ✅ |
| Admin web interface | ✅ | ✅ |
| Media, Album and Users listings | ✅ | ✅ |
| EXIF data | ✅ | ✅ |
| User-based API | ✅ | ✅ |
| Two-Factor Authentication (2FA) | ✅ | ✅ |
| Call-to-action album buttons | ✅ | ✅ |
| Random button | ✅ | ✅ |
| Encrypt secrets | ✅ | ✅ |
| System stats & usage | ✅ | ✅ |
| Custom semantics | ✅ | ✅ |
| One-click upgrade (web & CLI) | ✅ | ✅ |
| Theme palettes (10) | ✅ | ✅ |
| Custom JS & CSS | ✅ | ✅ |
| Supports GD & ImageMagick | ✅ | ✅ |
| Duplicate media detection | ✅ | ✅ |
| Docker support | ✅ | ✅ |
| CLI commands | ✅ | ✅ |
| Multiple languages (configurable) | ✅ | ✅ |
| Website mode (public, private) | ✅ | ✅ |
| Default timezone selection | ✅ | ✅ |
| Enable/disable NSFW listings | ✅ | ✅ |
| Enable/disable blur NSFW content | ✅ | ✅ |
| Classic + Endless scroll listings | ✅ | ✅ |
| Configurable listings | ✅ | ✅ |
| Anywhere uploader | ✅ | ✅ |
| Embed codes on upload complete | ✅ | ✅ |
| Embed codes on selected media | ✅ | ✅ |
| Embed codes media view | ✅ | ✅ |
| Expirable uploads | ✅ | ✅ |
| Storage modes (date, direct) | ✅ | ✅ |
| Filenaming (original, id, random, mixed) | ✅ | ✅ |
| Thumbs & medium sized images | ✅ | ✅ |
| CDN support (any) | ✅ | ✅ |
| Maintenance mode | ✅ | ✅ |
| Crypt-salted IDs (no public integer ids) | ✅ | ✅ |
| Comments API (Disqus, any JS) | ✅ | ✅ |
| Email SMTP + phpmail() | ✅ | ✅ |
| Test-email tool | ✅ | ✅ |
| Debugger included ([xrDebug](https://xrdebug.com)) | ✅ | ✅ |
| REPL included ([PsySH](https://psysh.org), [Tinkerwel](https://tinkerwell.app)) | ✅ | ✅ |
| Source code available | ✅ | ✅ |
| Maximum resolution | No limit | No limit |
| License | AGPLv3 | Not-AGPL |
| Roles | admin | admin, manager & user |
| Multiple users & management | | ✅ |
| Multiple external storage servers | | ✅ |
| Explore & Discovery | | ✅ |
| Advanced search | | ✅ |
| Followers | | ✅ |
| Guest API | | ✅ |
| Likes | | ✅ |
| Manage banners | | ✅ |
| Consent screen (age gate) | | ✅ |
| Bulk content importer | | ✅ |
| Stop words | | ✅ |
| Custom homepage | | ✅ |
| Custom logo | | ✅ |
| Custom pages | | ✅ |
| Custom routing | | ✅ |
| Cookie consent | | ✅ |
| Notifications | | ✅ |
| Queue handling | | ✅ |
| IP banning | | ✅ |
| Upload moderation | | ✅ |
| Upload plugin (PUP.js) | | ✅ |
| Image watermarks | | ✅ |
| External services support | | ✅ |
| StopForumSpam | | ✅ |
| ModerateContent | | ✅ |
| Project Arachnid | | ✅ |
| Auth providers (OAuth2) | | ✅ |
## Supported servers
Chevereto runs anywhere, system requirements are minimal and it can run on any server.
- Shared hosting ([cPanel](https://v4-docs.chevereto.com/guides/cpanel/), [Plesk](https://v4-docs.chevereto.com/guides/plesk/), DirectAdmin, Installatron, Softaculous, etc)
- [VPS](https://v4-docs.chevereto.com/guides/server/vps) (DigitalOcean, Linode, Vultr, etc)
- [Docker](https://github.com/chevereto/docker) (Multi-arch image compatible with `x86_64` and `arm64`)
- [PURE DOCKER](https://v4-docs.chevereto.com/guides/docker/pure-docker)
- [Chevereto Docker](https://v4-docs.chevereto.com/guides/docker/)
## License
@ -81,12 +154,4 @@ You should have received a copy of the GNU Affero General Public License along w
### Commercial 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
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.*
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.com](https://chevereto.com/license)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
<?php
$translation_header = array (
'Project-Id-Version' => 'VERSION',
'POT-Creation-Date' => '2024-11-14 15:22+0000',
'PO-Revision-Date' => '2024-11-14 15:22+0000',
'POT-Creation-Date' => '2023-05-22 15:49+0000',
'PO-Revision-Date' => '2023-05-22 15:49+0000',
'Last-Translator' => 'FULL NAME <EMAIL@ADDRESS>',
'Language-Team' => 'LANGUAGE TEAM <EMAIL@ADDRESS>',
'Language' => 'pt',
@ -19,39 +19,21 @@ $translation_table = [
"You have been forbidden to use this website." => [
0 => "Foi proibido de usar este site.",
],
"Moderate" => [
0 => "Moderar",
],
"View all my images" => [
0 => "Ver todas as minhas imagens",
],
"Recent" => [
0 => "Recente",
],
"Trending" => [
0 => "Popular agora",
],
"Popular" => [
0 => "Popular",
],
"Animated" => [
0 => "Animadas",
],
"Request denied" => [
0 => "Pedido negado",
],
"terms" => [
0 => "termos",
],
"privacy policy" => [
0 => "política de privacidade",
],
"That page doesn't exist" => [
0 => "Esta página não existe",
],
"Page %s" => [
0 => "Página %s",
],
"Forgot password?" => [
0 => "Esqueceu-se da senha?",
],
@ -67,14 +49,11 @@ $translation_table = [
"Awaiting confirmation" => [
0 => "Aguardando confirmação",
],
"Two-factor authentication" => [
0 => "Autenticação de dois factores",
],
"Email changed" => [
0 => "E-mail alterado",
],
"Invalid Username/Email" => [
0 => "Nome de utilizador/Email inválido",
0 => "Nome de usuário inválido / Email",
],
"User doesn't have an email." => [
0 => "O utilizador não tem um e-mail.",
@ -85,9 +64,6 @@ $translation_table = [
"Account already activated" => [
0 => "Conta activada",
],
"Account banned" => [
0 => "Conta banida",
],
"Allow up to 15 minutes for the email. You can try again later." => [
0 => "Aguarde até 15 minutos pela recepção do e-mail. Poderá tentar novamente mais tarde.",
],
@ -112,9 +88,6 @@ $translation_table = [
"Email already being used" => [
0 => "Esse e-mail já está a ser utilizado",
],
"Invalid code" => [
0 => "Código inválido",
],
"Check the errors in the form to continue." => [
0 => "Verifique os erros no formulário para continuar.",
],
@ -124,9 +97,6 @@ $translation_table = [
"Embed codes" => [
0 => "Códigos para Incorporar",
],
"albums" => [
0 => "álbuns",
],
"%a album hosted in %w" => [
0 => "Álbum %a alojado em %w",
],
@ -134,6 +104,12 @@ $translation_table = [
0 => "imagem",
1 => "imagens",
],
"Stats" => [
0 => "Estatísticas",
],
"Images" => [
0 => "Imagens",
],
"Album" => [
0 => "Álbum",
1 => "Álbuns",
@ -157,11 +133,8 @@ $translation_table = [
"Listings" => [
0 => "Resultados",
],
"File uploads" => [
0 => "Envios de ficheiros",
],
"Semantics" => [
0 => "Semântica",
"Image upload" => [
0 => "Envio de imagem",
],
"Categories" => [
0 => "Categorias",
@ -178,11 +151,8 @@ $translation_table = [
"Email" => [
0 => "E-mail",
],
"Tools" => [
0 => "Ferramentas",
],
"Logo" => [
0 => "Logo",
"External storage" => [
0 => "Alojamento externo",
],
"Homepage" => [
0 => "Página principal",
@ -190,23 +160,11 @@ $translation_table = [
"Pages" => [
0 => "Páginas",
],
"Consent screen" => [
0 => "Janela de consentimento",
],
"Guests %s" => [
0 => "Convidados %s",
],
"External storage" => [
0 => "Alojamento externo",
],
"Routing" => [
0 => "Redireccionamento",
],
"External services" => [
0 => "Serviços externos",
],
"Flood protection" => [
0 => "Protecção contra abuso",
0 => "Protecção contra as inundações",
],
"IP bans" => [
0 => "Banimentos por IP",
@ -214,41 +172,57 @@ $translation_table = [
"Watermarks" => [
0 => "Marcas de água",
],
"Documentation" => [
0 => "Documentação",
],
"Support" => [
0 => "Suporte",
0 => "Suport",
],
"Community" => [
0 => "Comunidade",
],
"install update" => [
0 => "Instalar actualização",
],
"Stats" => [
0 => "Estatísticas",
],
"Rebuild stats" => [
0 => "Estatísticas de reconstrução",
],
"Not your IP?" => [
0 => "Não é o seu IP?",
],
"PHP version" => [
0 => "Versão do PHP",
],
"Server" => [
0 => "Servidor",
],
"MySQL version" => [
0 => "Versão do MySQL",
],
"MySQL server info" => [
0 => "Informação do servidor MySQL",
],
"File uploads" => [
0 => "Envios de ficheiros",
],
"Enabled" => [
0 => "Ativado",
],
"Disabled" => [
0 => "Desactivado",
],
"Releases" => [
0 => "Lançamentos",
"Max. execution time" => [
0 => "Tempo máximo de execução",
],
"Community" => [
0 => "Comunidade",
"%d second" => [
0 => "%d segundo",
1 => "%d segundos",
],
"Cron last ran" => [
0 => "Última execução do agendamento",
"Memory limit" => [
0 => "Limite de memória",
],
"PHP version" => [
0 => "Versão do PHP",
],
"Server" => [
0 => "Servidor",
"External" => [
0 => "Externo",
],
"All" => [
0 => "Todas",
@ -256,15 +230,33 @@ $translation_table = [
"search content" => [
0 => "conteúdo de pesquisa",
],
"Before pagination" => [
0 => "Antes de paginação",
],
"After pagination" => [
0 => "Depois de paginação",
],
"Before comments" => [
0 => "Antes dos comentários",
],
"Image page" => [
0 => "Página da imagem",
],
"Inside viewer top (image page)" => [
0 => "Topo da página para visualizar a imagem",
],
"Footer (image page)" => [
0 => "Rodapé (página imagem)",
],
"User profile page" => [
0 => "Página de perfil do utilizador",
],
"After top (user profile)" => [
0 => "Depois de topo (perfil do utlizador)",
],
"Explore" => [
0 => "Explorar",
],
"After top (%s page)" => [
0 => "Depois do topo (%s página)",
],
"NSFW" => [
0 => "18+",
],
"Invalid website name" => [
0 => "Nome da página inválido",
],
@ -274,9 +266,6 @@ $translation_table = [
"Invalid timezone" => [
0 => "Fuso horário inválido",
],
"Invalid value: %s" => [
0 => "Valor inválido: %s",
],
"Invalid thumb width" => [
0 => "largura da miniatura inválida",
],
@ -289,6 +278,45 @@ $translation_table = [
"Invalid value" => [
0 => "Valor inválido",
],
"Invalid theme image listing size" => [
0 => "Tamanho para os resultados do tema inválido",
],
"Invalid user id" => [
0 => "ID de usuário Inválido",
],
"Invalid email mode" => [
0 => "Modo de e-mail inválido",
],
"Invalid SMTP port" => [
0 => "Porta SMTP inválida",
],
"Invalid SMTP security" => [
0 => "Segurança inválida SMTP ",
],
"Invalid website mode" => [
0 => "Modo de website inválido",
],
"Invalid website content privacy mode" => [
0 => "modo de conteúdo do site privacidade inválido",
],
"Invalid homepage style" => [
0 => "Estilo da página principal inválido",
],
"Invalid URL" => [
0 => "URL inválido",
],
"Invalid upload image path" => [
0 => "Caminho para o envio de imagens inválido",
],
"Max. allowed %s" => [
0 => "Máximo permitido %s",
],
"Invalid SMTP server" => [
0 => "Servidor SMTP inválido",
],
"Invalid SMTP username" => [
0 => "Nome de usuário SMTP inválido",
],
"Dashboard" => [
0 => "Administração",
],
@ -310,6 +338,21 @@ $translation_table = [
"Image %i hosted in %w" => [
0 => "Imagem %i alojada em %w",
],
"Direct links" => [
0 => "Links Diretos",
],
"Image link" => [
0 => "Link da imagem",
],
"Image URL" => [
0 => "URL da imagem",
],
"Thumbnail URL" => [
0 => "URL Thumbnail",
],
"Medium URL" => [
0 => "URL Médio",
],
"Login needed" => [
0 => "Necessário iniciar sessão",
],
@ -320,6 +363,9 @@ $translation_table = [
"Category" => [
0 => "Categoria",
],
"IP address already banned" => [
0 => "Endereço de IP já banido",
],
"Missing values" => [
0 => "Valores em falta",
],
@ -332,9 +378,6 @@ $translation_table = [
"Username already being used" => [
0 => "Nome de utilizador já está a ser utilizado",
],
"IP address already banned" => [
0 => "Endereço de IP já banido",
],
"%s has been disconnected." => [
0 => "%s foi desconectado.",
],
@ -398,9 +441,6 @@ $translation_table = [
"User ID" => [
0 => "ID de utilizador",
],
"Images" => [
0 => "Imagens",
],
"Register date" => [
0 => "Data de registo",
],
@ -523,7 +563,7 @@ $translation_table = [
0 => "%s atrás",
],
"moments ago" => [
0 => "há poucos segundos",
0 => "à momentos atrás",
],
"Random" => [
0 => "Aleatório",
@ -579,24 +619,27 @@ $translation_table = [
"Error deleting profile background image." => [
0 => "Erro apagar imagem de fundo do perfil",
],
"Create album" => [
0 => "Criar álbum",
],
"Delete" => [
0 => "Eliminar",
],
"Edit" => [
0 => "Editar",
"Update available v%s" => [
0 => "Actualização disponível v%s",
],
"Like" => [
0 => "Gostar",
],
"Next" => [
0 => "Próximo",
"Create album" => [
0 => "Criar álbum",
],
"Edit" => [
0 => "Editar",
],
"Delete" => [
0 => "Eliminar",
],
"Previous" => [
0 => "Anterior",
],
"Next" => [
0 => "Próximo",
],
"File too big." => [
0 => "Ficheiro muito grande.",
],
@ -609,6 +652,9 @@ $translation_table = [
"%s's Albums" => [
0 => "Álbuns de %s",
],
"Image edited successfully." => [
0 => "Imagem editada com sucesso.",
],
"private" => [
0 => "Privado",
],
@ -741,6 +787,9 @@ $translation_table = [
"This email was sent from %w %u" => [
0 => "Este e-mail foi enviado por %w %u",
],
"Select the images to upload" => [
0 => "Selecionar as imagens para envio",
],
"complete" => [
0 => "completo",
],
@ -780,12 +829,36 @@ $translation_table = [
"Description" => [
0 => "Descrição",
],
"Add image URLs" => [
0 => "Adicionar URLs de imagem",
],
"Add the image URLs here" => [
0 => "Adicione os URLs de imagem aqui",
],
"Error report" => [
0 => "Relatório de erro",
],
"Direct" => [
0 => "Directo",
],
"HTML Codes" => [
0 => "Códigos HTML",
],
"HTML medium linked" => [
0 => "HTML médio",
],
"HTML thumbnail linked" => [
0 => "HTML da miniatura",
],
"BBCode medium linked" => [
0 => "Código BBCode do tamanho médio",
],
"BBCode thumbnail linked" => [
0 => "Código BBCode da miniatura",
],
"Viewer links" => [
0 => "Ver links",
],
"All these words" => [
0 => "Todas estas palavras",
],
@ -918,9 +991,6 @@ $translation_table = [
"There's nothing to show here." => [
0 => "Não há nada para ver aqui.",
],
"Selection will be assigned to %t." => [
0 => "A selecção vai ser atribuída a %t.",
],
"There is no categories." => [
0 => "Não existem categorias.",
],
@ -1092,33 +1162,6 @@ $translation_table = [
"Disk used" => [
0 => "Espaço usado",
],
"Enable uploads" => [
0 => "Activar envios",
],
"Guest uploads" => [
0 => "Envios de visitantes",
],
"Enable this if you want to allow non registered users to upload." => [
0 => "Ative isto se quiser permitir que os utilizadores não registados façam envios.",
],
"Relative to Chevereto root" => [
0 => "Relativo ao root do Chevereto",
],
"Storage mode" => [
0 => "Modo de armazenamento",
],
"Datefolders creates %s structure" => [
0 => "Datefolders cria %s estrutura",
],
"File naming method" => [
0 => "Método de nomeação do arquivo",
],
"Thumb size" => [
0 => "Tamanho da miniatura",
],
"Thumbnails will be fixed to this size." => [
0 => "As miniaturas serão ajustadas para este tamanho.",
],
"Notify to email" => [
0 => "Notificar para o e-mail",
],
@ -1164,6 +1207,39 @@ $translation_table = [
"Default" => [
0 => "Padrão",
],
"Enable uploads" => [
0 => "Activar envios",
],
"Guest uploads" => [
0 => "Envios de visitantes",
],
"Enable this if you want to allow non registered users to upload." => [
0 => "Ative isto se quiser permitir que os utilizadores não registados façam envios.",
],
"Image path" => [
0 => "Caminho da imagem",
],
"Relative to Chevereto root" => [
0 => "Relativo ao root do Chevereto",
],
"Where to store the images? Relative to Chevereto root." => [
0 => "Onde alojar as imagens? Relativo ao root do Chevereto.",
],
"Storage mode" => [
0 => "Modo de armazenamento",
],
"Datefolders creates %s structure" => [
0 => "Datefolders cria %s estrutura",
],
"File naming method" => [
0 => "Método de nomeação do arquivo",
],
"Thumb size" => [
0 => "Tamanho da miniatura",
],
"Thumbnails will be fixed to this size." => [
0 => "As miniaturas serão ajustadas para este tamanho.",
],
"Expires" => [
0 => "Expira",
],
@ -1399,11 +1475,14 @@ $translation_table = [
0 => "Endereço de email",
],
"Added to %s" => [
0 => "Adicionado a %s",
0 => "Adicionar a %s",
],
"Add IP ban" => [
0 => "Adicionar banimento de IP",
],
"Upload and share your images." => [
0 => "Envie e compartilhe as suas imagens.",
],
"Sign up to unlock all the features" => [
0 => "Registre-se agora Grátis",
],

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,6 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\getCheveretoEnv;
use function Chevereto\Legacy\loaderHandler;
define('ACCESS', 'web');
@ -17,7 +16,7 @@ define('REPL', true);
require __DIR__ . '/legacy/load/loader.php';
include loaderHandler(
_cookie: [],
_env: getCheveretoEnv(),
_env: $_ENV,
_files: [],
_get: [],
_post: [],
@ -29,7 +28,8 @@ include loaderHandler(
);
return [
'startupMessage' => <<<EOM
'startupMessage' =>
<<<EOM
__ __
____/ / ___ _ _____ _______ / /____
/ __/ _ \/ -_) |/ / -_) __/ -_) __/ _ \\

View file

@ -16,40 +16,36 @@
"composer/package-versions-deprecated": true
},
"platform": {
"php": "8.1.28"
"php": "8.0.26"
}
},
"require": {
"php": "^8.1",
"php": "^8.0",
"intervention/image": "^2.6",
"jeroendesloovere/xmp-metadata-extractor": "^2.0",
"league/flysystem": "^2.0",
"jenssegers/imagehash": "^0.5.0",
"guzzlehttp/psr7": "^1.7||^2",
"guzzlehttp/psr7": "^1.7",
"phpmailer/phpmailer": "^6.5",
"psr/cache": "^1",
"psr/log": "^1",
"phpseclib/phpseclib": "^3.0.37",
"phpseclib/phpseclib": "^3.0",
"mobiledetect/mobiledetectlib": "^2.8",
"mlocati/ip-lib": "^1.17",
"composer/ca-bundle": "^1.2",
"chevere/throwable-handler": "^1.0.2",
"xrdebug/php": "^2.0.2",
"xrdebug/xrdebug": "^2.0.2",
"chevere/workflow": "^0.9.0",
"chevere/chevere": "^2.0",
"chevere/throwable-handler": "^0.9",
"chevere/xr": "^0.7",
"chevere/xr-server": "^0.7",
"chevere/workflow": "^0.7.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",
"psy/psysh": "^0.11.8",
"chevere/cache": "^0.5.0",
"chevere/var-dump": "^2.0.x-dev",
"chevere/var-support": "^1.0"
"php-ffmpeg/php-ffmpeg": "^1.2"
},
"autoload": {
"files": [
@ -74,8 +70,10 @@
},
"require-dev": {
"phpunit/phpunit": "^9.2",
"symplify/easy-coding-standard": "^12.2",
"phpstan/phpstan": "^1.11"
"symplify/easy-coding-standard": "^10.3",
"phpstan/phpstan": "^1.4",
"rector/rector": "^0.12.15",
"psy/psysh": "^0.11.8"
},
"prefer-stable": true,
"scripts": {

3495
app/composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/
use Chevereto\Config\AssetConfig;
use Chevereto\Config\Config;
use Chevereto\Config\EnabledConfig;
use Chevereto\Config\HostConfig;
@ -17,6 +18,19 @@ 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'],

View file

@ -10,97 +10,82 @@
*/
return [
'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',
'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_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',
];

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: VERSION\n"
"POT-Creation-Date: 2024-11-14 15:22+0000\n"
"PO-Revision-Date: 2024-11-14 15:22+0000\n"
"POT-Creation-Date: 2023-05-22 15:49+0000\n"
"PO-Revision-Date: 2023-05-22 15:49+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE TEAM <EMAIL@ADDRESS>\n"
"Language: pt\n"
@ -14,40 +14,21 @@ msgstr ""
msgid "You have been forbidden to use this website."
msgstr "Foi proibido de usar este site."
msgid "Moderate"
msgstr "Moderar"
msgid "View all my images"
msgstr "Ver todas as minhas imagens"
msgid "Recent"
msgstr "Recente"
msgid "Trending"
msgstr "Popular agora"
msgid "Popular"
msgstr "Popular"
msgid "Animated"
msgstr "Animadas"
msgid "Request denied"
msgstr "Pedido negado"
msgid "terms"
msgstr "termos"
msgid "privacy policy"
msgstr "política de privacidade"
msgid "That page doesn't exist"
msgstr "Esta página não existe"
#, php-format
msgid "Page %s"
msgstr "Página %s"
msgid "Forgot password?"
msgstr "Esqueceu-se da senha?"
@ -63,14 +44,11 @@ msgstr "Adicione o seu endereço de email"
msgid "Awaiting confirmation"
msgstr "Aguardando confirmação"
msgid "Two-factor authentication"
msgstr "Autenticação de dois factores"
msgid "Email changed"
msgstr "E-mail alterado"
msgid "Invalid Username/Email"
msgstr "Nome de utilizador/Email inválido"
msgstr "Nome de usuário inválido / Email"
msgid "User doesn't have an email."
msgstr "O utilizador não tem um e-mail."
@ -81,9 +59,6 @@ msgstr "A conta precisa ser ativada antes de poder usar este recurso"
msgid "Account already activated"
msgstr "Conta activada"
msgid "Account banned"
msgstr "Conta banida"
msgid "Allow up to 15 minutes for the email. You can try again later."
msgstr "Aguarde até 15 minutos pela recepção do e-mail. Poderá tentar novamente mais tarde."
@ -111,9 +86,6 @@ msgstr "E-mail inválido"
msgid "Email already being used"
msgstr "Esse e-mail já está a ser utilizado"
msgid "Invalid code"
msgstr "Código inválido"
msgid "Check the errors in the form to continue."
msgstr "Verifique os erros no formulário para continuar."
@ -123,9 +95,6 @@ msgstr "É preciso senha"
msgid "Embed codes"
msgstr "Códigos para Incorporar"
msgid "albums"
msgstr "álbuns"
msgid "%a album hosted in %w"
msgstr "Álbum %a alojado em %w"
@ -134,6 +103,12 @@ msgid_plural "images"
msgstr[0] "imagem"
msgstr[1] "imagens"
msgid "Stats"
msgstr "Estatísticas"
msgid "Images"
msgstr "Imagens"
msgid "Album"
msgid_plural "Albums"
msgstr[0] "Álbum"
@ -159,11 +134,8 @@ msgstr "Conteúdo"
msgid "Listings"
msgstr "Resultados"
msgid "File uploads"
msgstr "Envios de ficheiros"
msgid "Semantics"
msgstr "Semântica"
msgid "Image upload"
msgstr "Envio de imagem"
msgid "Categories"
msgstr "Categorias"
@ -180,11 +152,8 @@ msgstr "Idiomas"
msgid "Email"
msgstr "E-mail"
msgid "Tools"
msgstr "Ferramentas"
msgid "Logo"
msgstr "Logo"
msgid "External storage"
msgstr "Alojamento externo"
msgid "Homepage"
msgstr "Página principal"
@ -192,24 +161,11 @@ msgstr "Página principal"
msgid "Pages"
msgstr "Páginas"
msgid "Consent screen"
msgstr "Janela de consentimento"
#, php-format
msgid "Guests %s"
msgstr "Convidados %s"
msgid "External storage"
msgstr "Alojamento externo"
msgid "Routing"
msgstr "Redireccionamento"
msgid "External services"
msgstr "Serviços externos"
msgid "Flood protection"
msgstr "Protecção contra abuso"
msgstr "Protecção contra as inundações"
msgid "IP bans"
msgstr "Banimentos por IP"
@ -217,41 +173,59 @@ msgstr "Banimentos por IP"
msgid "Watermarks"
msgstr "Marcas de água"
msgid "Documentation"
msgstr "Documentação"
msgid "Support"
msgstr "Suporte"
msgstr "Suport"
msgid "Community"
msgstr "Comunidade"
msgid "install update"
msgstr "Instalar actualização"
msgid "Stats"
msgstr "Estatísticas"
msgid "Rebuild stats"
msgstr "Estatísticas de reconstrução"
msgid "Not your IP?"
msgstr "Não é o seu IP?"
msgid "PHP version"
msgstr "Versão do PHP"
msgid "Server"
msgstr "Servidor"
msgid "MySQL version"
msgstr "Versão do MySQL"
msgid "MySQL server info"
msgstr "Informação do servidor MySQL"
msgid "File uploads"
msgstr "Envios de ficheiros"
msgid "Enabled"
msgstr "Ativado"
msgid "Disabled"
msgstr "Desactivado"
msgid "Releases"
msgstr "Lançamentos"
msgid "Max. execution time"
msgstr "Tempo máximo de execução"
msgid "Community"
msgstr "Comunidade"
#, php-format
msgid "%d second"
msgid_plural "%d seconds"
msgstr[0] "%d segundo"
msgstr[1] "%d segundos"
msgid "Cron last ran"
msgstr "Última execução do agendamento"
msgid "Memory limit"
msgstr "Limite de memória"
msgid "PHP version"
msgstr "Versão do PHP"
msgid "Server"
msgstr "Servidor"
msgid "External"
msgstr "Externo"
msgid "All"
msgstr "Todas"
@ -259,16 +233,33 @@ msgstr "Todas"
msgid "search content"
msgstr "conteúdo de pesquisa"
msgid "Before pagination"
msgstr "Antes de paginação"
msgid "After pagination"
msgstr "Depois de paginação"
msgid "Before comments"
msgstr "Antes dos comentários"
msgid "Image page"
msgstr "Página da imagem"
msgid "Inside viewer top (image page)"
msgstr "Topo da página para visualizar a imagem"
msgid "Footer (image page)"
msgstr "Rodapé (página imagem)"
msgid "User profile page"
msgstr "Página de perfil do utilizador"
msgid "After top (user profile)"
msgstr "Depois de topo (perfil do utlizador)"
msgid "Explore"
msgstr "Explorar"
#, php-format
msgid "After top (%s page)"
msgstr "Depois do topo (%s página)"
msgid "NSFW"
msgstr "18+"
msgid "Invalid website name"
msgstr "Nome da página inválido"
@ -278,10 +269,6 @@ msgstr "Idioma inválido"
msgid "Invalid timezone"
msgstr "Fuso horário inválido"
#, php-format
msgid "Invalid value: %s"
msgstr "Valor inválido: %s"
msgid "Invalid thumb width"
msgstr "largura da miniatura inválida"
@ -294,6 +281,46 @@ msgstr "Tema inválido"
msgid "Invalid value"
msgstr "Valor inválido"
msgid "Invalid theme image listing size"
msgstr "Tamanho para os resultados do tema inválido"
msgid "Invalid user id"
msgstr "ID de usuário Inválido"
msgid "Invalid email mode"
msgstr "Modo de e-mail inválido"
msgid "Invalid SMTP port"
msgstr "Porta SMTP inválida"
msgid "Invalid SMTP security"
msgstr "Segurança inválida SMTP "
msgid "Invalid website mode"
msgstr "Modo de website inválido"
msgid "Invalid website content privacy mode"
msgstr "modo de conteúdo do site privacidade inválido"
msgid "Invalid homepage style"
msgstr "Estilo da página principal inválido"
msgid "Invalid URL"
msgstr "URL inválido"
msgid "Invalid upload image path"
msgstr "Caminho para o envio de imagens inválido"
#, php-format
msgid "Max. allowed %s"
msgstr "Máximo permitido %s"
msgid "Invalid SMTP server"
msgstr "Servidor SMTP inválido"
msgid "Invalid SMTP username"
msgstr "Nome de usuário SMTP inválido"
msgid "Dashboard"
msgstr "Administração"
@ -315,6 +342,21 @@ msgstr "Imagem %i na categoria %c"
msgid "Image %i hosted in %w"
msgstr "Imagem %i alojada em %w"
msgid "Direct links"
msgstr "Links Diretos"
msgid "Image link"
msgstr "Link da imagem"
msgid "Image URL"
msgstr "URL da imagem"
msgid "Thumbnail URL"
msgstr "URL Thumbnail"
msgid "Medium URL"
msgstr "URL Médio"
msgid "Login needed"
msgstr "Necessário iniciar sessão"
@ -326,6 +368,9 @@ msgstr[1] "imagens"
msgid "Category"
msgstr "Categoria"
msgid "IP address already banned"
msgstr "Endereço de IP já banido"
msgid "Missing values"
msgstr "Valores em falta"
@ -338,9 +383,6 @@ msgstr "Papel inválido"
msgid "Username already being used"
msgstr "Nome de utilizador já está a ser utilizado"
msgid "IP address already banned"
msgstr "Endereço de IP já banido"
#, php-format
msgid "%s has been disconnected."
msgstr "%s foi desconectado."
@ -407,9 +449,6 @@ msgstr "Apagar utilizador"
msgid "User ID"
msgstr "ID de utilizador"
msgid "Images"
msgstr "Imagens"
msgid "Register date"
msgstr "Data de registo"
@ -545,7 +584,7 @@ msgid "%s ago"
msgstr "%s atrás"
msgid "moments ago"
msgstr "há poucos segundos"
msgstr "à momentos atrás"
msgid "Random"
msgstr "Aleatório"
@ -603,24 +642,28 @@ msgstr "Imagem de fundo eliminada."
msgid "Error deleting profile background image."
msgstr "Erro apagar imagem de fundo do perfil"
msgid "Create album"
msgstr "Criar álbum"
msgid "Delete"
msgstr "Eliminar"
msgid "Edit"
msgstr "Editar"
#, javascript-format
msgid "Update available v%s"
msgstr "Actualização disponível v%s"
msgid "Like"
msgstr "Gostar"
msgid "Next"
msgstr "Próximo"
msgid "Create album"
msgstr "Criar álbum"
msgid "Edit"
msgstr "Editar"
msgid "Delete"
msgstr "Eliminar"
msgid "Previous"
msgstr "Anterior"
msgid "Next"
msgstr "Próximo"
msgid "File too big."
msgstr "Ficheiro muito grande."
@ -634,6 +677,9 @@ msgstr "Alguns arquivos não puderam ser adiccionados"
msgid "%s's Albums"
msgstr "Álbuns de %s"
msgid "Image edited successfully."
msgstr "Imagem editada com sucesso."
msgid "private"
msgstr "Privado"
@ -774,6 +820,9 @@ msgstr "Obrigado por se juntar a nós"
msgid "This email was sent from %w %u"
msgstr "Este e-mail foi enviado por %w %u"
msgid "Select the images to upload"
msgstr "Selecionar as imagens para envio"
msgid "complete"
msgstr "completo"
@ -813,12 +862,36 @@ msgstr "Assinalar como inseguro"
msgid "Description"
msgstr "Descrição"
msgid "Add image URLs"
msgstr "Adicionar URLs de imagem"
msgid "Add the image URLs here"
msgstr "Adicione os URLs de imagem aqui"
msgid "Error report"
msgstr "Relatório de erro"
msgid "Direct"
msgstr "Directo"
msgid "HTML Codes"
msgstr "Códigos HTML"
msgid "HTML medium linked"
msgstr "HTML médio"
msgid "HTML thumbnail linked"
msgstr "HTML da miniatura"
msgid "BBCode medium linked"
msgstr "Código BBCode do tamanho médio"
msgid "BBCode thumbnail linked"
msgstr "Código BBCode da miniatura"
msgid "Viewer links"
msgstr "Ver links"
msgid "All these words"
msgstr "Todas estas palavras"
@ -951,9 +1024,6 @@ msgstr "Entre com outra conta"
msgid "There's nothing to show here."
msgstr "Não há nada para ver aqui."
msgid "Selection will be assigned to %t."
msgstr "A selecção vai ser atribuída a %t."
msgid "There is no categories."
msgstr "Não existem categorias."
@ -1128,34 +1198,6 @@ msgstr "Activo"
msgid "Disk used"
msgstr "Espaço usado"
msgid "Enable uploads"
msgstr "Activar envios"
msgid "Guest uploads"
msgstr "Envios de visitantes"
msgid "Enable this if you want to allow non registered users to upload."
msgstr "Ative isto se quiser permitir que os utilizadores não registados façam envios."
msgid "Relative to Chevereto root"
msgstr "Relativo ao root do Chevereto"
msgid "Storage mode"
msgstr "Modo de armazenamento"
#, php-format
msgid "Datefolders creates %s structure"
msgstr "Datefolders cria %s estrutura"
msgid "File naming method"
msgstr "Método de nomeação do arquivo"
msgid "Thumb size"
msgstr "Tamanho da miniatura"
msgid "Thumbnails will be fixed to this size."
msgstr "As miniaturas serão ajustadas para este tamanho."
msgid "Notify to email"
msgstr "Notificar para o e-mail"
@ -1201,6 +1243,40 @@ msgstr "Branco"
msgid "Default"
msgstr "Padrão"
msgid "Enable uploads"
msgstr "Activar envios"
msgid "Guest uploads"
msgstr "Envios de visitantes"
msgid "Enable this if you want to allow non registered users to upload."
msgstr "Ative isto se quiser permitir que os utilizadores não registados façam envios."
msgid "Image path"
msgstr "Caminho da imagem"
msgid "Relative to Chevereto root"
msgstr "Relativo ao root do Chevereto"
msgid "Where to store the images? Relative to Chevereto root."
msgstr "Onde alojar as imagens? Relativo ao root do Chevereto."
msgid "Storage mode"
msgstr "Modo de armazenamento"
#, php-format
msgid "Datefolders creates %s structure"
msgstr "Datefolders cria %s estrutura"
msgid "File naming method"
msgstr "Método de nomeação do arquivo"
msgid "Thumb size"
msgstr "Tamanho da miniatura"
msgid "Thumbnails will be fixed to this size."
msgstr "As miniaturas serão ajustadas para este tamanho."
msgid "Expires"
msgstr "Expira"
@ -1438,11 +1514,14 @@ msgstr "Endereço de email"
#, php-format
msgid "Added to %s"
msgstr "Adicionado a %s"
msgstr "Adicionar a %s"
msgid "Add IP ban"
msgstr "Adicionar banimento de IP"
msgid "Upload and share your images."
msgstr "Envie e compartilhe as suas imagens."
msgid "Sign up to unlock all the features"
msgstr "Registre-se agora Grátis"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,9 @@ use function Chevereto\Legacy\feedbackAlert;
use function Chevereto\Legacy\isSafeToExecute;
use function Chevereto\Vars\env;
if (! (bool) env()['CHEVERETO_ENABLE_BULK_IMPORTER']) {
if (!(bool) env()['CHEVERETO_ENABLE_BULK_IMPORTER']) {
feedbackAlert('Bulk importer is disabled');
exit(255);
die(255);
}
$threadID = getenv('THREAD_ID') ?: 0;
$loop = 1;
@ -26,7 +26,7 @@ do {
if ($jobs === []) {
echo "~They took our jobs!~\n";
echo "[OK] No jobs left.\n";
exit(0);
die(0);
}
$id = $jobs[0]['import_id'];
$import = new Import();
@ -34,15 +34,13 @@ do {
$import->thread = (int) $threadID;
$import->get();
if ($import->isLocked()) {
$import->edit([
'status' => 'paused',
]);
echo "> Job locked for id #{$id}\n";
$import->edit(['status' => 'paused']);
echo "> Job locked for id #$id\n";
} else {
echo "* Processing job id #{$id}\n";
echo "* Processing job id #$id\n";
$import->process();
}
$loop++;
} while (isSafeToExecute());
echo "--\n[OK] Automatic importing looped {$loop} times ~ /dashboard/bulk for stats\n";
exit(0);
echo "--\n[OK] Automatic importing looped $loop times ~ /dashboard/bulk for stats\n";
die(0);

View file

@ -35,10 +35,8 @@ $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');
@ -50,7 +48,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(
@ -61,10 +59,7 @@ 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']);
@ -74,7 +69,7 @@ foreach ($twoFactors as $twoFactor) {
$values = [
'secret' => $secret,
];
feedback("- secret: {$secret}");
feedback("- secret: $secret");
TwoFactor::update(
id: $twoFactor['id'],
values: $values,
@ -90,7 +85,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(
@ -100,18 +95,11 @@ foreach ($loginProviders as $name => $loginProvider) {
}
feedbackSeparator();
feedbackStep($doing, 'login connection tokens');
$connections = DB::get(
table: 'login_connections',
where: 'all',
sort: [
'field' => 'id',
'order' => 'desc',
]
);
$connections = DB::get(table: 'login_connections', values: '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 = [
@ -122,14 +110,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 = [
@ -139,5 +127,5 @@ foreach ($albumsPassword as $album) {
id: (int) $album['id'],
values: $values,
);
feedback("- password: {$password}");
feedback("- password: $password");
}

View file

@ -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,13 +18,6 @@ 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;
@ -37,115 +30,44 @@ use function Chevereto\Vars\env;
if (getSetting('maintenance')) {
echo "[!] Chevereto is in maintenance mode.\n";
exit(255);
die(255);
}
$jobs = [
'deleteExpiredImages',
'cleanUnconfirmedUsers',
'removeDeleteLog',
'storageDelete',
];
if ((bool) env()['CHEVERETO_ENABLE_UPDATE_CHECK']) {
$jobs = ['deleteExpiredImages', 'cleanUnconfirmedUsers', 'removeDeleteLog', 'checkForNews'];
if ((bool) env()['CHEVERETO_ENABLE_EXTERNAL_STORAGE']) {
$jobs[] = 'storageDelete';
}
if ((bool) env()['CHEVERETO_ENABLE_CHECK_UPDATES']) {
$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($time_start);
exit(0);
writeLastRan();
}
feedbackStep('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);
}
$job();
}
writeLastRan($time_start);
function writeLastRan(float $time_start): void
writeLastRan();
function writeLastRan(): void
{
$datetimegmt = datetimegmt();
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;
Settings::update(['cron_last_ran' => datetimegmt()]);
echo "--\n✅ [DONE] Cron tasks ran @ $datetimegmt\n";
}
function echoLocked(string $job): void
{
echo "* Job: {$job} [now locked]\n";
echo "* [!] Job $job is locked ~ skipping\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;
@ -193,7 +115,7 @@ function removeDeleteLog(): void
}
function checkForNews(): void
{
if (! checkoutUpdate('news_check_datetimegmt', 'PT4H')) {
if (!checkoutUpdate('news_check_datetimegmt')) {
feedbackAlert('Skipping news check');
return;
@ -211,7 +133,7 @@ function checkForNews(): void
}
function checkForUpdates(): void
{
if (! checkoutUpdate('update_check_datetimegmt', 'P1D')) {
if (!checkoutUpdate('update_check_datetimegmt')) {
feedbackAlert('Skipping updates check');
return;
@ -227,15 +149,10 @@ function checkForUpdates(): void
}
echoLocked($job);
}
function checkoutUpdate(string $datetimeSetting, string $past): bool
function checkoutUpdate(string $datetimeSetting): bool
{
$get = Variable::fetch($datetimeSetting);
return $get === null
|| datetime_add(
$get,
$past
) < datetimegmt();
return is_null(Settings::get($datetimeSetting))
|| datetime_add(Settings::get($datetimeSetting), 'P1D') < datetimegmt();
}
function checkHtaccess()
{

View file

@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\cheveretoVersionInstalled;
use function Chevereto\Legacy\getSetting;
if (cheveretoVersionInstalled() !== '') {
if (getSetting('chevereto_version_installed') !== null) {
echo "[ERROR] Chevereto is already installed, try with the update command\n";
exit(255);
die(255);
}
require_once PATH_APP_LEGACY_INSTALL . 'installer.php';

View file

@ -1,41 +0,0 @@
<?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);

View file

@ -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,9 @@ foreach ($languages as $lang) {
'cache_header' => $k == 'base',
]);
}
echo "{$lang}\n";
if (file_exists($language_override_file)) {
echo "{$lang} [override]\n";
}
echo "$lang\n";
}
echo "---\n";
echo L10n::LOCALES_AVAILABLE_FILEPATH . "\n";
echo "💯 [OK] Languages re-cached\n";
exit(0);
die(0);

View file

@ -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";
exit(255);
if (!isset($opts['u'])) {
echo "[Error] Missing username" . "\n";
die(255);
}
$password = randomString(24);
$user = User::getSingle($opts['u'], 'username');
if ($user === []) {
echo '[Error] User not found' . "\n";
exit(255);
echo "[Error] User not found" . "\n";
die(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";
exit(255);
if (!$added) {
echo "[Error] Failed to add password" . "\n";
die(255);
}
}
echo $password . "\n";
exit(0);
die(0);

View file

@ -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";
exit(255);
die(255);
}
if (! Settings::hasKey($opts['k'])) {
if (!Settings::hasKey($opts['k'])) {
echo "[ERROR] Setting key doesn't exists\n";
exit(255);
die(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";
}
exit(0);
die(0);

View file

@ -14,22 +14,24 @@ 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";
exit(255);
echo "[Error] Missing -" . implode(' -', $missing) . "\n";
die(255);
}
if (! Settings::hasKey($opts['k'])) {
if (!Settings::hasKey($opts['k'])) {
echo "[ERROR] Setting key doesn't exists\n";
exit(255);
die(255);
}
/** @var int|string|null $value */
$value = $opts['v'] ?? null;
Settings::update([
$opts['k'] => $value,
]);
$typeset = Settings::getTypeset($opts['k']);
if ($typeset === 'bool') {
$value = (int) ($value == 1 || strtolower($value) === 'true');
}
Settings::update([$opts['k'] => $value]);
require 'setting-get.php';
exit(0);
die(0);

View file

@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\cheveretoVersionInstalled;
use function Chevereto\Legacy\getSetting;
if (cheveretoVersionInstalled() === '') {
if (getSetting('chevereto_version_installed') === null) {
echo "[ERROR] Chevereto is not installed, try with the install command.\n";
exit(255);
die(255);
}
require_once PATH_APP_LEGACY_INSTALL . 'installer.php';

View file

@ -9,45 +9,44 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\getCheveretoEnv;
use function Chevereto\Legacy\loaderHandler;
if (PHP_SAPI !== 'cli') {
header('HTTP/1.0 403 Forbidden');
echo '403 Forbidden';
exit(255);
die("403 Forbidden\n");
}
$opts = getopt('C:') ?: [];
if ($opts === []) {
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);
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);
}
}
define('ACCESS', $access);
require_once __DIR__ . '/../load/php-boot.php';
require_once __DIR__ . '/../load/loader.php';
require_once loaderHandler(
$_COOKIE,
getCheveretoEnv(),
$_ENV,
$_FILES,
$_GET,
$_POST,

View file

@ -9,8 +9,6 @@
* file that was distributed with this source code.
*/
use function Chevereto\Legacy\G\sanitize_path_slashes;
use function Chevereto\Legacy\getCheveretoEnv;
use function Chevereto\Legacy\loaderHandler;
define('ACCESS', 'web');
@ -18,25 +16,17 @@ define('ACCESS', 'web');
$appDir = __DIR__ . '/../..';
$loadDir = __DIR__ . '/../load';
require_once $loadDir . '/php-boot.php';
$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);
}
$urlPath = strtok($urlPath, '?');
if (in_array($urlPath, ['/upgrading', '/upgrading/'], true)
$uri = $_SERVER['REQUEST_URI'] ?? '';
$parseUri = parse_url($uri);
if (in_array($parseUri['path'] ?? null, ['/upgrading', '/upgrading/'])
&& file_exists($appDir . '/.upgrading/upgrading.lock')) {
require $appDir . '/upgrading.php';
exit;
}
require_once $loadDir . '/loader.php';
require_once loaderHandler(
$_COOKIE,
getCheveretoEnv(),
$_ENV,
$_FILES,
$_GET,
$_POST,

File diff suppressed because it is too large Load diff

View file

@ -2,12 +2,12 @@
use function Chevereto\Legacy\G\get_base_url;
// @phpstan-ignore-next-line
if (! defined('ACCESS') || ! ACCESS) {
exit('This file cannot be directly accessed.');
if (!defined('ACCESS') || !ACCESS) {
die('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="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>
<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>
</div>

View file

@ -3,20 +3,13 @@ use function Chevereto\Legacy\G\get_base_url;
use function Chevereto\Legacy\get_chevereto_version;
// @phpstan-ignore-next-line
if (! defined('ACCESS') || ! ACCESS) {
exit('This file cannot be directly accessed.');
if (!defined('ACCESS') || !ACCESS) {
die('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.addEventListener("DOMContentLoaded", function() {
CHV.fn.system.checkUpdates();
});
</script>
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>

View file

@ -1,68 +1,50 @@
<?php
use Chevereto\Legacy\Classes\Settings;
use function Chevereto\Vars\env;
use function Chevereto\Legacy\getSetting;
// @phpstan-ignore-next-line
if (! defined('ACCESS') || ! ACCESS) {
exit('This file cannot be directly accessed.');
}
$version_patch = APP_VERSION;
$explode = explode('.', $version_patch);
$version_major = $explode[0];
$version_minor = $version_major . '.' . $explode[1];
$version_link = strtr(
'https://releases.chevereto.com/%major%.X/%minor%/%patch%.html',
[
'%major%' => $version_major,
'%minor%' => $version_minor,
'%patch%' => $version_patch,
]
);
$edition = ucfirst(env()['CHEVERETO_EDITION'] ?? '');
?>
<h1><i class="fa fa-box-open"></i> Chevereto <?php echo $edition; ?> <a class="label--version" target="_blank" href="<?php echo $version_link; ?>"><?php echo APP_VERSION; ?></a></h1>
<p>Fill this form with the details of the initial admin account you want to use. You can change this account later on.</p>
if (!defined('ACCESS') || !ACCESS) {
die('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>
<p>You can change this account later on.</p>
<?php if ($error ?? false) { ?>
<p class="highlight padding-10"><?php echo $error_message ?? ''; ?></p>
<p class="highlight padding-10"><?php echo $error_message ?? ''; ?></p>
<?php } ?>
<form method="post">
<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 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">
<label for="email">Admin email</label>
<input type="email" name="email" id="email" class="width-100p" value="<?php echo $safe_post['email'] ?? ''; ?>" placeholder="Admin email" title="Valid email address for your admin account" required>
<span class="input-warning red-warning"><?php echo $input_errors['email'] ?? ''; ?></span>
</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 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>
</div>
<form method="post">
<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>
<span class="input-warning red-warning"><?php echo $input_errors['username'] ?? ''; ?></span>
</div>
<div class="p input-label">
<label for="email">Admin email</label>
<input type="email" name="email" id="email" class="width-100p" value="<?php echo $safe_post['email'] ?? ''; ?>" placeholder="Admin email" title="Valid email address for your admin account" required>
<span class="input-warning red-warning"><?php echo $input_errors['email'] ?? ''; ?></span>
</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>
<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>
</div>
<?php
if ($is_2X ?? false) {
?>
<div>
<div class="p input-label">
<label for="crypt_salt">__CHV_CRYPT_SALT__</label>
<input type="text" name="crypt_salt" id="crypt_salt" class="width-100p" value="<?php echo $safe_post['crypt_salt'] ?? ''; ?>" placeholder="Example: changeme" title="As defined in includes/definitions.php" required>
<span class="input-below highlight">Value from define("__CHV_CRYPT_SALT__", "changeme");</span>
<span class="input-warning red-warning"><?php echo $input_errors['crypt_salt'] ?? ''; ?></span>
</div>
</div>
<div>
<div class="p input-label">
<label for="crypt_salt">__CHV_CRYPT_SALT__</label>
<input type="text" name="crypt_salt" id="crypt_salt" class="width-100p" value="<?php echo $safe_post['crypt_salt'] ?? ''; ?>" placeholder="Example: changeme" title="As defined in includes/definitions.php" required>
<span class="input-below highlight">Value from define("__CHV_CRYPT_SALT__", "changeme");</span>
<span class="input-warning red-warning"><?php echo $input_errors['crypt_salt'] ?? ''; ?></span>
</div>
</div>
<?php
}
?>
<div>
<button class="action radius" type="submit">Install</button>
</div>
</form>
?>
<div>
<button class="action radius" type="submit">Install</button>
</div>
</form>

View file

@ -1,7 +1,8 @@
<?php
// @phpstan-ignore-next-line
if (! defined('ACCESS') || ! ACCESS) {
exit('This file cannot be directly accessed.');
// @phpstan-ignore-next-line
if (!defined('ACCESS') || !ACCESS) {
die('This file cannot be directly accessed.');
} ?>
<h1>Update failed</h1>
<p>The update process failed. Here is the error returned:</p>

View file

@ -4,20 +4,13 @@ use function Chevereto\Legacy\G\get_base_url;
use function Chevereto\Legacy\get_chevereto_version;
// @phpstan-ignore-next-line
if (! defined('ACCESS') || ! ACCESS) {
exit('This file cannot be directly accessed.');
if (!defined('ACCESS') || !ACCESS) {
die('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.addEventListener("DOMContentLoaded", function() {
CHV.fn.system.checkUpdates();
});
</script>
<script>$(document).ready(function() { CHV.fn.system.checkUpdates(); });</script>

View file

@ -9,5 +9,5 @@
* file that was distributed with this source code.
*/
const APP_VERSION = '4.2.4';
const APP_VERSION_AKA = 'regio';
const APP_VERSION = '4.1.1';
const APP_VERSION_AKA = 'pulento';

View file

@ -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,21 +51,15 @@ 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>'
. absolute_to_relative($v)
. "</code> doesn't exists and can't be created.";
} catch (Throwable $e) {
$errors[] = "<code>" . absolute_to_relative($v) . "</code> doesn't exists. Make sure to upload it.";
}
} 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.';
}
}
}
@ -77,17 +71,12 @@ 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 = [
@ -95,13 +84,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',
@ -128,7 +117,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'),
@ -145,7 +134,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);
}
}
@ -153,11 +142,7 @@ 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))]);
}
}
}

View file

@ -9,50 +9,48 @@
* 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;
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')
)
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', 'w')
)
)
->withError(
new StreamWriter(
streamFor('php://stderr', 'a')
)
);
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);
}
echo 'An error occurred while loading Chevereto.' . PHP_EOL;
exit(255);
)
);
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);
}
throw new RuntimeException(
message($message)
);
}

View file

@ -9,18 +9,12 @@
* file that was distributed with this source code.
*/
define('CHEVERETO_PHP_VERSION_REQUIRED', '8.1.28');
if (version_compare(PHP_VERSION, CHEVERETO_PHP_VERSION_REQUIRED, '<')) {
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
if (PHP_SAPI !== 'cli') {
http_response_code(503);
}
echo 'This server is running PHP '
. PHP_VERSION
. ' and Chevereto needs at least PHP '
. CHEVERETO_PHP_VERSION_REQUIRED
. PHP_EOL;
exit(255);
echo 'This server is currently running PHP ' . PHP_VERSION . ' and Chevereto needs at least PHP 8.0.0 to run.' . PHP_EOL;
die(255);
}
require_once __DIR__ . '/loader.php';

View file

@ -12,162 +12,48 @@
use Chevere\ThrowableHandler\Documents\ConsoleDocument;
use Chevere\ThrowableHandler\Documents\HtmlDocument;
use Chevere\ThrowableHandler\Documents\PlainDocument;
use Chevere\ThrowableHandler\ThrowableHandler;
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 Chevere\ThrowableHandler\ThrowableHandler;
use function Chevere\Writer\writers;
use function Chevere\xrDebug\PHP\throwableHandler as XrDebugThrowableHandler;
use function Chevere\Xr\throwableHandler as XrThrowableHandler;
use Chevereto\Config\Config;
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;
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
set_error_handler(ThrowableHandler::ERROR_AS_EXCEPTION);
register_shutdown_function(ThrowableHandler::SHUTDOWN_ERROR_AS_EXCEPTION);
set_exception_handler(function (Throwable $throwable) {
$extra = '';
$publicHandler = throwableHandler($throwable);
$namespace = env()['CHEVERETO_ID_HANDLE']
?? false;
if ($namespace) {
$publicHandler = $publicHandler
->withId($namespace . $publicHandler->id());
}
$throwableHandler = throwableHandler($throwable);
if (PHP_SAPI === 'cli') {
$docInternal = new ConsoleDocument($publicHandler);
$parameters = [];
$docInternal = new ConsoleDocument($throwableHandler);
} else {
if (! headers_sent()) {
$docInternal = new PlainDocument($throwableHandler);
if (!headers_sent()) {
http_response_code(500);
}
$isDebug = isDebug();
try {
$debugLevel = Config::system()->debugLevel();
} catch (Throwable) {
$envDebugLevel = getenv('CHEVERETO_DEBUG_LEVEL');
$debugLevel = $envDebugLevel === false
? 1
: (int) $envDebugLevel;
}
$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);
$debugLevel = (int) ($_ENV['CHEVERETO_DEBUG_LEVEL'] ?? 1);
}
$docPublic = new HtmlDocument(
$doDebug ? $internalHandler : $publicHandler
$throwableHandler->withIsDebug(
in_array($debugLevel, [2, 3]) || $isDebug
)
);
writers()->output()
->write($docPublic->__toString() . "\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";
writers()->error()
->write($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);
exit(255);
XrThrowableHandler(
$throwable,
<<<HTML
<div class="throwable-message">Incident ID: {$throwableHandler->id()}</div>
HTML
);
die(255);
});
function xrDebugExtraSection(string $title, string $contents)
{
return <<<HTML
<div class="throwable-message">
<b>{$title}</b>
<div>{$contents}</div>
</div>
HTML;
}

View file

@ -10,8 +10,10 @@
*/
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;
@ -19,26 +21,20 @@ 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 function Chevereto\Legacy\G\get_public_url;
use Chevereto\Legacy\G\Handler;
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;
@ -47,65 +43,30 @@ use function Chevereto\Vars\server;
use function Chevereto\Vars\session;
use function Chevereto\Vars\sessionVar;
if (cheveretoVersionInstalled() === '') {
if (Settings::get('chevereto_version_installed') === null) {
new Handler(
loadTemplate: ! REPL, // @phpstan-ignore-line
loadTemplate: !REPL, // @phpstan-ignore-line
before: function ($handler) {
headersNoCache();
if ($handler->request_array()[0] !== 'install') {
redirect('install', 302);
redirect('install');
}
},
);
}
$bannedIp = IpBan::getSingle();
if ($bannedIp !== []) {
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);
}
is_url($bannedIp['message'])
? redirect($bannedIp['message'])
: (
die(empty($bannedIp['message'])
? _s('You have been forbidden to use this website.')
: $bannedIp['message']
)
);
}
$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);
@ -120,14 +81,13 @@ $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'], true)
&& !in_array($handler->getRoutePath(), ['account/two-factor', 'captcha-verify', 'logout'])
&& $handler->request_array()[0] !== 'page'
) {
headersNoCache();
redirect('account/two-factor', 302);
) {
redirect('account/two-factor');
}
}
if (! getSetting('language_chooser_enable')) {
if (!getSetting('language_chooser_enable')) {
$user_lang = getSetting('default_language');
}
new L10n(
@ -136,31 +96,25 @@ $hook_before = function (Handler $handler) {
? false
: getSetting('auto_language')
);
if (http_response_code() === 403) {
headersNoCache();
exit();
if (http_response_code() == 403) {
die();
}
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 (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']]);
}
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);
headersNoCache();
redirect(get_current_url(true, ['agree-consent']), 302);
redirect(get_current_url(true, ['agree-consent']));
}
$base = $handler::baseRequest();
parse_str(server()['QUERY_STRING'] ?? '', $querystr);
@ -174,11 +128,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']], true)) {
if (!in_array('pro', editionCombo()[env()['CHEVERETO_EDITION']])) {
if ((bool) env()['CHEVERETO_ENABLE_EXPOSE_PAID_FEATURES']) {
$moderateLink = 'https://chevereto.com/pricing';
$moderateLabel .= ' ' . badgePaid('pro');
@ -192,18 +146,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();
@ -212,7 +166,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'], true)) {
if (in_array($handler->request_array()[0], ['login', 'signup', 'account'])) {
$paletteId = 0;
} else {
$paletteId = Login::isLoggedUser()
@ -226,21 +180,14 @@ $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') {
headersNoCache();
redirect('login', 302);
if ($handler::cond('maintenance') && $handler->request_array()[0] == 'dashboard') {
redirect('login');
}
$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);
@ -248,7 +195,7 @@ $hook_before = function (Handler $handler) {
$langLinks[$k] = [
'hreflang' => $hreflang,
'name' => $v['name'],
'url' => get_public_url($langUrl),
'url' => $langUrl,
];
}
$handler::setVar('langLinks', $langLinks);
@ -263,46 +210,42 @@ $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') {
$userMapPaths = ['search'];
$userMapPaths[] = getSetting('user_profile_view') === 'files'
? 'albums'
: 'files';
if ($handler->request_array()[0] === '/'
&& getSetting('website_mode_personal_routing') === '/'
&& in_array(key($querystr), ['random'], true)
if (getSetting('website_mode') == 'personal') {
if ($handler->request_array()[0] == '/'
&& getSetting('website_mode_personal_routing') == '/'
&& in_array(key($querystr), ['random'])
) {
$handler->mapRoute('index');
} elseif ($handler->request_array()[0] === 'search'
&& in_array($handler->request_array()[1] ?? [], ['images', 'albums', 'users'], true)
} elseif ($handler->request_array()[0] == 'search'
&& in_array($handler->request_array()[1] ?? [], ['images', 'albums', 'users'])
) {
$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, true))
} elseif ($handler->request_array()[0] == getSetting('website_mode_personal_routing')
|| (getSetting('website_mode_personal_routing') == '/'
&& in_array($handler->request_array()[0], ['albums', 'search']))
) {
$handler->mapRoute('user', [
'id' => getSetting('website_mode_personal_uid'),
]);
}
if ($handler->request_array()[0] === '/'
&& ! in_array(key($querystr), ['random', 'lang'], true)
&& ! $handler::cond('mapped_route')
if ($handler->request_array()[0] == '/'
&& !in_array(key($querystr), ['random', 'lang'])
&& !$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') {
@ -315,13 +258,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);
}
}
$virtual_routes = ['image', 'album', 'user', 'video', 'audio'];
if (in_array($handler->request_array()[0], $virtual_routes, true)) {
$virtualizable_routes = ['image', 'album', 'user'];
if (in_array($handler->request_array()[0], $virtualizable_routes)) {
$virtual_route = getSetting('route_' . $handler->request_array()[0]);
if ($handler->request_array()[0] !== $virtual_route) {
$virtualized_url = str_replace(
@ -329,21 +272,21 @@ $hook_before = function (Handler $handler) {
get_base_url($virtual_route),
get_current_url()
);
redirect($virtualized_url, 301);
redirect($virtualized_url);
return;
}
}
if ($base !== 'index' && ! is_route_available($handler->request_array()[0])) {
foreach ($virtual_routes as $k) {
if ($handler->request_array()[0] === getSetting('route_' . $k)) {
if ($base !== 'index' && !is_route_available($handler->request_array()[0])) {
foreach ($virtualizable_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 ($virtual_routes as $v) {
foreach ($virtualizable_routes as $v) {
$v = getSetting('route_' . $v);
if (isset($v)) {
$allowed_requests[] = $v;
@ -352,28 +295,13 @@ $hook_before = function (Handler $handler) {
if (getSetting('enable_signups')) {
$allowed_requests[] = 'signup';
}
if (! in_array($handler->request_array()[0], $allowed_requests, true)) {
headersNoCache();
redirect('login', 302);
if (!in_array($handler->request_array()[0], $allowed_requests)) {
redirect('login');
}
}
$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('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(
'search_enabled',
$handler::cond('content_manager')
@ -384,60 +312,47 @@ $hook_before = function (Handler $handler) {
);
$handler::setCond(
'random_enabled',
getSetting('website_random')
&& (Login::isLoggedUser() ?: getSetting('website_random_guest'))
$handler::cond('content_manager')
?: (
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 = [];
$tags_top = [];
if ($handler::cond('explore_enabled') || $base === 'dashboard') {
if ($handler::cond('explore_enabled') || $base == 'dashboard') {
try {
$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]);
$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]);
}
}
} 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) {
} catch (Throwable $e) {
}
}
if ($handler::cond('explore_enabled')
&& $categories === []
&& !(bool) env()['CHEVERETO_ENABLE_USERS']
) {
$handler::setCond('explore_enabled', false);
}
$handler::setVar('categories', $categories);
$handler::setVar('tags_top', $tags_top);
$explore_discovery = [
$explore_semantics = [
'recent' => [
'label' => _s('Recent'),
'icon' => 'fas fa-history',
@ -450,188 +365,127 @@ $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' => _n('Video', 'Videos', 20),
'label' => _s('Videos'),
'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 (Login::isLoggedUser() && getSetting('enable_followers')) {
$explore_discovery['following'] = [
'label' => _s('Following'),
'icon' => 'fas fa-rss',
'url' => get_base_url('following'),
];
if (!(bool) env()['CHEVERETO_ENABLE_USERS']) {
$explore_semantics = [];
}
if (! getSetting('enable_likes')) {
unset($explore_discovery['popular']);
if (!getSetting('enable_likes')) {
unset($explore_semantics['popular']);
}
foreach ($explore_discovery as $k => &$v) {
$v['url'] = get_base_url('explore/' . $k);
if (!in_array('gif', Image::getEnabledImageExtensions())) {
unset($explore_semantics['animated']);
}
foreach ($explore_content as $k => &$v) {
foreach ($explore_semantics as $k => &$v) {
$v['url'] = get_base_url('explore/' . $k);
}
unset($v);
$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',
]
);
$pos_page_tos = array_search('tos', array_column($pages_visible_db, 'internal'));
$pos_page_privacy = array_search('privacy', array_column($pages_visible_db, 'internal'));
$page_tos = $pos_page_tos === false
? null
: $pages_visible_db[$pos_page_tos];
$page_privacy = $pos_page_privacy === false
? null
: $pages_visible_db[$pos_page_privacy];
$handler::setVar('page_tos', $page_tos);
$handler::setVar('page_privacy', $page_privacy);
$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));
}
$pages_visible = [];
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 ((! (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')) {
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'], true)
) {
if ($upload_allowed && in_array($handler->request_array()[0], ['login', 'signup', 'account'])) {
$upload_allowed = false;
}
$handler::setCond('upload_enabled', $upload_enabled); // System allows to upload?
$handler::setCond('upload_allowed', $upload_allowed); // Current user can upload?
$handler::setCond('upload_allowed', $upload_allowed); // Target peer can upload?
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, true)) {
if (!in_array($handler->request_array()[0], $allowed_requests)) {
$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() : []);
$excludeLastUrl = [
'login',
'signup',
'account',
'connect',
'logout',
'json',
'api',
'captcha-verify',
'webmanifest',
'tag-autocomplete',
];
if (! in_array($handler->request_array()[0], $excludeLastUrl, true)) {
if (!in_array($handler->request_array()[0], ['login', 'signup', 'account', 'connect', 'logout', 'json', 'api', 'captcha-verify'])) {
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>'
]));
$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;
}
$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;
}
$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'], true)
) {
if (array_key_exists('deleted', get()) && in_array($handler->template(), ['user', 'album'])) {
set_status_header(303);
}
if ($handler->template() === '404') {
if ($handler->template() == '404') {
if (sessionVar()->hasKey('last_url')) {
sessionVar()->remove('last_url');
}
@ -644,19 +498,14 @@ $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', getSetting('website_name', true));
$handler::setVar('safe_html_website_name', safe_html(getSetting('website_name')));
$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')));
}
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')));
}
$handler::setVar('safe_html_meta_description', safe_html($handler::var('meta_description')));
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, );

View file

@ -10,6 +10,8 @@
*/
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;
@ -17,14 +19,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\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,82 +43,73 @@ 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'], true)
&& $handler->isRequestLevel(3)
) {
if (!$doing || !in_array($doing, ['activate', 'password-reset', 'change-email-confirm', 'two-factor']) && $handler->isRequestLevel(3)) {
$handler->issueError(404);
return;
}
if (! Settings::get('enable_signups')
&& in_array($doing, ['awaiting-confirmation', 'activate', 'email-changed'], true)
) {
if (!Settings::get('enable_signups') && in_array($doing, ['awaiting-confirmation', 'activate', 'email-changed'])) {
$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', 302);
if (Login::isLoggedUser() && $doing !== 'email-needed' && $loggedStatus == 'awaiting-email') {
redirect('account/email-needed');
}
switch ($doing) {
case 'email-needed':
if (Login::isLoggedUser()) {
if ($loggedStatus !== 'awaiting-email') {
redirect($logged_user['url'], 302);
}
} else {
redirect('login', 302);
if (Login::isLoggedUser() && $loggedStatus !== 'awaiting-email') {
redirect($logged_user['url']);
}
break;
case 'resend-activation':
case 'activate':
if (Login::isLoggedUser() && $loggedStatus !== 'awaiting-confirmation') {
redirect($logged_user['url'] ?? '', 302);
redirect($logged_user['url'] ?? '');
}
break;
case 'two-factor':
if (! Login::isLoggedUser()) {
redirect('login', 302);
if (!Login::isLoggedUser()) {
redirect('');
}
if (! TwoFactor::hasFor($logged_user['id'])) {
redirect('settings/security', 302);
if (!TwoFactor::hasFor($logged_user['id'])) {
redirect('settings/security');
}
if (! sessionVar()->hasKey('challenge_two_factor')) {
redirect($logged_user['url'] ?? '', 302);
if (!sessionVar()->hasKey('challenge_two_factor')) {
redirect($logged_user['url'] ?? '');
}
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, true)) {
if (in_array($doing, $keysToCheck)) {
$request_log = RequestLog::getCounts($request_db_field, 'fail');
$captcha_needed = (getSetting('captcha') ?? false)
? must_use_captcha($request_log['day'])
@ -128,9 +119,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');
}
@ -139,32 +130,33 @@ 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;
@ -186,11 +178,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;
@ -199,24 +191,15 @@ 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) {
@ -227,14 +210,11 @@ 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,
@ -242,40 +222,35 @@ 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',
getSetting('website_name')
);
if ($doing == 'password-forgot') {
$mail['subject'] = _s('Reset your password at %s', getSettings()['website_name']);
} else {
$mail['subject'] = _s(
'Confirmation required at %s',
getSetting('website_name')
);
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
}
$mail['message'] = get_email_body_str('mails/account-' . ($doing === 'password-forgot' ? 'password-reset' : 'confirm'));
$mail['message'] = get_email_body_str('mails/account-' . ($doing == 'password-forgot' ? 'password-reset' : 'confirm'));
xr($mail);
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', 302);
redirect('account/awaiting-confirmation');
}
$handler::setVar('password_forgot_email', $user['email']);
} else {
@ -287,14 +262,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');
}
}
@ -302,12 +277,14 @@ 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;
@ -333,7 +310,7 @@ return function (Handler $handler) {
RequestLog::insert([
'type' => $request_db_field,
'result' => 'fail',
'user_id' => null,
'user_id' => null
]);
$handler->issueError(403);
@ -341,10 +318,7 @@ return function (Handler $handler) {
}
$user_id = decodeID($get_token_array[0]);
$get_token = hashed_token_info(get()['token']);
$confirmation_db = Confirmation::get([
'user_id' => $get_token['id'],
'type' => $request_db_field,
]);
$confirmation_db = Confirmation::get(['type' => $request_db_field, 'user_id' => $get_token['id']]);
if ($confirmation_db === false) {
$handler->issueError(403);
@ -352,16 +326,14 @@ 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);
@ -369,49 +341,39 @@ 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', getSetting('website_name'));
$mail['subject'] = _s('Welcome to %s', getSettings()['website_name']);
$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();
$redirectTo = $logged_user !== []
? User::getUrl($logged_user)
: '';
redirect($redirectTo, 302);
redirect($logged_user !== [] ? User::getUrl($logged_user) : null);
break;
case 'password-reset':
if ($POST !== []) {
if (! preg_match('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['new-password'] ?? '')) {
if (!preg_match('/' . getSetting('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);
}
@ -423,70 +385,50 @@ return function (Handler $handler) {
break;
case 'change-email-confirm':
$email_candidate = $confirmation_db['confirmation_extra'];
$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'],
]);
$email_db = DB::get('users', ['email' => $email_candidate]);
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', 302);
redirect('account/email-changed');
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'], 302);
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']);
}
$hashed_token = generate_hashed_token((int) $logged_user['id']);
$array_values = [
@ -503,7 +445,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']);
$mail['message'] = get_email_body_str('mails/account-confirm');
if (send_mail($POST['email'], $mail['subject'], $mail['message'])) {
$is_process_done = true;
@ -512,13 +454,13 @@ return function (Handler $handler) {
'status' => 'awaiting-confirmation',
'email' => $POST['email'],
]);
redirect('account/awaiting-confirmation', 302);
redirect('account/awaiting-confirmation');
} else {
RequestLog::insert(
[
'result' => 'fail',
'type' => $request_db_field,
'user_id' => $user['id'] ?? null,
'user_id' => $user['id'] ?? null
]
);
if ((getSetting('captcha') ?? false)
@ -534,7 +476,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;
@ -544,20 +486,20 @@ return function (Handler $handler) {
break;
case 'two-factor':
$handler->setTemplate($route . '/' . 'two-factor');
if (null !== ($POST['user-two-factor'] ?? null) && ! $is_error) {
if (!is_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'], 302);
redirect($logged_user['url']);
} 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)

View file

@ -9,18 +9,14 @@
* 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 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 Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\redirect;
use function Chevereto\Legacy\G\safe_html;
use function Chevereto\Legacy\G\starts_with;
@ -28,11 +24,10 @@ 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\virtualRouteHandleRedirect;
use function Chevereto\Legacy\redirectIfRouting;
use function Chevereto\Vars\env;
use function Chevereto\Vars\get;
use function Chevereto\Vars\post;
@ -42,7 +37,7 @@ use function Chevereto\Vars\session;
use function Chevereto\Vars\sessionVar;
return function (Handler $handler) {
virtualRouteHandleRedirect('album', $handler->requestArray()[0]);
redirectIfRouting('album', $handler->requestArray()[0]);
$albumIndex = getSetting('root_route') === 'album'
? 0
: 1;
@ -65,21 +60,19 @@ 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 === []) {
@ -87,23 +80,26 @@ 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_public_url(get_current_url()))) {
if (!starts_with($album['url'], get_current_url())) {
if (server()['QUERY_STRING'] ?? false) {
$redirect = rtrim($album['url'], '/') . '/?' . server()['QUERY_STRING'];
} else {
$redirect = $album['url'];
}
redirect($redirect, 302);
redirect($redirect);
}
$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;
@ -113,14 +109,11 @@ 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'
) {
headersNoCache();
redirect('login', 302);
if (!Login::getUser() && $album['privacy'] != 'private_but_link') {
redirect('login');
}
}
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');
@ -132,22 +125,21 @@ 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');
}
@ -164,77 +156,28 @@ return function (Handler $handler) {
$handler::setVar('pre_doctitle', _s('Password required'));
return;
}
$redirect_password = session()['redirect_password_to'] ?? null;
if (isset($redirect_password)) {
sessionVar()->remove('redirect_password_to', null);
headersNoCache();
redirect($redirect_password, 302);
} else {
$redirect_password = session()['redirect_password_to'] ?? null;
if (isset($redirect_password)) {
sessionVar()->remove('redirect_password_to');
redirect($redirect_password);
}
}
}
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';
@ -257,13 +200,11 @@ 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->setTagsIds(...$tags_id);
$listing->setTagsString($tag_string_no_spaces);
$listing->setOwner((int) $album["user"]["id"]);
$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);
@ -274,17 +215,8 @@ 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,
],
'tag' => rawurldecode($tag_string_no_spaces),
'params_hidden' => ['list' => 'images', 'from' => 'album', 'albumid' => $album['id_encoded']],
'tools_available' => $album['user']['id'] ? [] : ['album' => false]
]);
if (isShowEmbedContent()) {
$tabs[] = [
@ -296,28 +228,18 @@ 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 = array_merge($array, [
'icon' => 'fas fa-folder-tree',
'label' => _s('Sub %s', _s('albums')),
'id' => 'tab-sub',
'url' => $album['url'] . '/sub',
]);
$array['label'] = _s('Sub %s', _s('albums'));
$array['id'] = 'tab-sub';
$array['url'] = $album['url'] . '/sub';
$tabs[] = $array;
break;
@ -330,10 +252,9 @@ 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])) {
@ -341,12 +262,11 @@ 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([
@ -355,68 +275,27 @@ 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', $meta_description);
$handler::setVar('meta_description', htmlspecialchars($meta_description));
if ($handler::cond('content_manager') || $is_owner) {
$handler::setVar('user_items_editor', [
'user_albums' => User::getAlbums((int) $album['user']['id']),
'type' => $type,
"user_albums" => User::getAlbums((int) $album["user"]["id"]),
"type" => "images"
]);
}
$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']);
$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);
$addValue = session()['album_view_stock'];
$addValue[] = $id;
sessionVar()->put('album_view_stock', $addValue);
};

View file

@ -1,21 +0,0 @@
<?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'));
};

View file

@ -23,21 +23,17 @@ 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\mime_to_extension;
use function Chevereto\Legacy\G\json_output;
use function Chevereto\Legacy\G\random_string;
use function Chevereto\Legacy\getSetting;
use function Chevereto\Legacy\getVariable;
use function Chevereto\Vars\env;
use function Chevereto\Vars\files;
use function Chevereto\Vars\request;
@ -50,126 +46,106 @@ return function (Handler $handler) {
$FILES = files();
$SERVER = server();
$format = $REQUEST['format'] ?? 'json';
$version = strval($handler->request()[0] ?? '');
$action = strval($handler->request()[1] ?? '');
$key = strval($SERVER['HTTP_X_API_KEY'] ?? $REQUEST['key'] ?? '');
$version = $handler->request()[0] ?? null;
$action = $handler->request()[1] ?? null;
$key = $SERVER['HTTP_X_API_KEY'] ?? $REQUEST['key'] ?? null;
foreach (['version', 'action', 'key'] as $var) {
if (${$var} === '') {
throw new Exception("No {$var} provided", 100);
if ($$var === null) {
throw new Exception("No $var provided", 100);
}
}
if (! in_array($version, ['1'], true)) {
if (!in_array($version, ['1'])) {
throw new Exception('Invalid API version.', 110);
}
$verify = ApiKey::verify($key);
if ($verify === []) {
if (! (bool) env()['CHEVERETO_ENABLE_API_GUEST']) {
throw new Exception('Invalid API key.', 100);
if (!(bool) env()['CHEVERETO_ENABLE_API_GUEST']) {
throw new Exception("Guest API is disabled.", 400);
}
$apiV1Key = (string) (getSetting('api_v1_key') ?? '');
if ($apiV1Key === '') {
throw new Exception("API V1 public key can't be null. Go to /dashboard and set the Guest API key.", 0);
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 (! hash_equals($apiV1Key, $key)) {
throw new Exception('Invalid API key.', 100);
// @var string $key
if (!hash_equals($apiV1Key, $key)) {
throw new Exception("Invalid guest API key.", 100);
}
} else {
$user = User::getSingle($verify['user_id']);
}
$isAdmin = boolval(($user['is_admin'] ?? false));
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'
if (!getSetting('guest_uploads')
|| getSetting('website_privacy_mode') == 'private'
|| $handler::cond('maintenance')
) {
$upload_allowed = false;
}
} elseif (! $isAdmin
&& getSetting('website_mode') === 'personal'
&& getSetting('website_mode_personal_uid') !== ($user['id'] ?? 0)
} elseif (!$user['is_admin']
&& getSetting('website_mode') == 'personal'
&& getSetting('website_mode_personal_uid') !== $user['id']
) {
$upload_allowed = false;
}
if ((! (bool) env()['CHEVERETO_ENABLE_LOCAL_STORAGE'])
&& getVariable('storages_active')->nullInt() === 0
) {
$upload_enabled = false;
$upload_allowed = false;
}
if ($user === []
&& $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'));
}
$handler::setCond('upload_enabled', $upload_enabled);
$handler::setCond('upload_allowed', $upload_allowed);
if (Settings::get('enable_uploads_url') && ! $isAdmin) {
Settings::setValue('enable_uploads_url', 0);
}
if (! $handler::cond('upload_allowed')) {
if (!$upload_allowed) {
throw new Exception(_s('Request denied'), 401);
}
$version_to_actions = [
'1' => ['upload'],
];
if (! in_array($action, $version_to_actions[$version], true)) {
throw new Exception('Invalid API action', 120);
'1' => ['upload']
];
if (!in_array($action, $version_to_actions[$version])) {
throw new Exception('Invalid API action.', 120);
}
$source = $FILES['source']
?? $REQUEST['source']
?? $REQUEST['image']
?? null;
if ($source === null) {
throw new Exception('Empty upload source', 130);
if (is_null($source)) {
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, true));
if (! hash_equals($base64source, $source)) {
throw new Exception('Invalid base64 string', 120);
$base64source = base64_encode(base64_decode($source));
if (!hash_equals($base64source, $source)) {
throw new Exception('Invalid base64 string.', 120);
}
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);
$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);
}
$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) . '.' . mime_to_extension($mimetype),
'type' => $mimetype,
'name' => random_string(12) . '.jpg',
'type' => 'image/jpeg',
'tmp_name' => $api_temp_file,
'error' => 'UPLOAD_ERR_OK',
'size' => filesize($api_temp_file),
'size' => '1'
];
break;
break;
}
$isImgBBSpec = array_key_exists('image', $REQUEST);
$albumId = $REQUEST['album_id'] ?? null;
@ -177,8 +153,8 @@ return function (Handler $handler) {
$albumId = decodeID($albumId);
}
$expiration = $REQUEST['expiration'] ?? null;
if ($expiration !== null && ctype_digit($expiration)) {
$expiration = (int) $expiration;
if (!is_null($expiration) && ctype_digit($expiration)) {
$expiration = Image::getExpirationFromSeconds($expiration);
}
$params = [
'album_id' => $albumId,
@ -186,38 +162,25 @@ 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,
'use_file_date' => $isAdmin
? ($REQUEST['use_file_date'] ?? false)
: false,
'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,
'user_email' => $user['email'] ?? null,
];
Akismet::checkImage(
title: $params['title'] ?? null,
description: $params['description'] ?? null,
tags: $params['tags'] ?? null,
source_db: $user_source_db
);
Akismet::checkImage($params['title'] ?? null, $params['description'] ?? null, $user_source_db);
}
$uploadToWebsite = Image::uploadToWebsite($source, $user, $params);
$uploaded_id = intval($uploadToWebsite[0]);
$image = Image::formatArray(Image::getSingle($uploaded_id), true);
$image['delete_url'] = Image::getDeleteUrl(
type: $image['type'],
idEncoded: encodeID($uploaded_id),
password: $uploadToWebsite[1]
);
$image['delete_url'] = Image::getDeleteUrl(encodeID($uploaded_id), $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 = [];
@ -226,51 +189,49 @@ 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_document_output($json_array);
json_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 {
exit($json_array['status_code']);
die($json_array['status_code']);
}
break;
break;
}
exit();
die();
} else {
json_output($json_array);
}
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_document_output($json_array);
json_output($json_array);
break;
case 'txt':
case 'redirect':
exit($json_array['error']['message']);
die($json_array['error']['message']);
}
} else {
json_document_output($json_array);
json_output($json_array);
}
}
};

View file

@ -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('', 302);
redirect();
}
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);
exit($fetch);
} catch (Exception) {
sessionVar()->put('isBot', !$isSuccess);
die($fetch);
} catch (Exception $e) {
}
exit();
die();
};

View file

@ -11,18 +11,14 @@
use Chevereto\Legacy\Classes\Listing;
use Chevereto\Legacy\Classes\Login;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\get_route_name;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\redirect;
use function Chevereto\Legacy\get_share_links;
use function Chevereto\Vars\request;
return function (Handler $handler) {
if (! $handler::cond('explore_enabled')) {
$handler->issueError(404);
return;
}
if ($handler->isRequestLevel(3)) {
if (!$handler::cond('explore_enabled')) {
$handler->issueError(404);
return;
@ -30,33 +26,29 @@ return function (Handler $handler) {
$category = null;
$categories = $handler::var('categories');
$category_url_key = $handler->request()[0] ?? false;
if (! $category_url_key) {
$handler->issueError(404);
return;
if (!$category_url_key) {
redirect('explore');
}
$category_url_key = urldecode($category_url_key);
foreach ($categories as $v) {
if ($v['url_key'] == $category_url_key) {
$category = $v;
if ($category_url_key) {
foreach ($categories as $v) {
if ($v['url_key'] == $category_url_key) {
$category = $v;
break;
break;
}
}
}
if (! $category) {
$handler->issueError(404);
if (!$category) {
$handler->issueError(404);
return;
return;
}
$handler::setVar('pre_doctitle', $category['name']);
}
$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();
@ -75,9 +67,10 @@ return function (Handler $handler) {
$listing->setRequester(Login::getUser());
$listing->exec();
$meta_description = $category['description'] ?? '';
$handler::setVar('meta_description', $meta_description);
$handler::setVar('meta_description', htmlspecialchars($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());
};

View file

@ -9,29 +9,28 @@
* 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 Chevereto\Legacy\G\Handler;
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 Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\redirect;
use function Chevereto\Legacy\getSetting;
use Hybridauth\Exception\InvalidAuthorizationStateException;
use Hybridauth\Hybridauth;
return function (Handler $handler) {
if (! version_compare(cheveretoVersionInstalled(), '4.0.0-beta.11', '>=')) {
if (!version_compare(Settings::get('chevereto_version_installed') ?? '', '4.0.0-beta.11', '>=')) {
echo 'Route not available until the system update gets installed.';
exit();
die();
}
$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;
@ -44,7 +43,7 @@ return function (Handler $handler) {
if ($validate['valid']
&& in_array($validate['id'], Login::getSession()['login_cookies'] ?? [])
) {
redirect('settings/connections#' . $doing, 302);
redirect('settings/connections#' . $doing);
return;
}
@ -59,7 +58,7 @@ return function (Handler $handler) {
'keys' => [
'id' => $provider['key_id'],
'secret' => $provider['key_secret'],
],
]
];
}
$session = new HybridauthSession();
@ -67,12 +66,13 @@ 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, 302);
redirect('connect/' . $doing);
}
if ($adapter->isConnected()) {
$user = $logged_user;
@ -87,11 +87,11 @@ return function (Handler $handler) {
}
if ($connectedUserId != ($user['id'] ?? 0)) {
Login::logout();
redirect('connect/' . $doing, 302);
redirect('connect/' . $doing);
}
}
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) Settings::USERNAME_MAX_LENGTH);
$baseUsername = substr(strtolower($username), 0, (int) getSetting('username_max_length'));
$username = $baseUsername;
$j = 1;
while (! User::isValidUsername($username)) {
if (strlen($username) > Settings::USERNAME_MAX_LENGTH) {
while (!User::isValidUsername($username)) {
if (strlen($username) > getSetting('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) > Settings::USERNAME_MAX_LENGTH) {
if (strlen($username) > getSetting('username_max_length')) {
$username = substr($baseUsername, 0, -strlen(strval($i))) . $i;
} else {
$username .= $i;
@ -132,6 +132,9 @@ 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);
}
@ -166,10 +169,10 @@ return function (Handler $handler) {
? $user['url']
: 'settings/connections#' . $doing
);
redirect($redirectTo, 302);
redirect($redirectTo);
}
redirect('', 302);
redirect('');
exit();
die();
};

File diff suppressed because it is too large Load diff

View file

@ -12,41 +12,30 @@
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)
&& getSetting('homepage_style') == 'route_explore'
&& str_contains(get_current_url(), $baseUrlRouteName)
) {
$redirect = str_replace_first(
$baseUrlRouteName,
get_base_url(),
get_current_url()
);
headersNoCache();
redirect($redirect, 302);
if (!isset($doing) && getSetting('homepage_style') == 'route_explore' && strpos(get_current_url(), get_base_url(get_route_name())) !== false) {
$redir = str_replace_first(get_base_url(get_route_name()), get_base_url(), get_current_url());
redirect($redir);
}
$explore_discovery = $handler::var('explore_discovery') + $handler::var('explore_content');
if (isset($doing) && ! array_key_exists($doing, $explore_discovery)) {
$explore_semantics = $handler::var('explore_semantics');
if (isset($doing) && !array_key_exists($doing, $explore_semantics)) {
$handler->issueError(404);
return;
@ -62,58 +51,30 @@ return function (Handler $handler) {
if ($doing) {
$basename .= ($basename ? '/' : '') . $doing;
}
$list = isset($doing) ? $explore_discovery[$doing] : [
'label' => _s('Explore'),
'icon' => 'fas fa-compass',
];
$list['list'] = $doing === null
? get_route_name()
: $doing;
$doing ??= 'images';
$list = isset($doing) ? $explore_semantics[$doing] : ['label' => _s('Explore'), 'icon' => 'fas fa-images'];
$list['list'] = is_null($doing) ? get_route_name() : $doing;
$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'] = array_merge($listingParams['params_hidden'], [
'is_animated' => 1,
'is_image' => 1,
'is_video' => 0,
]);
$listingParams['params_hidden']['is_animated'] = 1;
}
if ($doing == 'videos') {
$listingParams['params_hidden'] = array_merge($listingParams['params_hidden'], [
'is_image' => 0,
'is_video' => 1,
]);
$listingParams['params_hidden']['is_video'] = 1;
}
if ($doing == 'images' && $basename !== '') {
$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
);
$getParams = Listing::getParams(request());
$tabs = Listing::getTabs($listingParams, $getParams, true);
$currentKey = $tabs['currentKey'];
$type = $tabs['tabs'][$currentKey]['type'];
$tabs = $tabs['tabs'];
parse_str($tabs[$currentKey]['params'], $tab_params);
$fix_sort = explode('_', $tab_params['sort']);
if (count($fix_sort) == 2) {
$getParams['sort'] = $fix_sort;
}
parse_str($tabs[$currentKey]['params'], $tabs_params);
$getParams['sort'] = explode('_', $tabs_params['sort']); // Hack this stuff
$handler::setVar('list_params', $getParams);
$listing = new Listing();
$listing->setType($type);
@ -144,6 +105,4 @@ 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);
};

View file

@ -11,27 +11,22 @@
use Chevereto\Legacy\Classes\Listing;
use Chevereto\Legacy\Classes\Login;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\cheveretoVersionInstalled;
use function Chevereto\Legacy\encodeID;
use Chevereto\Legacy\G\Handler;
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(cheveretoVersionInstalled(), '3.7.0', '<')
|| ! getSetting('enable_followers')
) {
if (version_compare(getSetting('chevereto_version_installed'), '3.7.0', '<') || !getSetting('enable_followers')) {
$handler->issueError(404);
return;
}
$logged_user = Login::getUser();
if ($logged_user === []) {
headersNoCache();
redirect('login', 302);
redirect('login');
}
if ($handler->isRequestLevel(2)) {
$handler->issueError(404);
@ -42,9 +37,7 @@ 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);
@ -62,7 +55,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);

View file

@ -14,32 +14,28 @@ 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 function Chevereto\Legacy\G\get_route_name;
use function Chevereto\Legacy\G\get_route_path;
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\virtualRouteHandleRedirect;
use function Chevereto\Legacy\redirectIfRouting;
use function Chevereto\Vars\env;
use function Chevereto\Vars\session;
use function Chevereto\Vars\sessionVar;
return function (Handler $handler) {
virtualRouteHandleRedirect('image', $handler->requestArray()[0]);
redirectIfRouting('image', $handler->requestArray()[0]);
$imageIndex = getSetting('root_route') === 'image'
? 0
: 1;
@ -57,23 +53,18 @@ 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);
@ -84,7 +75,7 @@ return function (Handler $handler) {
$password = $request_handle[2] ?? '';
if (Image::verifyPassword($id, $password)) {
Image::delete($id);
redirect($image['path_viewer'] . '?deleted', 301);
redirect($image['path_viewer'] . '?deleted');
}
}
@ -92,65 +83,56 @@ 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'], 302);
redirect($image['path_viewer']);
}
$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'
) {
headersNoCache();
redirect('login', 302);
if (!Login::getUser() && ($image['album']['privacy'] ?? null) != 'private_but_link') {
redirect('login');
}
}
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']);
headersNoCache();
redirect($image['album']['url'], 302);
redirect($image['album']['url']);
}
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'])
&& ($handler::cond('content_manager') || $is_owner)) {
$image['user']['albums'] = User::getAlbums((int) $image['user']['id']);
if (isset($image['user']['id'])) {
$image['user']['albums'] = User::getAlbums((int) $image["user"]["id"]);
}
$is_album_cover = false;
if (isset($image['album']['id'])) {
@ -162,34 +144,22 @@ return function (Handler $handler) {
$handler::setCond('album_cover', $is_album_cover);
$image_safe_html = safe_html($image);
$image['alt'] = $image_safe_html['description'] ?? ($image_safe_html['title'] ?? $image_safe_html['name']);
$hostedAt = _s('%f hosted at %w', [
'%f' => $image_safe_html['name'] . '.' . $image['extension'],
'%w' => getSetting('website_name'),
]);
$pre_doctitle = isset($image['title'])
? strip_tags($image['title'])
: $hostedAt;
: $image_safe_html['name'] . '.' . $image['extension'] . ' hosted at ' . getSetting('website_name');
$tabs = [];
$tabs[] = [
'icon' => 'fas fa-list-ul',
'label' => _s('About'),
'id' => 'tab-about',
'current' => true,
'url' => '#about',
];
$commentsArgs = [
'url' => $image['url_short'],
'id' => $image['type'] . ':' . $image['id_encoded'],
'title' => $image['title_truncated_html'],
];
// $commentsArgs['id'] = str_replace_first(get_route_path(), get_route_name(), get_route_path(true)); // Legacy fix
$comments = getComments(...$commentsArgs);
$comments = getComments();
if ($comments !== '') {
$tabs[] = [
'icon' => 'fas fa-comments',
'label' => _s('Comments'),
'id' => 'tab-comments',
'url' => '#comments',
];
}
$handler::setVar('comments', $comments);
@ -198,37 +168,20 @@ 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('File ID'),
'label' => _s('Image ID'),
'content' => $image['id'] . ' (' . $image['id_encoded'] . ')',
],
getIpButtonsArray($bannedIp, $image['uploader_ip']),
@ -238,18 +191,19 @@ return function (Handler $handler) {
],
[
'label' => '',
'content' => $image['date_gmt'] . ' (UTC)',
'content' => $image['date_gmt'] . ' (GMT)',
],
];
$handler::setVar('content_ip', $image['uploader_ip']);
$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') {
@ -292,14 +246,14 @@ return function (Handler $handler) {
$meta_description = $image['description'];
} else {
$image_tr = [
'%i' => $image[$image['title'] === null ? 'filename' : 'title'],
'%i' => $image[is_null($image['title']) ? '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'])) {
@ -308,7 +262,7 @@ return function (Handler $handler) {
$meta_description = _s('Image %i hosted in %w', $image_tr);
}
}
$handler::setVar('meta_description', $meta_description ?? '');
$handler::setVar('meta_description', htmlspecialchars($meta_description ?? ''));
if ($handler::cond('content_manager') || $is_owner) {
$handler::setVar('user_items_editor', [
'user_albums' => $image['user']['albums'] ?? null,
@ -319,27 +273,22 @@ return function (Handler $handler) {
}
$handler::setVar('share_links_array', get_share_links());
$handler::setVar('privacy', $image['album']['privacy'] ?? '');
require_theme_file('snippets/embed');
include_theme_file('snippets/embed');
$embed_share_tpl = get_global('embed_share_tpl');
$sharing = [];
foreach (flatten_array($image) as $imageKey => $imageValue) {
$sharing['%' . strtoupper($imageKey) . '%'] = $imageValue;
}
$embed = [];
$hasSizes = [
'frame' => $image['url_frame'] !== '',
'medium' => $image['medium']['url'] !== null,
'thumb' => $image['thumb']['url'] !== null,
$sharing = [
'%URL_VIEWER%' => $image['url_viewer'],
'%URL%' => $image['url'],
'%DISPLAY_URL%' => $image['display_url'],
'%DISPLAY_TITLE%' => $image['display_title'],
'%URL_FRAME%' => $image['url_frame'],
'%THUMB_URL%' => $image['thumb']['url'],
'%MEDIUM_URL%' => $image['medium']['url'] ?? '',
];
$embed = [];
foreach ($embed_share_tpl as $code => $group) {
$entries = [];
$groupLabel = $group['label'];
foreach ($group['options'] as $option => $optionValue) {
foreach ($hasSizes as $sizeKey => $sizeValue) {
if (! $sizeValue && str_starts_with($option, $sizeKey . '-')) {
continue 2;
}
}
$value = $optionValue['template'];
if (is_array($value)) {
$value = $value[$image['type']];
@ -354,32 +303,19 @@ return function (Handler $handler) {
$label = $optionValue['label'];
$label = str_ireplace($groupLabel, '', $label);
$label = ucfirst(trim($label));
$entry = [
$entries[] = [
'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']);
}
};

View file

@ -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 (null === ($handler->request()[0] ?? null) || null === ($handler->request()[1] ?? null)) {
if (is_null($handler->request()[0] ?? null) || is_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);

View file

@ -15,17 +15,16 @@ 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;
@ -35,9 +34,7 @@ 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';
@ -49,27 +46,25 @@ return function (Handler $handler) {
if (server()['QUERY_STRING'] ?? false) {
switch (key($querystr)) {
case 'random':
headersNoCache();
if (! $handler::cond('random_enabled')) {
redirect('', 302);
if (!$handler::cond('random_enabled')) {
redirect('/');
}
$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'] ?? '');
$key = array_search($last_viewed_image, $random_ids, true);
if ($key !== false) {
if (($key = array_search($last_viewed_image, $random_ids)) !== 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 {
@ -79,24 +74,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('', 302);
redirect();
} else {
sessionVar()->put('random_failure', (session()['random_failure'] ?? 0) + 1);
}
@ -105,23 +100,21 @@ return function (Handler $handler) {
sessionVar()->remove('random_failure');
}
}
$redirectTo = $image
? $image['path_viewer']
: '?random';
redirect($redirectTo, 302);
redirect(
$image
? $image['path_viewer']
: '?random'
);
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'], 301);
redirect($image['path_viewer']);
}
}
}
@ -129,6 +122,7 @@ return function (Handler $handler) {
return;
break;
case 'list':
$handler->setTemplate('index');
@ -144,7 +138,7 @@ return function (Handler $handler) {
break;
}
}
if (Settings::get('homepage_style') === 'split') {
if (Settings::get('homepage_style') == 'split') {
$tabs = [
[
'tools' => true,
@ -153,28 +147,22 @@ return function (Handler $handler) {
'type' => 'image',
],
];
$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);
$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);
if (is_array($home_uid_arr)) {
$home_uid_arr = array_filter($home_uid_arr);
$home_uid_bind = [];
foreach ($home_uid_arr as $k => $v) {
if (! is_numeric($v)) {
continue;
}
$home_uid_bind[] = ':user_id_' . $k;
if ($v == 0) {
$home_uid_is_null = true;
}
}
$home_uid_bind = implode(',', $home_uid_bind);
}
$doing = is_array($home_uid_arr)
? 'recent'
: 'trending';
$explore_discovery = $handler::var('explore_discovery');
$list = $explore_discovery[$doing];
$doing = is_array($home_uid_arr) ? 'recent' : 'trending';
$explore_semantics = $handler::var('explore_semantics');
$list = $explore_semantics[$doing];
$list['list'] = $doing;
$getParams = Listing::getParams(request());
$listing = new Listing();
@ -199,7 +187,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]);
}
}
@ -239,29 +227,26 @@ 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 ' . $button_color . '">'
'class="btn btn-big accent ' . getSetting('homepage_cta_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', implode(' ', $homepage_cta));
$handler::setVar('homepage_cta', join(' ', $homepage_cta));
};

View file

@ -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 (cheveretoVersionInstalled() !== '') {
if (Settings::get('chevereto_version_installed') !== null) {
$handler->issueError(404);
return;

File diff suppressed because it is too large Load diff

View file

@ -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,30 +38,27 @@ return function (Handler $handler) {
$logged_user = Login::getUser();
User::statusRedirect($logged_user['status'] ?? null);
if ($logged_user) {
redirect(User::getUrl($logged_user), 302);
redirect(User::getUrl($logged_user));
}
$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,
@ -74,9 +71,9 @@ return function (Handler $handler) {
case 'awaiting-confirmation':
Login::setSignup([
'status' => 'awaiting-confirmation',
'email' => $user['email'],
'email' => $user['email']
]);
redirect('account/awaiting-confirmation', 302);
redirect('account/awaiting-confirmation');
break;
case 'banned':
@ -84,7 +81,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']);
}
@ -93,7 +90,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(), true);
$redirect_to = User::getUrl(Login::getUser());
if (TwoFactor::hasFor($user['id'])) {
sessionVar()->put('challenge_two_factor', $user['id']);
$redirect_to = 'account/two-factor';
@ -104,7 +101,7 @@ return function (Handler $handler) {
$redirect_to = 'account/email-needed';
}
redirect($redirect_to, 302);
redirect($redirect_to);
} else {
$is_error = true;
}

View file

@ -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;

View file

@ -11,27 +11,24 @@
use Chevereto\Legacy\Classes\Listing;
use Chevereto\Legacy\Classes\Login;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\get_route_name;
use Chevereto\Legacy\G\Handler;
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'],
@ -43,7 +40,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);

View file

@ -12,14 +12,14 @@
use Chevereto\Legacy\Classes\Image;
use Chevereto\Legacy\Classes\Settings;
use Chevereto\Legacy\Classes\User;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\get_public_url;
use function Chevereto\Legacy\G\json_document_output;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\json_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_document_output;
use function Chevereto\Legacy\G\xml_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;
}
$viewerImage = Image::getUrlViewer(type: 'image', id_encoded: '%id');
$viewerImage = str_replace('/', '\/', $viewerImage);
$regex = str_replace_last('%id', '(.*)', $viewerImage);
$viewer = Image::getUrlViewer('%id');
$viewer = str_replace('/', '\/', $viewer);
$regex = str_replace_last('%id', '(.*)', $viewer);
$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);
exit();
die();
}
$id = getIdFromURLComponent($matches[1]);
if ($id == 0) {
set_status_header(404);
exit();
die();
}
$image = Image::getSingle(id: $id, pretty: true);
if ($image === []) {
set_status_header(404);
exit();
die();
}
if (! $image['is_approved']) {
if (!$image['is_approved']) {
set_status_header(403);
exit();
die();
}
if (in_array($image['album']['privacy'] ?? '', ['password', 'private', 'custom'])) {
set_status_header(401);
exit();
die();
}
if (($image['user']['is_private'] ?? false) == 1) {
unset($image['user']);
@ -72,15 +72,7 @@ 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;
@ -121,16 +113,18 @@ return function (Handler $handler) {
'thumbnail_height' => $display_height,
]);
}
$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);
switch (get()['format'] ?? '') {
case 'xml':
xml_output(['oembed' => $data]);
break;
case 'json':
default:
json_output($data);
break;
}
exit();
die();
};

View file

@ -10,29 +10,29 @@
*/
use Chevereto\Legacy\Classes\Page;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\add_ending_slash;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Vars\env;
return function (Handler $handler) {
if (! (bool) env()['CHEVERETO_ENABLE_PAGES']) {
$handler->issueError(404);
if (!(bool) env()['CHEVERETO_ENABLE_PAGES']) {
$this->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) {

View file

@ -10,27 +10,22 @@
*/
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 function Chevereto\Legacy\G\require_theme_file;
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\G\include_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()) {
$handler->issueError(404);
return;
}
if ($handler->isRequestLevel(2)) {
if (!getSetting('enable_plugin_route') && !Login::isAdmin()) {
$handler->issueError(404);
return;
}
$src = getSetting('sdk_pup_url') ?: get_public_url('sdk/pup.js');
$src = str_replace_first('https:', '', $src);
require_theme_file('snippets/embed');
include_theme_file('snippets/embed');
$embed_share_tpl = get_global('embed_share_tpl');
$embed = [];
foreach ($embed_share_tpl as $vGroup) {
@ -44,7 +39,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) {
@ -76,7 +71,7 @@ return function (Handler $handler) {
'Vanilla Forums',
'vBulletin',
'WoltLab',
'XenForo',
'XenForo'
],
'palettes' => [
'default' => ['#ececec', '#000', '#2980b9', '#fff'],
@ -90,7 +85,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}',
@ -106,7 +101,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>';

View file

@ -9,8 +9,8 @@
* file that was distributed with this source code.
*/
use Chevereto\Legacy\G\Handler;
use function Chevereto\Legacy\decryptString;
use Chevereto\Legacy\G\Handler;
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);

View file

@ -13,20 +13,27 @@ 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;
@ -36,14 +43,14 @@ return function (Handler $handler) {
return;
} // Allow only 3 levels
if (null === ($handler->request()[0] ?? null)) {
if (is_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;
@ -54,8 +61,8 @@ return function (Handler $handler) {
$search->request = request();
$search->requester = Login::getUser();
$search->build();
if ($search->q === '') {
redirect('', 302);
if (!check_value($search->q)) {
redirect();
return;
}
@ -84,16 +91,13 @@ return function (Handler $handler) {
$listing->setOutputTpl($search->type);
$listing->exec();
$handler::setVar('listing', $listing);
} catch (Exception) {
} catch (Exception $e) {
$getParams = [];
}
$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) {
@ -102,23 +106,17 @@ 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']));
@ -129,5 +127,4 @@ return function (Handler $handler) {
$handler::setVar('user_items_editor', false);
}
$handler::setVar('share_links_array', get_share_links());
$handler::setVar('meta_robots', 'noindex, follow');
};

View file

@ -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,44 +45,27 @@ 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', 302);
redirect('login');
}
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',
'file_meta_tag_camera_model',
'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', '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, true);
if (!getSetting('enable_expirable_uploads')) {
$key = array_search('image_expiration', $allowed_to_edit);
unset($allowed_to_edit[$key]);
}
$user = $is_dashboard_user
@ -93,16 +76,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, true)
if (in_array('language', $allowed_to_edit)
&& 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']);
@ -129,18 +112,15 @@ return function (Handler $handler) {
];
$default_route = 'account';
$route_homepage = false;
if (getSetting('website_mode') === 'personal'
&& getSetting('website_mode_personal_routing') !== '/'
&& $logged_user['id'] === getSetting('website_mode_personal_uid')
) {
if (getSetting('website_mode') == 'personal' and getSetting('website_mode_personal_routing') !== '/' and $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;
@ -151,26 +131,22 @@ return function (Handler $handler) {
}
$doing_level = $is_dashboard_user ? 2 : 0;
$doing = $handler->request()[$doing_level] ?? $default_route;
if (isset($handler->request()[$doing_level + 1])
|| ($doing != null && ! array_key_exists($doing, $routes))
) {
if (!$user || isset($handler->request()[$doing_level + 1]) || (!is_null($doing) and !array_key_exists($doing, $routes))) {
$handler->issueError(404);
return;
}
if ($doing === '') { // @phpstan-ignore-line
if ($doing == '') {
$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) {
unset($routes[$aux]);
if ($aux == 'homepage' and !$route_homepage) {
continue;
}
$tabs[$aux] = [
@ -178,18 +154,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;
@ -213,85 +189,63 @@ 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], false)
? 1
: 0;
$POST[$k] = in_array($POST[$k], ['On', 1]) ? 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 (isset($POST['image_expiration'])
&& (
! dateinterval($POST['image_expiration'])
|| ! array_key_exists($POST['image_expiration'], Image::getAvailableExpirations())
)
) {
if ($POST['image_expiration'] !== null && (!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')) {
if (isset($POST['language'])
&& ! array_key_exists($POST['language'], get_available_languages())
) {
$POST['language'] = getSetting('default_language');
}
if (getSetting('language_chooser_enable') && !array_key_exists($POST['language'], get_available_languages())) {
$POST['language'] = getSetting('default_language');
}
if (! in_array($POST['timezone'], timezone_identifiers_list(), false)) {
if (!in_array($POST['timezone'], timezone_identifiers_list())) {
$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'], true)) { // 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) {
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;
}
@ -301,7 +255,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']
) {
@ -313,25 +267,22 @@ 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='
@ -341,13 +292,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']);
$mail['message'] = $mail_body;
send_mail($POST['email'], $mail['subject'], $mail['message']);
unset($POST['email']);
@ -355,15 +306,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;
@ -373,20 +324,18 @@ 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('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['new-password'] ?? '')) {
if (!preg_match('/' . getSetting('user_password_pattern') . '/', $POST['new-password'] ?? '')) {
$input_errors['new-password'] = _s('Invalid password');
}
if ($POST['new-password'] !== $POST['new-password-confirm']) {
@ -396,11 +345,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']);
@ -410,7 +359,7 @@ return function (Handler $handler) {
break;
case 'homepage':
if (! array_key_exists($doing, $routes)) {
if (!array_key_exists($doing, $routes)) {
$handler->issueError(404);
return;
@ -419,7 +368,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];
@ -447,12 +396,14 @@ 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'], false)) {
if (!$is_error) {
if (in_array($doing, [null, 'account', 'profile'])) {
foreach ($POST as $k => $v) {
if (($user[$k] ?? null) !== $v) {
$is_changed = true;
@ -460,10 +411,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'], true)) {
if (!in_array($editing_array['status'] ?? null, ['valid', 'banned', 'awaiting-confirmation', 'awaiting-email'])) {
unset($editing_array['status']);
}
if ($logged_user['is_manager']) {
@ -484,13 +435,13 @@ return function (Handler $handler) {
break;
}
if ($user['is_admin'] != $is_admin) {
$pushAdmin = true;
$handler::setCond('admin', (bool) $is_admin);
$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']);
@ -498,25 +449,14 @@ return function (Handler $handler) {
if (empty($POST['email'])) {
unset($editing_array['email']);
}
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);
}
if (User::update($user['id'], $editing_array)) {
$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');
@ -524,38 +464,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'], false) && ! $is_dashboard_user) {
if (in_array($doing, ['', 'account']) && !$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);
@ -563,7 +503,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);
}
@ -572,7 +512,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'],
@ -602,38 +542,36 @@ 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'] . ' (UTC)',
],
'content' => $handler::var('user')['date_gmt'] . ' (GMT)'
]
];
if ($handler::var('user')['registration_ip']) {
$user_list_values[] = getIpButtonsArray($bannedIp, $handler::var('user')['registration_ip']);

View file

@ -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', 302);
redirect('account/awaiting-confirmation');
}
$logged_user = Login::getUser();
User::statusRedirect($logged_user['status'] ?? null);
if ($logged_user) {
redirect(User::getUrl($logged_user), 302);
redirect(User::getUrl($logged_user));
}
$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('/' . Settings::USER_PASSWORD_PATTERN . '/', $POST['password'] ?? '')) {
if (!preg_match('/' . getSetting('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'] ?? 0) != 1) {
if ($POST['signup-accept-terms-policies'] != 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,35 +111,26 @@ 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;
}
@ -150,7 +141,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';
}
}
@ -161,7 +152,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 {
@ -175,14 +166,14 @@ return function (Handler $handler) {
$is_error = true;
$error_message = $e->getMessage();
} else {
throw new Exception($e, (int) $e->getCode(), $e);
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);
@ -190,7 +181,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='
@ -199,12 +190,9 @@ 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',
getSetting('website_name')
);
$mail['subject'] = _s('Confirmation required at %s', getSettings()['website_name']);
$mail['message'] = get_email_body_str('mails/account-confirm');
send_mail($POST['email'], $mail['subject'], $mail['message']);
} else {
@ -220,24 +208,24 @@ return function (Handler $handler) {
$mail['subject'] = _s('Welcome to %s', getSetting('website_name'));
$mail['message'] = get_email_body_str('mails/account-welcome');
send_mail($logged_user['email'], $mail['subject'], $mail['message']);
} catch (Exception) {
} catch (Exception $e) {
} // Silence
redirect($user['url'], 302);
redirect($user['url']);
}
Login::setSignup([
'status' => 'awaiting-confirmation',
'email' => $SAFE_POST['email'],
'email' => $SAFE_POST['email']
]);
redirect('account/awaiting-confirmation', 302);
redirect('account/awaiting-confirmation');
}
}
}
if ($is_error) {
RequestLog::insert([
'type' => 'signup',
'result' => 'fail',
'result' => 'fail'
]);
$error_message ??= _s('Check the errors in the form to continue.');
$error_message = $error_message ?? _s('Check the errors in the form to continue.');
if ((getSetting('captcha') ?? false) && must_use_captcha($failed_access_requests['day'] + 1)) {
$captcha_needed = true;
}

View file

@ -1,46 +0,0 @@
<?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);
};

View file

@ -1,160 +0,0 @@
<?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);
};

View file

@ -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']
|| cheveretoVersionInstalled() === ''
if (!(bool) env()['CHEVERETO_ENABLE_UPDATE_HTTP']
|| Settings::get('chevereto_version_installed') === null
) {
$handler->issueError(404);
return;
}
if (! Login::isAdmin()) {
if (!Login::isAdmin()) {
$handler->issueError(403);
return;

View file

@ -13,21 +13,22 @@ 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);
@ -36,7 +37,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 = [];
}
}

View file

@ -1,85 +0,0 @@
<?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);
};

View file

@ -9,33 +9,27 @@
* file that was distributed with this source code.
*/
use Chevereto\Legacy\Classes\DB;
use Chevere\String\ModifyString;
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 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 Chevereto\Legacy\G\Handler;
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\headersNoCache;
use function Chevereto\Legacy\virtualRouteHandleRedirect;
use function Chevereto\Legacy\redirectIfRouting;
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();
virtualRouteHandleRedirect('user', $handler->requestArray()[0]);
redirectIfRouting('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)) {
@ -46,30 +40,19 @@ return function (Handler $handler) {
$request_handle = $userIndex === 0
? $handler->requestArray()
: $handler->request();
$userMapPaths = ['search', 'following', 'followers'];
$userMapPaths[] = getSetting('user_profile_view') === 'files'
? 'albums'
: 'files';
if (getSetting('website_mode') === 'personal'
&& getSetting('website_mode_personal_routing') === '/'
&& $request_handle[0] !== '/'
if (getSetting('website_mode') == 'personal'
&& getSetting('website_mode_personal_routing') == '/'
&& in_array($request_handle[0], ['albums', 'search', 'following', 'followers'])
) {
if (! in_array($request_handle[0], $userMapPaths, true)) {
$handler->issueError(404);
return;
}
$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],
1 => $request_handle[0]
];
}
}
if (($request_handle[0] ?? false) === getSetting('route_user')
&& getSetting('root_route') !== 'user'
) {
if ($request_handle[0] === getSetting('route_user') && getSetting('root_route') !== 'user') {
array_shift($request_handle);
}
$username = $request_handle[0] ?? null;
@ -79,7 +62,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;
@ -87,89 +70,74 @@ return function (Handler $handler) {
$logged_user = Login::getUser();
User::statusRedirect($logged_user['status'] ?? null);
$userHandle = isset($id) ? 'id' : 'username';
$user = $personal_mode_user
?? User::getSingle(${$userHandle}, $userHandle);
$user = $personal_mode_user ?? 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 = str_replace_first('/' . $user['username'], '', $currentUrl);
headersNoCache();
redirect($redirectTo, 302);
$redirectTo = (new ModifyString($currentUrl))
->withReplaceFirst('/' . $user['username'], '')
->__toString();
redirect($redirectTo);
}
}
$pre_doctitle = '';
$user_routes = [];
$userHome = $user['home'] === 'files'
? 'files'
: $user['home'];
$user_views = [
'files' => [
'images' => [
'title' => _s(
'%t by %s',
"%t by %s",
[
'%t' => _n('File', 'Files', 20),
'%t' => _n('File', 'Files', 20)
]
),
'title_short' => _s('Files'),
'title_short' => _s("Images"),
],
'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'),
'title_short' => _s('Search'),
],
];
foreach (array_keys($user_views) as $k) {
$user_routes[] = $k === $userHome
? $username
: $k;
foreach (array_keys($user_views) as $k) { // Need to use $k => $v to fetch array key easily
$user_routes[] = $k == 'images' ? $username : $k;
}
// albums: images, admin, search
// 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';
@ -179,37 +147,33 @@ 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'], 302);
if (!(request()['q'] ?? false)) {
redirect($user['url']);
}
$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, true)
) {
if ($request_handle[1] !== server()['QUERY_STRING'] && !in_array($request_handle[1], $user_routes)) {
$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'], true)
) {
if (!empty(request()['list']) && !in_array(request()['list'], ['images', 'albums', 'users'])) {
$handler->issueError(404);
return;
@ -219,97 +183,68 @@ return function (Handler $handler) {
$user_views[$request_handle[1]]['current'] = true;
}
} else {
$user_views[$userHome]['current'] = true;
$user_views['images']['current'] = true;
}
$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;
}
}
$handler::setCond('show_follow_button', $show_follow_button);
$base_user_url = $user['url'];
$current_view = $userHome;
$type = 'images';
$current_view = $type;
$tools = false;
foreach ($user_views as $k => $v) {
$handler::setCond('user_' . $k, (bool) $v['current']);
if ($v['current']) {
$current_view = $k;
if ($current_view !== $userHome) {
$base_user_url .= "/{$k}";
if ($current_view !== 'images') {
$base_user_url .= "/$k";
}
}
}
$type = match ($current_view) {
'files' => 'images',
default => $current_view
};
$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 'images':
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 = [
[
@ -325,7 +260,7 @@ return function (Handler $handler) {
'label' => _n('Album', 'Albums', 20),
'id' => 'list-user-albums',
'current' => $currentKey === 1,
],
]
];
foreach ($tabs as $k => $v) {
$params = [
@ -338,10 +273,10 @@ return function (Handler $handler) {
$tabs[$k]['url'] = $base_user_url . '/?' . $tabs[$k]['params'];
}
break;
break;
}
$icon = [
'files' => 'fas fa-photo-film',
'images' => 'fas fa-photo-film',
'albums' => 'fas fa-images',
'liked' => 'fas fa-heart',
'following' => 'fas fa-rss',
@ -351,91 +286,34 @@ 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';
$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 DISTINCT 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 DISTINCT 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)) {
if (!isset($tabs)) {
$tabs = Listing::getTabs([
'listing' => $type,
'basename' => $base_user_url,
'tools' => $tools,
'tools_available' => $tools_available ?? [],
'tools_available' => $tools_available ?? null,
'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['images']['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'], true)) {
if ($user["image_count"] > 0
|| $user["album_count"] > 0
|| in_array($current_view, ['liked', 'following', 'followers'])) {
$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;
@ -444,39 +322,31 @@ return function (Handler $handler) {
switch ($current_view) {
case 'liked':
$where = 'WHERE like_user_id=:user_id';
$tpl = 'liked/' . match ($type) {
'images' => 'image',
'albums' => 'album',
};
$tpl = 'liked';
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';
// if ($type === 'albums' && $tags_active === []) {
// $where .= ' AND album_parent_id IS NULL';
// }
: 'WHERE album_user_id=:user_id 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;
}
@ -494,17 +364,15 @@ 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->setTagsIds(...$tags_id);
$listing->setTagsString($tag_string_no_spaces);
$listing->setOwner((int) $user["id"]);
$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
);
@ -512,14 +380,13 @@ return function (Handler $handler) {
$listing->setTools(true);
}
}
$listing->bind(':user_id', $user['id']);
if ($user_views['search']['current'] && ! empty($user['search']['q'])) {
$handler::setVar('meta_robots', 'noindex, follow');
$listing->bind(":user_id", $user["id"]);
if ($user_views['search']['current'] && !empty($user['search']['q'])) {
$listing->bind(':q', $user['search']['q']);
}
$listing->setOutputTpl($output_tpl);
$listing->exec();
} catch (Exception) {
} catch (Exception $e) {
} // Silence to avoid wrong input queries
}
$title = sprintf($user_views[$current_view]['title'], $user['name_short_html']);
@ -529,7 +396,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);
@ -549,24 +416,12 @@ 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);
};

View file

@ -1,22 +0,0 @@
<?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);
};

View file

@ -1,38 +0,0 @@
<?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();
};

View file

@ -4,7 +4,6 @@ parameters:
- phpstan-bootstrap.php
paths:
- bin
- legacy
- src/Legacy
- src/Encryption
- ../content/

31
app/phpunit-report.xml Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
colors="true"
verbose="true"
cacheResult="false"
failOnRisky="true"
failOnWarning="true"
testdox="true">
<php>
<const name="PHPUNIT_CHEVERETO_TESTSUITE" value="true"/>
</php>
<testsuites>
<testsuite name="Chevereto unit tests">
<directory suffix="Test.php">tests/Unit/</directory>
</testsuite>
</testsuites>
<coverage cacheDirectory=".phpunit.cache/code-coverage" processUncoveredFiles="true" ignoreDeprecatedCodeUnits="true">
<include>
<directory suffix=".php">src/</directory>
</include>
<exclude>
<directory suffix=".php">src/Components/Legacy/</directory>
<directory suffix=".php">src/Components/Legacy/**/</directory>
<directory suffix="workflow.php">src/</directory>
</exclude>
<report>
<clover outputFile="build/coverage/clover.xml"/>
<html outputDirectory="build/coverage/html" lowUpperBound="50" highLowerBound="90"/>
</report>
</coverage>
</phpunit>

33
app/phpunit.xml Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
colors="true"
verbose="true"
stderr="true"
cacheResult="false"
failOnRisky="true"
failOnWarning="true"
testdox="false"
processIsolation="true">
<php>
<const name="PHPUNIT_CHEVERETO_TESTSUITE" value="true"/>
</php>
<testsuites>
<testsuite name="Chevereto integration tests">
<directory suffix="Test.php">tests/Integration</directory>
</testsuite>
</testsuites>
<coverage cacheDirectory=".phpunit.cache/code-coverage" processUncoveredFiles="true" ignoreDeprecatedCodeUnits="true">
<include>
<directory suffix=".php">src/</directory>
</include>
<exclude>
<directory suffix=".php">src/Components/Legacy/</directory>
<directory suffix=".php">src/Components/Legacy/**/</directory>
<directory suffix="workflow.php">src/</directory>
</exclude>
<report>
<clover outputFile="build/coverage/clover.xml"/>
<html outputDirectory="build/coverage/html" lowUpperBound="50" highLowerBound="90"/>
</report>
</coverage>
</phpunit>

View file

@ -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` text,
`album_password` text,
`album_privacy_extra` mediumtext,
`album_password` mediumtext,
`album_image_count` bigint(32) NOT NULL DEFAULT '0',
`album_description` text,
`album_description` mediumtext,
`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` text,
`album_cta` longtext,
PRIMARY KEY (`album_id`),
KEY `album_name` (`album_name`),
KEY `album_user_id` (`album_user_id`),

View file

@ -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` text NOT NULL,
`api_key_hash` mediumtext NOT NULL,
PRIMARY KEY (`api_key_id`),
KEY `api_key_user_id` (`api_key_user_id`),
KEY `api_key_name` (`api_key_name`),

View file

@ -8,6 +8,7 @@ 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;

View file

@ -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) COLLATE utf8mb4_bin NOT NULL,
`category_description` text,
`category_url_key` varchar(32) NOT NULL,
`category_description` mediumtext,
PRIMARY KEY (`category_id`),
UNIQUE KEY `url_key` (`category_url_key`) USING BTREE
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

View file

@ -8,8 +8,5 @@ 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`),
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`)
PRIMARY KEY (`confirmation_id`)
) ENGINE=%table_engine% DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

View file

@ -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` text,
`image_description` mediumtext,
`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` mediumtext,
`image_original_exifdata` longtext,
`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','mov') then 2
when `image_extension` in ('avif','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') then 2
when `image_extension` in ('jpg', 'jpeg', 'gif', 'png', 'webp') then 1
else 0 end) stored,
PRIMARY KEY (`image_id`),
KEY `image_name` (`image_name`),

View file

@ -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) DEFAULT NULL,
`importing_content_id` bigint(32) NOT NULL DEFAULT '0',
PRIMARY KEY (`importing_id`),
UNIQUE KEY `importing_path` (`importing_path`(191))
) ENGINE=%table_engine% DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

View file

@ -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` text,
`login_connection_token` text NOT NULL COMMENT 'Ciphertext',
`login_connection_resource_name` mediumtext,
`login_connection_token` mediumtext 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`),

View file

@ -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` text NOT NULL,
`login_cookie_hash` text NOT NULL,
`login_cookie_user_agent` mediumtext NOT NULL,
`login_cookie_hash` mediumtext 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`),

View file

@ -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` text NOT NULL,
`login_password_hash` mediumtext 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;

Some files were not shown because too many files have changed in this diff Show more