use namespace

This commit is contained in:
Jean-Christian Denis 2023-03-26 15:37:32 +02:00
parent 7880918940
commit 84d2e74487
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
11 changed files with 564 additions and 319 deletions

View file

@ -16,5 +16,6 @@ if (!defined('DC_RC_PATH')) {
class initFilesAlias class initFilesAlias
{ {
/** @var string This plugin table name */
public const ALIAS_TABLE_NAME = 'filesalias'; public const ALIAS_TABLE_NAME = 'filesalias';
} }

View file

@ -10,27 +10,53 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\filesAlias;
use dcAdmin;
use dcAuth;
use dcCore;
use dcFavorites;
use dcNsProcess;
use dcPage;
class Backend extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN');
return static::$init;
}
public static function process(): bool
{
if (!static::$init) {
return false;
} }
dcCore::app()->menu[dcAdmin::MENU_BLOG]->addItem( dcCore::app()->menu[dcAdmin::MENU_BLOG]->addItem(
__('Media sharing'), My::name(),
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
urldecode(dcPage::getPF(basename(__DIR__) . '/icon.svg')), dcPage::getPF(My::id() . '/icon.svg'),
preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/', $_SERVER['REQUEST_URI']), preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . My::id())) . '(&.*)?$/', $_SERVER['REQUEST_URI']),
dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CONTENT_ADMIN]), dcCore::app()->blog->id) dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CONTENT_ADMIN]), dcCore::app()->blog->id)
); );
dcCore::app()->addBehavior('adminDashboardFavoritesV2', function (dcFavorites $favs) { dcCore::app()->addBehavior('adminDashboardFavoritesV2', function (dcFavorites $favs): void {
$favs->register('filesAlias', [ $favs->register(My::id(), [
'title' => __('Media sharing'), 'title' => My::name(),
'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), 'url' => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
'small-icon' => dcPage::getPF(basename(__DIR__) . '/icon.svg'), 'small-icon' => dcPage::getPF(My::id() . '/icon.svg'),
'large-icon' => dcPage::getPF(basename(__DIR__) . '/icon.svg'), 'large-icon' => dcPage::getPF(My::id() . '/icon.svg'),
'permissions' => dcCore::app()->auth->makePermissions([ 'permissions' => dcCore::app()->auth->makePermissions([
dcAuth::PERMISSION_USAGE, dcAuth::PERMISSION_USAGE,
dcAuth::PERMISSION_CONTENT_ADMIN, dcAuth::PERMISSION_CONTENT_ADMIN,
]), ]),
]); ]);
}); });
return true;
}
}

View file

@ -10,80 +10,37 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_RC_PATH')) { declare(strict_types=1);
return null;
}
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates'); namespace Dotclear\Plugin\filesAlias;
dcCore::app()->tpl->addValue('fileAliasURL', ['templateAlias','fileAliasURL']);
class templateAlias use dcCore;
use dcNsProcess;
class Frontend extends dcNsProcess
{ {
public static function fileAliasURL($attr) public static function init(): bool
{ {
$f = dcCore::app()->tpl->getFilters($attr); static::$init = defined('DC_RC_PATH');
return '<?php echo ' . sprintf($f, 'dcCore::app()->blog->url.dcCore::app()->url->getBase("filesalias")."/".dcCore::app()->ctx->filealias->filesalias_url') . '; ?>'; return static::$init;
}
} }
class urlFilesAlias extends dcUrlHandlers public static function process(): bool
{ {
public static function alias($args) if (!static::$init) {
{ return false;
$delete = false;
dcCore::app()->ctx->__set('filealias', dcCore::app()->__get('filealias')->getAlias($args));
if (dcCore::app()->ctx->__get('filealias')->isEmpty()) {
self::p404();
} }
if (dcCore::app()->ctx->__get('filealias')->filesalias_disposable) { dcCore::app()->tpl->setPath(
$delete = true; dcCore::app()->tpl->getPath(),
} My::path() . DIRECTORY_SEPARATOR . 'default-templates'
);
dcCore::app()->tpl->addValue(
'fileAliasURL',
[FrontendTemplate::class, 'fileAliasURL']
);
if (dcCore::app()->ctx->__get('filealias')->filesalias_password) { return true;
# Check for match
if (!empty($_POST['filepassword']) && $_POST['filepassword'] == dcCore::app()->ctx->__get('filealias')->filesalias_password) {
self::servefile(dcCore::app()->ctx->__get('filealias')->filesalias_destination, $args, $delete);
} else {
self::serveDocument('file-password-form.html', 'text/html', false);
return;
}
} else {
self::servefile(dcCore::app()->ctx->__get('filealias')->filesalias_destination, $args, $delete);
}
}
public static function servefile($target, $alias, $delete = false)
{
$a = new aliasMedia();
$media = $a->getMediaId($target);
if (empty($media)) {
self::p404();
}
$file = dcCore::app()->media->getFile($media);
if (empty($file->file)) {
self::p404();
}
header('Content-type: ' . $file->type);
header('Content-Length: ' . $file->size);
header('Content-Disposition: attachment; filename="' . $file->basename . '"');
if (ob_get_length() > 0) {
ob_end_clean();
}
flush();
readfile($file->file);
if ($delete) {
dcCore::app()->__get('filealias')->deleteAlias($alias);
}
} }
} }

29
src/FrontendTemplate.php Normal file
View file

@ -0,0 +1,29 @@
<?php
/**
* @brief filesAlias, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Osku and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\filesAlias;
use ArrayObject;
use dcCore;
class FrontendTemplate
{
public static function fileAliasURL(ArrayObject $attr): string
{
return '<?php echo ' . sprintf(
dcCore::app()->tpl->getFilters($attr),
'dcCore::app()->blog->url.dcCore::app()->url->getBase("filesalias")."/".dcCore::app()->ctx->filealias->filesalias_url'
) . '; ?>';
}
}

View file

@ -10,21 +10,34 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\filesAlias;
use dbStruct;
use dcCore;
use dcNsProcess;
use Exception;
class Install extends dcNsProcess
{
public static function init(): bool
{
self::$init = defined('DC_CONTEXT_ADMIN') && dcCore::app()->newVersion(My::id(), dcCore::app()->plugins->moduleInfo(My::id(), 'version'));
return self::$init;
}
public static function process(): bool
{
if (!self::$init) {
return false;
} }
try { try {
if (!dcCore::app()->newVersion(
basename(__DIR__),
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
)) {
return null;
}
$s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
$s->{initFilesAlias::ALIAS_TABLE_NAME} $s->{My::ALIAS_TABLE_NAME}
->blog_id('varchar', 32, false) ->blog_id('varchar', 32, false)
->filesalias_url('varchar', 255, false) ->filesalias_url('varchar', 255, false)
->filesalias_destination('varchar', 255, false) ->filesalias_destination('varchar', 255, false)
@ -44,4 +57,6 @@ try {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
return false; return true;
}
}

View file

@ -10,22 +10,59 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\filesAlias;
use dcAuth;
use dcCore;
use dcMedia;
use dcNsProcess;
use dcPage;
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\Html\Form\{
Checkbox,
Form,
Hidden,
Input,
Label,
Note,
Para,
Submit,
Text
};
use Exception;
class Manage extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN') && dcCore::app()->auth->check(
dcCore::app()->auth->makePermissions([
dcAuth::PERMISSION_ADMIN,
]),
dcCore::app()->blog->id
);
return static::$init;
} }
$o = dcCore::app()->__get('filealias'); public static function process(): bool
$aliases = $o->getAliases(); {
$media = new dcMedia(); if (!static::$init) {
$a = new aliasMedia(); return false;
$part = $_REQUEST['part'] ?? 'list'; }
if (!(dcCore::app()->media instanceof dcMedia)) {
dcCore::app()->media = new dcMedia();
}
# Update aliases # Update aliases
if (isset($_POST['a']) && is_array($_POST['a'])) { if (isset($_POST['a']) && is_array($_POST['a'])) {
try { try {
$o->updateAliases($_POST['a']); Utils::updateAliases($_POST['a']);
dcAdminNotices::addSuccessNotice(__('Aliases successfully updated.')); dcPage::addSuccessNotice(__('Aliases successfully updated.'));
dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__)); dcCore::app()->adminurl->redirect('admin.plugin.' . My::id());
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
@ -39,15 +76,15 @@ if (isset($_POST['filesalias_url'])) {
$totrash = isset($_POST['filesalias_disposable']) ? true : false; $totrash = isset($_POST['filesalias_disposable']) ? true : false;
$password = empty($_POST['filesalias_password']) ? '' : $_POST['filesalias_password']; $password = empty($_POST['filesalias_password']) ? '' : $_POST['filesalias_password'];
if (preg_match('/^' . preg_quote($media->root_url, '/') . '/', $target)) { if (preg_match('/^' . preg_quote(dcCore::app()->media->root_url, '/') . '/', $target)) {
$target = preg_replace('/^' . preg_quote($media->root_url, '/') . '/', '', $target); $target = preg_replace('/^' . preg_quote(dcCore::app()->media->root_url, '/') . '/', '', $target);
$found = $a->getMediaId($target); $found = Utils::getMediaId($target);
if (!empty($found)) { if (!empty($found)) {
try { try {
$o->createAlias($url, $target, $totrash, $password); Utils::createAlias($url, $target, $totrash, $password);
dcAdminNotices::addSuccessNotice(__('Alias for this media created.')); dcPage::addSuccessNotice(__('Alias for this media created.'));
dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__)); dcCore::app()->adminurl->redirect('admin.plugin.' . My::id());
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
@ -55,13 +92,13 @@ if (isset($_POST['filesalias_url'])) {
dcCore::app()->error->add(__('Target is not in media manager.')); dcCore::app()->error->add(__('Target is not in media manager.'));
} }
} else { } else {
$found = $a->getMediaId($target); $found = Utils::getMediaId($target);
if (!empty($found)) { if (!empty($found)) {
try { try {
$o->createAlias($url, $target, $totrash, $password); Utils::createAlias($url, $target, $totrash, $password);
dcAdminNotices::addSuccessNotice(__('Alias for this media modified.')); dcPage::addSuccessNotice(__('Alias for this media modified.'));
dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__)); dcCore::app()->adminurl->redirect('admin.plugin.' . My::id());
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
@ -70,90 +107,134 @@ if (isset($_POST['filesalias_url'])) {
} }
} }
} }
?>
<html>
<head>
<title><?php echo __('Media sharing'); ?></title>
</head>
<body> return true;
<?php }
if ($part == 'new') { public static function render(): void
{
if (!self::$init) {
return;
}
dcPage::openModule(My::name());
if (($_REQUEST['part'] ?? '') == 'new') {
self::displayAliasForm();
} else {
self::displayAliasList();
}
dcPage::helpBlock('filesAlias');
dcPage::closeModule();
}
private static function displayAliasForm(): void
{
echo echo
dcPage::breadcrumb([ dcPage::breadcrumb([
html::escapeHTML(dcCore::app()->blog->name) => '', Html::escapeHTML(dcCore::app()->blog->name) => '',
__('Media sharing') => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), My::name() => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
__('New alias') => '', __('New alias') => '',
]) . ]) .
dcPage::notices() . dcPage::notices() .
'<form action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)) . '" method="post">' . (new Form('filesalias_new'))->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))->method('post')->fields([
'<h3>' . __('New alias') . '</h3>' . (new Text('h3', Html::escapeHTML(__('New alias')))),
'<p ><label for="filesalias_destination" class="required">' . __('Destination:') . ' </label>' . (new Note())->text(sprintf(__('Do not put blog media URL "%s" in fields or it will be removed.'), dcCore::app()->media->root_url))->class('form-note'),
form::field('filesalias_destination', 70, 255) . '</p>' . // destination
'<p class="form-note warn">' . __('Destination file must be in media manager.') . '</p>' . (new Para())->items([
'<p><label for="filesalias_url">' . __('URL (alias):') . '</label>' . (new Label(__('Destination:')))->for('filesalias_destination')->class('required'),
form::field('filesalias_url', 70, 255) . '</p>' . (new Input('filesalias_destination'))->size(70)->maxlenght(255),
'<p class="form-note info">' . __('Leave empty to get a randomize alias.') . '</p>' . ]),
'<p><label for="filesalias_password">' . __('Password:') . '</label> ' . (new Note())->text(__('Destination file must be in media manager.'))->class('form-note'),
form::field('filesalias_password', 70, 255) . '</p>' . // url
'<p>' . form::checkbox('filesalias_disposable', 1) . (new Para())->items([
'<label for="filesalias_disposable" class="classic">' . __('Disposable') . '</label></p>' . (new Label(__('URL (alias):')))->for('filesalias_url')->class('required'),
'<p>' . (new Input('filesalias_url'))->size(70)->maxlenght(255),
dcCore::app()->formNonce() . ]),
form::hidden('part', 'new') . (new Note())->text(__('Leave empty to get a randomize alias.'))->class('form-note'),
'<input type="submit" value="' . __('Save') . '" /></p>' . // password
'<p class="form-note">' . sprintf(__('Do not put blog media URL "%s" in fields or it will be removed.'), $media->root_url) . '</p>' . (new Para())->items([
'</form>'; (new Label(__('Password:')))->for('filesalias_password')->class('required'),
} else { (new Input('filesalias_password'))->size(70)->maxlenght(255),
]),
// disposable
(new Para())->items([
(new Checkbox('filesalias_disposable', false))->value(1),
(new Label(__('Disposable'), Label::OUTSIDE_LABEL_AFTER))->for('filesalias_disposable')->class('classic'),
]),
// submit
(new Para())->items([
(new Submit(['save']))->value(__('Save')),
(new Hidden(['part'], 'new')),
(new Text('', dcCore::app()->formNonce())),
]),
])->render();
}
private static function displayAliasList(): void
{
$aliases = Utils::getAliases();
echo echo
dcPage::breadcrumb([ dcPage::breadcrumb([
html::escapeHTML(dcCore::app()->blog->name) => '', Html::escapeHTML(dcCore::app()->blog->name) => '',
__('Media sharing') => '', My::name() => '',
]) . ]) .
dcPage::notices() . dcPage::notices() .
'<p class="top-add"><a class="button add" href="' . '<p class="top-add"><a class="button add" href="' .
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'new']) . dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'new']) .
'">' . __('New alias') . '</a></p>'; '">' . __('New alias') . '</a></p>';
if (empty($aliases)) { if ($aliases->isEmpty()) {
echo '<p>' . __('No alias') . '</p>'; echo '<p>' . __('No alias') . '</p>';
} else { } else {
$lines = '';
$i = 0;
while ($aliases->fetch()) {
$url = dcCore::app()->blog->url . dcCore::app()->url->getBase('filesalias') . '/' . Html::escapeHTML($aliases->f('filesalias_url'));
$lines .= '<tr class="line" id="l_' . $i . '">' .
'<td>' .
(new Input(['a[' . $i . '][filesalias_destination]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($aliases->f('filesalias_destination')))->render() .
'</td>' .
'<td>' .
(new Input(['a[' . $i . '][filesalias_url]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($aliases->f('filesalias_url')))->render() .
'<a href="' . $url . '">' . __('link') . '</a></td>' .
'<td>' .
(new Input(['a[' . $i . '][filesalias_password]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($aliases->f('filesalias_password')))->render() .
'</td>' .
'<td class="maximal">' .
(new Checkbox(['a[' . $i . '][filesalias_disposable]'], (bool) $aliases->f('filesalias_disposable')))->value(1)->render() .
'</td>' .
'</tr>';
$i++;
}
echo echo
'<form action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)) . '" method="post">' . (new Form('filesalias_list'))->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))->method('post')->fields([
(new Text(
'',
'<div class="table-outer">' . '<div class="table-outer">' .
'<table><thead>' . '<table><thead>' .
'<caption>' . __('Aliases list') . '</caption>' . '<caption>' . __('Aliases list') . '</caption>' .
'<tr>' . '<tr>' .
'<th class="nowrap" scope="col">' . __('Destination') . ' - <ins>' . html::escapeHTML($media->root_url) . '</ins><code>(-?-)</code></th>' . '<th class="nowrap" scope="col">' . __('Destination') . ' - <ins>' . Html::escapeHTML(dcCore::app()->media->root_url) . '</ins><code>(-?-)</code></th>' .
'<th class="nowrap" scope="col">' . __('Alias') . ' - <ins>' . dcCore::app()->blog->url . dcCore::app()->url->getBase('filesalias') . '/' . '</ins><code>(-?-)</code></th>' . '<th class="nowrap" scope="col">' . __('Alias') . ' - <ins>' . dcCore::app()->blog->url . dcCore::app()->url->getBase('filesalias') . '/' . '</ins><code>(-?-)</code></th>' .
'<th class="nowrap" scope="col">' . __('Disposable') . '</th>' .
'<th class="nowrap" scope="col">' . __('Password') . '</th>' . '<th class="nowrap" scope="col">' . __('Password') . '</th>' .
'</tr></thead><body>'; '<th class="nowrap" scope="col">' . __('Disposable') . '</th>' .
'</tr></thead><body>' .
foreach ($aliases as $k => $v) { $lines .
$url = dcCore::app()->blog->url . dcCore::app()->url->getBase('filesalias') . '/' . html::escapeHTML($v['filesalias_url']); '</tobdy></table></div>'
)),
$link = '<a href="' . $url . '">' . __('link') . '</a>'; (new Para())->items([
$v['filesalias_disposable'] ??= false; (new Submit(['save']))->value(__('Update')),
echo (new Hidden(['part'], 'list')),
'<tr class="line" id="l_' . $k . '">' . (new Text('', dcCore::app()->formNonce())),
'<td>' . form::field(['a[' . $k . '][filesalias_destination]'], 40, 255, html::escapeHTML($v['filesalias_destination'])) . '</td>' . ]),
'<td class="maximal">' . form::field(['a[' . $k . '][filesalias_url]'], 20, 255, html::escapeHTML($v['filesalias_url'])) . '<a href="' . $url . '">' . __('link') . '</a></td>' . (new Note())->text(__('To remove a link, empty its alias or destination.'))->class('form-note'),
'<td class="minimal">' . form::checkbox(['a[' . $k . '][filesalias_disposable]'], 1, $v['filesalias_disposable']) . '</td>' . ])->render();
'<td class="minimal">' . form::field(['a[' . $k . '][filesalias_password]'], 10, 255, html::escapeHTML($v['filesalias_password'])) . '</td>' . }
'</tr>';
}
echo '</tobdy></table></div>' .
'<p class="form-note">' . __('To remove a link, empty its alias or destination.') . '</p>' .
'<p>' . dcCore::app()->formNonce() . form::hidden('part', 'list') .
'<input type="submit" value="' . __('Update') . '" /></p>' .
'</form>';
} }
} }
dcPage::helpBlock('filesAlias');
?>
</body>
</html>

45
src/My.php Normal file
View file

@ -0,0 +1,45 @@
<?php
/**
* @brief filesAlias, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Osku and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\filesAlias;
/**
* Plugin definitions
*/
class My extends \initFilesAlias
{
/**
* This module id
*/
public static function id(): string
{
return basename(dirname(__DIR__));
}
/**
* This module name
*/
public static function name(): string
{
return __('Media sharing');
}
/**
* This module root path
*/
public static function path(): string
{
return dirname(__DIR__);
}
}

View file

@ -10,9 +10,16 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
declare(strict_types=1);
namespace Dotclear\Plugin\filesAlias;
/**
* Adapted from Enrico Pallazzo class
*/
class PallazzoTools class PallazzoTools
{ {
public static function rand_uniqid() public static function rand_uniqid(): string
{ {
$index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$in = time(); $in = time();

View file

@ -10,21 +10,35 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_RC_PATH')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\filesAlias;
use dcCore;
use dcNsProcess;
class Prepend extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_RC_PATH');
return static::$init;
} }
Clearbricks::lib()->autoload([ public static function process(): bool
'filesAliases' => __DIR__ . '/inc/class.files.alias.php', {
'aliasMedia' => __DIR__ . '/inc/class.files.alias.php', if (!static::$init) {
'PallazzoTools' => __DIR__ . '/inc/lib.files.alias.tools.php', return false;
]); }
dcCore::app()->__set('filealias', new filesAliases());
dcCore::app()->url->register( dcCore::app()->url->register(
'filesalias', 'filesalias',
'pub', 'pub',
'^pub/(.+)$', '^pub/(.+)$',
['urlFilesAlias','alias'] [UrlHandler::class, 'alias']
); );
return true;
}
}

83
src/UrlHandler.php Normal file
View file

@ -0,0 +1,83 @@
<?php
/**
* @brief filesAlias, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Osku and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\filesAlias;
use dcCore;
use dcMedia;
use dcUrlHandlers;
class UrlHandler extends dcUrlHandlers
{
public static function alias(string $args): void
{
$delete = false;
dcCore::app()->ctx->__set('filealias', Utils::getAlias($args));
if (dcCore::app()->ctx->__get('filealias')->isEmpty()) {
self::p404();
}
if (dcCore::app()->ctx->__get('filealias')->f('filesalias_disposable')) {
$delete = true;
}
if (dcCore::app()->ctx->__get('filealias')->f('filesalias_password')) {
# Check for match
if (!empty($_POST['filepassword']) && $_POST['filepassword'] == dcCore::app()->ctx->__get('filealias')->f('filesalias_password')) {
self::servefile(dcCore::app()->ctx->__get('filealias')->f('filesalias_destination'), $args, $delete);
} else {
self::serveDocument('file-password-form.html', 'text/html', false);
return;
}
} else {
self::servefile(dcCore::app()->ctx->__get('filealias')->f('filesalias_destination'), $args, $delete);
}
}
public static function servefile(string $target, string $alias, bool $delete = false): void
{
$media = Utils::getMediaId($target);
if (empty($media)) {
self::p404();
}
if (!(dcCore::app()->media instanceof dcMedia)) {
dcCore::app()->media = new dcMedia();
}
$file = dcCore::app()->media->getFile($media);
if (empty($file->file)) {
self::p404();
}
header('Content-type: ' . $file->type);
header('Content-Length: ' . $file->size);
header('Content-Disposition: attachment; filename="' . $file->basename . '"');
if (ob_get_length() > 0) {
ob_end_clean();
}
flush();
readfile($file->file);
if ($delete) {
Utils::deleteAlias($alias);
}
}
}

View file

@ -10,53 +10,48 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class filesAliases declare(strict_types=1);
{
protected $aliases;
public function __construct() namespace Dotclear\Plugin\filesAlias;
use dcCore;
use dcMedia;
use dcRecord;
use Exception;
class Utils
{ {
public static function getAliases(): dcRecord
{
return new dcRecord(dcCore::app()->con->select(
'SELECT filesalias_url, filesalias_destination, filesalias_password, filesalias_disposable ' .
'FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escapeStr(dcCore::app()->blog->id) . "' " .
'ORDER BY filesalias_url ASC '
));
} }
public function getAliases() public static function getAlias(string $url): dcRecord
{ {
if (is_array($this->aliases)) { return new dcRecord(dcCore::app()->con->select(
return $this->aliases; 'SELECT filesalias_url, filesalias_destination, filesalias_password, filesalias_disposable ' .
'FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escapeStr(dcCore::app()->blog->id) . "' " .
"AND filesalias_url = '" . dcCore::app()->con->escapeStr($url) . "' " .
'ORDER BY filesalias_url ASC '
));
} }
$this->aliases = []; public static function updateAliases(array $aliases): void
$sql = 'SELECT filesalias_url, filesalias_destination, filesalias_password, filesalias_disposable ' .
'FROM ' . dcCore::app()->prefix . initFilesAlias::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escape(dcCore::app()->blog->id) . "' " .
'ORDER BY filesalias_url ASC ';
$this->aliases = dcCore::app()->con->select($sql)->rows();
return $this->aliases;
}
public function getAlias($url)
{
$strReq = 'SELECT filesalias_url, filesalias_destination, filesalias_password, filesalias_disposable ' .
'FROM ' . dcCore::app()->prefix . initFilesAlias::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escape(dcCore::app()->blog->id) . "' " .
"AND filesalias_url = '" . dcCore::app()->con->escape($url) . "' " .
'ORDER BY filesalias_url ASC ';
$rs = dcCore::app()->con->select($strReq);
return $rs;
}
public function updateAliases($aliases)
{ {
dcCore::app()->con->begin(); dcCore::app()->con->begin();
try { try {
$this->deleteAliases(); self::deleteAliases();
foreach ($aliases as $k => $v) { foreach ($aliases as $k => $v) {
if (!empty($v['filesalias_url']) && !empty($v['filesalias_destination'])) { if (!empty($v['filesalias_url']) && !empty($v['filesalias_destination'])) {
$v['filesalias_disposable'] = isset($v['filesalias_disposable']) ? true : false; $v['filesalias_disposable'] = isset($v['filesalias_disposable']) ? true : false;
$this->createAlias($v['filesalias_url'], $v['filesalias_destination'], $v['filesalias_disposable'], $v['filesalias_password']); self::createAlias($v['filesalias_url'], $v['filesalias_destination'], $v['filesalias_disposable'], $v['filesalias_password']);
} }
} }
@ -68,7 +63,7 @@ class filesAliases
} }
} }
public function createAlias($url, $destination, $disposable = 0, $password = null) public static function createAlias(string $url, string $destination, bool $disposable = false, ?string $password = null): void
{ {
if (!$url) { if (!$url) {
throw new Exception(__('File URL is empty.')); throw new Exception(__('File URL is empty.'));
@ -78,49 +73,41 @@ class filesAliases
throw new Exception(__('File destination is empty.')); throw new Exception(__('File destination is empty.'));
} }
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . initFilesAlias::ALIAS_TABLE_NAME); $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ALIAS_TABLE_NAME);
$cur->blog_id = (string) dcCore::app()->blog->id; $cur->setField('blog_id', (string) dcCore::app()->blog->id);
$cur->filesalias_url = (string) $url; $cur->setField('filesalias_url', (string) $url);
$cur->filesalias_destination = (string) $destination; $cur->setField('filesalias_destination', (string) $destination);
$cur->filesalias_password = $password; $cur->setField('filesalias_password', $password);
$cur->filesalias_disposable = abs((int) $disposable); $cur->setField('filesalias_disposable', (int) $disposable);
$cur->insert(); $cur->insert();
} }
public function deleteAliases() public static function deleteAliases(): void
{ {
dcCore::app()->con->execute( dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . initFilesAlias::ALIAS_TABLE_NAME . ' ' . 'DELETE FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escape(dcCore::app()->blog->id) . "' " "WHERE blog_id = '" . dcCore::app()->con->escapeStr(dcCore::app()->blog->id) . "' "
); );
} }
public function deleteAlias($url) public static function deleteAlias(string $url): void
{ {
dcCore::app()->con->execute( dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . initFilesAlias::ALIAS_TABLE_NAME . ' ' . 'DELETE FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escape(dcCore::app()->blog->id) . "' " . "WHERE blog_id = '" . dcCore::app()->con->escapeStr(dcCore::app()->blog->id) . "' " .
"AND filesalias_url = '" . dcCore::app()->con->escape($url) . "' " "AND filesalias_url = '" . dcCore::app()->con->escapeStr($url) . "' "
); );
} }
}
class aliasMedia extends dcMedia public static function getMediaId(string $target): int
{
public function __construct()
{
}
public function getMediaId($target)
{ {
$strReq = 'SELECT media_id ' . $strReq = 'SELECT media_id ' .
'FROM ' . dcCore::app()->prefix . dcMedia::MEDIA_TABLE_NAME . ' ' . 'FROM ' . dcCore::app()->prefix . dcMedia::MEDIA_TABLE_NAME . ' ' .
//"WHERE media_path = '" . $this->path . "' " . "WHERE media_path = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->settings->get('system')->get('public_path')) . "' " .
"WHERE media_path = '" . dcCore::app()->con->escape(dcCore::app()->blog->settings->system->public_path) . "' " . "AND media_file = '" . dcCore::app()->con->escapeStr($target) . "' ";
"AND media_file = '" . dcCore::app()->con->escape($target) . "' ";
$rs = dcCore::app()->con->select($strReq); $rs = dcCore::app()->con->select($strReq);
return $rs->count() ? $rs->media_id : null; return $rs->count() ? (int) $rs->f('media_id') : 0;
} }
} }