full rewrite for dotclear 2.24
This commit is contained in:
parent
f79f1c7046
commit
c5544b81b3
47
_admin.php
47
_admin.php
@ -1,27 +1,26 @@
|
||||
<?php
|
||||
# -- BEGIN LICENSE BLOCK ----------------------------------
|
||||
# This file is part of httpPassword, a plugin for Dotclear.
|
||||
#
|
||||
# Copyright (c) 2007-2009 Frederic PLE
|
||||
# dotclear@frederic.ple.name
|
||||
#
|
||||
# Licensed under the GPL version 2.0 license.
|
||||
# A copy of this license is available in LICENSE file or at
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# -- END LICENSE BLOCK ------------------------------------
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!defined('DC_CONTEXT_ADMIN')) { return; }
|
||||
|
||||
$_menu['Plugins']->addItem('httpPassword',
|
||||
'plugin.php?p=httpPassword',
|
||||
'index.php?pf=httpPassword/icon.png',
|
||||
preg_match('/plugin.php\?p=httpPassword(&.*)?$/',
|
||||
$_SERVER['REQUEST_URI']),
|
||||
$core->auth->check('usage,contentadmin',$core->blog->id)
|
||||
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
|
||||
__('Http password'),
|
||||
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)),
|
||||
urldecode(dcPage::getPF(basename(__DIR__) . '/icon.png')),
|
||||
preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/', $_SERVER['REQUEST_URI']),
|
||||
dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
|
||||
dcAuth::PERMISSION_USAGE,
|
||||
initHttpPassword::PERMISSION,
|
||||
]), dcCore::app()->blog->id)
|
||||
);
|
||||
|
||||
$core->auth->setPermissionType(
|
||||
'httpPassword',
|
||||
'Gestion de la protection du site httpPassword'
|
||||
);
|
||||
?>
|
||||
|
46
_define.php
46
_define.php
@ -1,21 +1,33 @@
|
||||
<?php
|
||||
# -- BEGIN LICENSE BLOCK ----------------------------------
|
||||
# This file is part of httpPassword, a plugin for Dotclear.
|
||||
#
|
||||
# Copyright (c) 2007-2009 Frederic PLE
|
||||
# dotclear@frederic.ple.name
|
||||
#
|
||||
# Licensed under the GPL version 2.0 license.
|
||||
# A copy of this license is available in LICENSE file or at
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# -- END LICENSE BLOCK ------------------------------------
|
||||
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->registerModule(
|
||||
/* Name */ "httpPassword",
|
||||
/* Description*/ "Manage .htpasswd file to make the blog private",
|
||||
/* Author */ "Frederic PLE <dotclear@frederic.ple.name>",
|
||||
/* Version */ '0.5.10',
|
||||
/* Permissions */ 'httpPassword'
|
||||
'Http password',
|
||||
'Manage .htpasswd file to make the blog private',
|
||||
'Frederic PLE and contributors',
|
||||
'1.0',
|
||||
[
|
||||
'requires' => [['core', '2.24']],
|
||||
'permissions' => dcCore::app()->auth->makePermissions([
|
||||
dcAuth::PERMISSION_USAGE,
|
||||
initHttpPassword::PERMISSION,
|
||||
]),
|
||||
'type' => 'plugin',
|
||||
'support' => 'https://github.com/JcDenis/' . basename(__DIR__),
|
||||
'details' => 'http://plugins.dotaddict.org/dc2/details/' . basename(__DIR__),
|
||||
'repository' => 'https://raw.githubusercontent.com/JcDenis/' . basename(__DIR__) . '/master/dcstore.xml',
|
||||
]
|
||||
);
|
||||
?>
|
||||
|
21
_init.php
Normal file
21
_init.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
class initHttpPassword
|
||||
{
|
||||
public const PERMISSION = 'httpPassword';
|
||||
public const FILE_PASSWORD = '.htpasswd';
|
||||
}
|
61
_install.php
61
_install.php
@ -1,36 +1,37 @@
|
||||
<?php
|
||||
# -- BEGIN LICENSE BLOCK ----------------------------------
|
||||
# This file is part of httpPassword, a plugin for Dotclear.
|
||||
#
|
||||
# Copyright (c) 2007-2009 Frederic PLE
|
||||
# dotclear@frederic.ple.name
|
||||
#
|
||||
# Licensed under the GPL version 2.0 license.
|
||||
# A copy of this license is available in LICENSE file or at
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# -- END LICENSE BLOCK ------------------------------------
|
||||
|
||||
if (!defined('DC_CONTEXT_ADMIN')) { return; }
|
||||
|
||||
$m_version = $core->plugins->moduleInfo('httpPassword','version');
|
||||
|
||||
$i_version = $core->getVersion('httpPassword');
|
||||
|
||||
if (version_compare($i_version,$m_version,'>=')) {
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Création du setting (s'il existe, il ne sera pas écrasé)
|
||||
$settings = new dcSettings($core,null);
|
||||
$settings->setNamespace('httppassword');
|
||||
$mydomain = preg_replace('/^.*\.([^.]+[^.])$/','$1',gethostbyaddr($_SERVER['SERVER_ADDR']));
|
||||
$defaultcrypt = '';
|
||||
try {
|
||||
// Check versions
|
||||
if (!dcCore::app()->newVersion(
|
||||
basename(__DIR__),
|
||||
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$settings->put('httppassword_active',false,'boolean','Activer',false,false);
|
||||
$settings->put('httppassword_crypt',$defaultcrypt,'string','Fonction de cryptage',false,false);
|
||||
$settings->put('httppassword_message','Zone Privee','String','Message personnalisable dans le popup d\'authentification',false,false);
|
||||
$settings->put('httppassword_trace',false,'boolean','Activation des traces (debug)',false,false);
|
||||
$settings->put('httppassword_debugmode',false,'boolean','Activation du mode Debug',false,false);
|
||||
// Set settings
|
||||
$s = dcCore::app()->blog->settings->get(basename(__DIR__));
|
||||
$s->put('active', false, 'boolean', 'Enable plugin', false, false);
|
||||
$s->put('crypt', 'crypt_md5', 'string', 'Crypt algorithm', false, false);
|
||||
$s->put('message', 'Private space', 'String', 'Personalized message on Authentication popup', false, false);
|
||||
|
||||
$core->setVersion('httpPassword',$m_version);
|
||||
?>
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
dcCore::app()->error->add($e->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
24
_prepend.php
Normal file
24
_prepend.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Clearbricks::lib()->autoload([
|
||||
'httpPassword' => implode(DIRECTORY_SEPARATOR, [__DIR__, 'inc', 'class.httppassword.php']),
|
||||
]);
|
||||
|
||||
dcCore::app()->auth->setPermissionType(
|
||||
initHttpPassword::PERMISSION,
|
||||
__('Manage http password blog protection')
|
||||
);
|
126
_public.php
126
_public.php
@ -1,101 +1,65 @@
|
||||
<?php
|
||||
# -- BEGIN LICENSE BLOCK ----------------------------------
|
||||
# This file is part of httpPassword, a plugin for Dotclear.
|
||||
#
|
||||
# Copyright (c) 2007-2009 Frederic PLE
|
||||
# dotclear@frederic.ple.name
|
||||
#
|
||||
# Licensed under the GPL version 2.0 license.
|
||||
# A copy of this license is available in LICENSE file or at
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# -- END LICENSE BLOCK ------------------------------------
|
||||
|
||||
if ($core->blog->settings->httppassword_active) {
|
||||
$core->addBehavior('publicPrepend',array('httpPassword','Check'));
|
||||
//$core->addBehavior('publicPrepend',array('httpPassword','LastLogin'));
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
class httpPassword {
|
||||
dcCore::app()->addBehavior('publicPrependV2', function (): void {
|
||||
$PHP_AUTH_USER = $PHP_AUTH_PW = '';
|
||||
|
||||
private static function __debuglog ($core,$trace) {
|
||||
static $fic = false;
|
||||
if (!$core->blog->settings->httppassword_trace)
|
||||
return;
|
||||
if ($fic === false)
|
||||
$fic = fopen($core->blog->public_path . '/.htpasswd.trc.txt','a');
|
||||
if ($fic !== false) {
|
||||
fprintf($fic,"%s - %s\n",date('Ymd-His'),$trace);
|
||||
}
|
||||
}
|
||||
|
||||
private static function __debugmode ($core) {
|
||||
$fic = fopen($core->blog->public_path . '/.debugmode','a');
|
||||
fprintf($fic,"\n%s\n%s\n", str_repeat('-', 30), date('Ymd-His'));
|
||||
fprintf($fic,".... \$_SERVER =\n%s\n",var_export($_SERVER,true));
|
||||
fprintf($fic,".... \$_ENV =\n%s\n",var_export($_ENV,true));
|
||||
fprintf($fic,".... Apache headers =\n%s\n",var_export(apache_request_headers(),true));
|
||||
}
|
||||
|
||||
private static function __HTTP401($core) {
|
||||
httpPassword::__debuglog($core,__FUNCTION__);
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Basic realm="'. utf8_decode(htmlspecialchars_decode($core->blog->settings->httppassword_message)) .'"');
|
||||
exit(0);
|
||||
}
|
||||
public static function Check($core) {
|
||||
httpPassword::__debuglog($core,'ENV = ' . var_export($_ENV,true));
|
||||
if ($core->blog->settings->httppassword_debugmode)
|
||||
httpPassword::__debugmode($core);
|
||||
if (isset($_SERVER['PHP_AUTH_USER']) and isset($_SERVER['PHP_AUTH_PW'])) {
|
||||
$PHP_AUTH_USER = $_SERVER['PHP_AUTH_USER'];
|
||||
$PHP_AUTH_PW = $_SERVER['PHP_AUTH_PW'];
|
||||
httpPassword::__debuglog($core,__FUNCTION__ . ' user identication found in $_SERVER');
|
||||
} else if (isset($_ENV['REMOTE_USER'])) {
|
||||
list($PHP_AUTH_PW,$PHP_AUTH_USER) = explode(' ',$_ENV['REMOTE_USER'],2);
|
||||
list($PHP_AUTH_USER,$PHP_AUTH_PW) = explode(':',base64_decode($PHP_AUTH_USER));
|
||||
httpPassword::__debuglog($core,__FUNCTION__ . ' user identication found in $_ENV');
|
||||
} elseif (isset($_ENV['REMOTE_USER'])) {
|
||||
[$PHP_AUTH_PW, $PHP_AUTH_USER] = explode(' ', $_ENV['REMOTE_USER'], 2);
|
||||
[$PHP_AUTH_USER, $PHP_AUTH_PW] = explode(':', base64_decode($PHP_AUTH_USER));
|
||||
}
|
||||
if ($PHP_AUTH_PW === '' or $PHP_AUTH_USER === '') {
|
||||
httpPassword::sendHttp401();
|
||||
}
|
||||
if (!isset($PHP_AUTH_USER) or !isset($PHP_AUTH_PW) or $PHP_AUTH_USER === '')
|
||||
httpPassword::__HTTP401($core);
|
||||
|
||||
httpPassword::__debuglog($core,'Testing user: '.$PHP_AUTH_USER.' pass: '.$PHP_AUTH_PW);
|
||||
|
||||
if (!is_file($core->blog->public_path . '/.htpasswd')) {
|
||||
if (!is_file(dcCore::app()->blog->public_path . DIRECTORY_SEPARATOR . initHttpPassword::FILE_PASSWORD)) {
|
||||
header('HTTP/1.0 500 Internal Server Error');
|
||||
echo "Le plugin httppassword présente une anomalie de configuration";
|
||||
echo 'httpPassword plugin is not well configured.';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$htpasswd = file($core->blog->public_path . '/.htpasswd',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
|
||||
$htpasswd = file(dcCore::app()->blog->public_path . DIRECTORY_SEPARATOR . initHttpPassword::FILE_PASSWORD, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
$authenticated = false;
|
||||
foreach($htpasswd as $ligne) {
|
||||
list($cur_user,$cur_pass) = explode(':',trim($ligne),2);
|
||||
httpPassword::__debuglog($core,'cur_user: '.$cur_user.' cur_pass: '.$cur_pass);
|
||||
if ($cur_user == $PHP_AUTH_USER and crypt($PHP_AUTH_PW,$cur_pass) == $cur_pass) {
|
||||
foreach ($htpasswd as $ligne) {
|
||||
[$cur_user, $cur_pass] = explode(':', trim($ligne), 2);
|
||||
if ($cur_user == $PHP_AUTH_USER and crypt($PHP_AUTH_PW, $cur_pass) == $cur_pass) {
|
||||
$authenticated = true;
|
||||
httpPassword::__debuglog($core,' OK');
|
||||
}
|
||||
if ($authenticated) break;
|
||||
if ($authenticated) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset($htpasswd);
|
||||
if (!$authenticated) httpPassword::__HTTP401($core);
|
||||
else httpPassword::LastLogin($core,$PHP_AUTH_USER);
|
||||
|
||||
return(true);
|
||||
if (!$authenticated) {
|
||||
httpPassword::sendHttp401();
|
||||
} else {
|
||||
$logs = dcCore::app()->log->getLogs(['log_table' => basename(__DIR__), 'log_msg' => $PHP_AUTH_USER]);
|
||||
if (!$logs->isEmpty()) {
|
||||
$ids = [];
|
||||
while ($logs->fetch()) {
|
||||
$ids[] = $logs->__get('log_id');
|
||||
}
|
||||
|
||||
public static function LastLogin($core,$user) {
|
||||
$fic = $core->blog->public_path . '/.lastlogin';
|
||||
|
||||
$httpPasswordLastLogin = array();
|
||||
if (is_file($fic))
|
||||
$httpPasswordLastLogin = unserialize(file_get_contents($fic));
|
||||
|
||||
$httpPasswordLastLogin[$user] = date('Y-m-d H:i');
|
||||
|
||||
file_put_contents($fic,serialize($httpPasswordLastLogin));
|
||||
|
||||
return(true);
|
||||
$logs = dcCore::app()->log->delLogs($ids);
|
||||
}
|
||||
}
|
||||
?>
|
||||
$cursor = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcLog::LOG_TABLE_NAME);
|
||||
$cursor->__set('log_table', basename(__DIR__));
|
||||
$cursor->__set('log_msg', $PHP_AUTH_USER);
|
||||
dcCore::app()->log->addLog($cursor);
|
||||
}
|
||||
});
|
||||
|
107
inc/class.httppassword.php
Normal file
107
inc/class.httppassword.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_RC_PATH')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
class httpPassword
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return basename(dirname(__DIR__));
|
||||
}
|
||||
|
||||
public static function crypt(?string $secret): string
|
||||
{
|
||||
switch (dcCore::app()->blog->settings->get(self::id())->get('crypt')) {
|
||||
case 'plaintext':
|
||||
$saltlen = -1;
|
||||
$salt = '';
|
||||
|
||||
break;
|
||||
case 'crypt_std_des':
|
||||
$saltlen = 2;
|
||||
$salt = '';
|
||||
|
||||
break;
|
||||
case 'crypt_ext_des':
|
||||
$saltlen = 9;
|
||||
$salt = '';
|
||||
|
||||
break;
|
||||
case 'crypt_md5':
|
||||
$saltlen = 12;
|
||||
$salt = '$1$';
|
||||
|
||||
break;
|
||||
case 'crypt_blowfish':
|
||||
$saltlen = 16;
|
||||
$salt = '$2$';
|
||||
|
||||
break;
|
||||
case 'crypt_sha256':
|
||||
$saltlen = 16;
|
||||
$salt = '$5$';
|
||||
|
||||
break;
|
||||
case 'crypt_sha512':
|
||||
$saltlen = 16;
|
||||
$salt = '$6$';
|
||||
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($saltlen > 0) {
|
||||
$salt .= substr(
|
||||
sha1(dcCore::app()->getNonce() . date('U')),
|
||||
2,
|
||||
$saltlen - strlen($salt)
|
||||
);
|
||||
$secret = crypt($secret, $salt);
|
||||
}
|
||||
|
||||
return($secret);
|
||||
}
|
||||
|
||||
public static function isWritable(): bool
|
||||
{
|
||||
if (false === ($fp = fopen(dcCore::app()->blog->public_path . DIRECTORY_SEPARATOR . initHttpPassword::FILE_PASSWORD, 'a+'))) {
|
||||
return false;
|
||||
}
|
||||
fclose($fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getCryptCombo(): array
|
||||
{
|
||||
return [
|
||||
__('No encryption') => 'plaintext',
|
||||
__('Crypt DES standard') => 'crypt_std_des',
|
||||
__('Crypt DES étendu') => 'crypt_ext_des',
|
||||
__('Crypt MD5') => 'crypt_md5',
|
||||
__('Crypt Blowfish') => 'crypt_blowfish',
|
||||
__('Crypt SHA256') => 'crypt_sha256',
|
||||
__('Crypt SHA512') => 'crypt_sha512',
|
||||
];
|
||||
}
|
||||
|
||||
public static function sendHttp401(): void
|
||||
{
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Basic realm="' . utf8_decode(htmlspecialchars_decode(dcCore::app()->blog->settings->get(self::id())->get('message'))) . '"');
|
||||
exit(0);
|
||||
}
|
||||
}
|
708
index.php
708
index.php
@ -1,475 +1,279 @@
|
||||
<?php
|
||||
# -- BEGIN LICENSE BLOCK ----------------------------------
|
||||
# This file is part of httpPassword, a plugin for Dotclear.
|
||||
#
|
||||
# Copyright (c) 2007-2009 Frederic PLE
|
||||
# dotclear@frederic.ple.name
|
||||
#
|
||||
# Licensed under the GPL version 2.0 license.
|
||||
# A copy of this license is available in LICENSE file or at
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# -- END LICENSE BLOCK ------------------------------------
|
||||
|
||||
function htpasswd_crypt(&$core,$secret)
|
||||
{
|
||||
switch ($core->blog->settings->httppassword_crypt) {
|
||||
case "plaintext":
|
||||
$saltlen = -1;
|
||||
break;
|
||||
case "crypt_std_des":
|
||||
$saltlen = 2;
|
||||
$salt = "";
|
||||
break;
|
||||
case "crypt_ext_des":
|
||||
$saltlen = 9;
|
||||
$salt = "";
|
||||
break;
|
||||
case "crypt_md5":
|
||||
$saltlen = 12;
|
||||
$salt = '$1$';
|
||||
break;
|
||||
case "crypt_blowfish":
|
||||
$saltlen = 16;
|
||||
$salt = '$2$';
|
||||
break;
|
||||
default:
|
||||
return(false);
|
||||
}
|
||||
|
||||
if ($saltlen > 0) {
|
||||
$salt .= substr(
|
||||
sha1($core->getNonce() . date('U')),
|
||||
2,
|
||||
$saltlen - strlen($salt)
|
||||
);
|
||||
$secret = crypt($secret,$salt);
|
||||
}
|
||||
|
||||
return($secret);
|
||||
/**
|
||||
* @brief httpPassword, a plugin for Dotclear 2
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Plugin
|
||||
*
|
||||
* @author Frederic PLE and contributors
|
||||
*
|
||||
* @copyright Jean-Christian Denis
|
||||
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
if (!defined('DC_CONTEXT_ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!defined('DC_CONTEXT_ADMIN')) { return; }
|
||||
$s = dcCore::app()->blog->settings->get(basename(__DIR__));
|
||||
$pwd_file = dcCore::app()->blog->public_path . DIRECTORY_SEPARATOR . initHttpPassword::FILE_PASSWORD;
|
||||
$action = $_POST['action'] ?? '';
|
||||
$redir = $_REQUEST['redir'] ?? '';
|
||||
$part = $_REQUEST['part'] ?? 'settings';
|
||||
$passwords = [];
|
||||
$writable = httpPassword::isWritable();
|
||||
$section_menu = [
|
||||
__('Settings') => 'settings',
|
||||
__('Logins history') => 'logins',
|
||||
__('Authorized users') => 'passwords',
|
||||
];
|
||||
|
||||
$crypt_algo = array(
|
||||
'plaintext' => 'Aucun',
|
||||
);
|
||||
if (CRYPT_STD_DES == 1)
|
||||
$crypt_algo['crypt_std_des'] = 'Crypt DES standard';
|
||||
|
||||
if (CRYPT_EXT_DES == 1)
|
||||
$crypt_algo['crypt_ext_des'] = 'Crypt DES étendu';
|
||||
|
||||
if (CRYPT_MD5 == 1)
|
||||
$crypt_algo['crypt_md5'] = 'Crypt MD5';
|
||||
|
||||
if (CRYPT_BLOWFISH == 1)
|
||||
$crypt_algo['crypt_blowfish'] = 'Crypt Blowfish';
|
||||
|
||||
$htpasswdfile = $core->blog->public_path . '/.htpasswd' ;
|
||||
$htp = file($htpasswdfile);
|
||||
if (!is_array($htp)) $htp = array();
|
||||
sort($htp);
|
||||
|
||||
$u = array();
|
||||
$v = array();
|
||||
|
||||
foreach($htp as $ligne) {
|
||||
list($login, $pwd) = explode(':', $ligne, 2);
|
||||
$u[trim($login)] = trim($pwd);
|
||||
if (!in_array($part, $section_menu) || !$writable) {
|
||||
$part = 'settings';
|
||||
}
|
||||
unset($ftp);
|
||||
|
||||
$txt = !empty($_POST['txt']) ? $_POST['txt'] : null;
|
||||
$action = !empty($_POST['httppasswordaction'])
|
||||
? $_POST['httppasswordaction']
|
||||
: null;
|
||||
|
||||
$core->blog->settings->setNamespace('httppassword');
|
||||
|
||||
$debugmodefile = $core->blog->public_path . '/.debugmode';
|
||||
|
||||
switch($action) {
|
||||
case "mod":
|
||||
// traitement des donnees du formulaire
|
||||
foreach(preg_split('/\n/m',$txt) as $ligne)
|
||||
{
|
||||
if (strpos($ligne, ':') === false)
|
||||
$ligne = trim($ligne) . ':';
|
||||
list($login, $pwd) = explode(':', $ligne);
|
||||
$v[trim($login)] = trim($pwd);
|
||||
}
|
||||
|
||||
// Rechercher les suppressions
|
||||
foreach(array_keys($u) as $login)
|
||||
{
|
||||
if (!isset($v[$login]))
|
||||
unset($u[$login]);
|
||||
}
|
||||
|
||||
// Rechercher les modifs + nouveaux
|
||||
foreach(array_keys($v) as $login)
|
||||
{
|
||||
if ($v[$login] != "") {
|
||||
$u[$login] = htpasswd_crypt(
|
||||
$core,
|
||||
$v[$login]
|
||||
if (empty($redir)) {
|
||||
$redir = dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => $part]);
|
||||
}
|
||||
if (!$writable) {
|
||||
dcAdminNotices::addWarningNotice(
|
||||
__('No write permissions on blogs directories.')
|
||||
);
|
||||
if ($u[$login] === false)
|
||||
unset($u[$login]);
|
||||
}
|
||||
}
|
||||
|
||||
$txt = "";
|
||||
foreach(array_keys($u) as $login)
|
||||
$txt .= $login.":".$u[$login]."\r\n";
|
||||
file_put_contents($htpasswdfile,$txt);
|
||||
break;
|
||||
|
||||
case "desactive":
|
||||
case "active":
|
||||
$active = !$core->blog->settings->httppassword_active;
|
||||
$core->blog->settings->put(
|
||||
'httppassword_active',
|
||||
$active,
|
||||
'boolean'
|
||||
);
|
||||
$core->blog->settings->httppassword_active = $active;
|
||||
break;
|
||||
|
||||
case "cryptfunc":
|
||||
$httppassword_crypt = trim($_POST['cryptage']);
|
||||
if (in_array($httppassword_crypt,array_keys($crypt_algo))) {
|
||||
$core->blog->settings->put(
|
||||
'httppassword_crypt',
|
||||
$httppassword_crypt,
|
||||
'string'
|
||||
);
|
||||
$core->blog->settings->httppassword_crypt =
|
||||
$httppassword_crypt;
|
||||
}
|
||||
break;
|
||||
|
||||
case "auth_message":
|
||||
$message = htmlspecialchars($_POST['auth_message']);
|
||||
$core->blog->settings->put(
|
||||
'httppassword_message',
|
||||
$message,
|
||||
'string'
|
||||
);
|
||||
$core->blog->settings->httppassword_message = $message;
|
||||
break;
|
||||
|
||||
case "debugmode":
|
||||
if ($_POST['debugmode'] === "true")
|
||||
$debugmode = true;
|
||||
else {
|
||||
$debugmode = false;
|
||||
if (is_file($debugmodefile))
|
||||
unlink($debugmodefile);
|
||||
}
|
||||
$core->blog->settings->put(
|
||||
'httppassword_debugmode',
|
||||
$debugmode,
|
||||
'boolean'
|
||||
);
|
||||
$core->blog->settings->httppassword_debugmode = $debugmode;
|
||||
break;
|
||||
}
|
||||
|
||||
$fic = $core->blog->public_path . '/.lastlogin';
|
||||
if (is_file($fic)) {
|
||||
$httpPasswordLastLogin = unserialize(file_get_contents($fic));
|
||||
if ($httpPasswordLastLogin === false) $httpPasswordLastLogin = array();
|
||||
} else
|
||||
$httpPasswordLastLogin = array();
|
||||
|
||||
$form_block=' style="display: none;"';
|
||||
if (strlen($core->blog->settings->httppassword_crypt) > 0) $form_block="";
|
||||
?><html>
|
||||
<head>
|
||||
<title>httpPassword</title>
|
||||
<?php echo dcPage::jsPageTabs($part); ?>
|
||||
<style type="text/css">
|
||||
.ns-name {
|
||||
background: #ccc;
|
||||
color: #000;
|
||||
padding-top: 0.3em;
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 1.1em;
|
||||
if ('passwords' == $part) {
|
||||
$lines = file($pwd_file);
|
||||
if (!is_array($lines)) {
|
||||
$lines = [];
|
||||
}
|
||||
.fp-code {
|
||||
border-left: #d0d0d0 solid 4px;
|
||||
margin-left: 40px;
|
||||
padding: 5px;
|
||||
sort($lines);
|
||||
foreach ($lines as $line) {
|
||||
[$login, $pwd] = explode(':', $line, 2);
|
||||
$passwords[trim($login)] = trim($pwd);
|
||||
}
|
||||
tr.row-odd { background: #bbbbbb; }
|
||||
tr.row-even { background: #dddddd; }
|
||||
h3 { border-top: #d0d0d0 dotted 2px; margin-top: 15px; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2><?php echo html::escapeHTML($core->blog->name); ?> › httpPasswd</h2>
|
||||
|
||||
<div id="local" class="multi-part" title="Gestion des accès restreints">
|
||||
<table><tr>
|
||||
<td>
|
||||
<div<?php echo $form_block; ?>>
|
||||
<h3>Activation du plugin</h3>
|
||||
<?php
|
||||
$canwrite = true;
|
||||
foreach(array('.htpasswd','.lastlogin') as $f) {
|
||||
$fp = fopen(dirname($htpasswdfile) . '/' . $f,'a+');
|
||||
if ($fp === false)
|
||||
$canwrite = false;
|
||||
else
|
||||
fclose($fp);
|
||||
unset($lines);
|
||||
}
|
||||
|
||||
$fichier_existe = is_file(dirname($htpasswdfile) . '/.htpasswd');
|
||||
$fichier_modifier = true;
|
||||
if ('savesettings' == $action) {
|
||||
$s->put('active', !empty($_POST['active']));
|
||||
$s->put('crypt', in_array((string) $_POST['crypt'], httpPassword::getCryptCombo()) ? $_POST['crypt'] : 'paintext');
|
||||
$s->put('message', (string) $_POST['message']);
|
||||
|
||||
if (!$canwrite) { ?>
|
||||
<p><strong>Pour utiliser cette extension, vous devez avoir les permissions
|
||||
pour écrire dans les fichiers :</strong></p>
|
||||
<ul>
|
||||
<li><tt><?php echo $htpasswdfile; ?></tt></li>
|
||||
<li><tt><?php echo dirname($htpasswdfile) . '/.lastlogin'; ?></tt></li>
|
||||
</ul>
|
||||
<?php } elseif ($core->blog->settings->httppassword_active) { ?>
|
||||
<p><strong>Protection ACTIVÉE</strong></p>
|
||||
<form method="post">
|
||||
Cliquer sur ce bouton pour désactiver la protection :
|
||||
<input type="submit" value="Désactiver" />
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce() .
|
||||
form::hidden(array('p'),'httpPassword') .
|
||||
form::hidden(array('httppasswordaction'),'desactive');
|
||||
?>
|
||||
</form>
|
||||
dcCore::app()->blog->triggerBlog();
|
||||
|
||||
<?php } else { ?>
|
||||
utilisateur valide !</strong></p>
|
||||
<form method="post">
|
||||
Cliquer sur ce bouton pour activer la protection :
|
||||
<input type="submit" value="Activer" />
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce().
|
||||
form::hidden(array('p'),'httpPassword').
|
||||
form::hidden(array('httppasswordaction'),'active');
|
||||
?>
|
||||
</form>
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Settings successfully updated.')
|
||||
);
|
||||
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Sécurité des mots de passe</h3>
|
||||
<p>Pour modifier la fonction de "cryptage".</p>
|
||||
<p><strong>Attention, le changement de
|
||||
cryptage s'appliquera individuellement à la prochaine modification
|
||||
de chacun des comptes (crétion ou changement de mot de passe)</strong></p>
|
||||
<form method="post">
|
||||
<?php
|
||||
foreach($crypt_algo as $algo_code => $algo_libelle) {
|
||||
echo '<input type="radio" name="cryptage" value="' . $algo_code . '" ';
|
||||
if ($core->blog->settings->httppassword_crypt == $algo_code)
|
||||
echo 'checked ';
|
||||
echo '/> ' . $algo_libelle . '<br />';
|
||||
} ?><input type="submit" value="Modifier" />
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce().
|
||||
form::hidden(array('p'),'httpPassword').
|
||||
form::hidden(array('httppasswordaction'),'cryptfunc');
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div<?php echo $form_block; ?>>
|
||||
<h3>Message d'authentification</h3>
|
||||
<form method="post">
|
||||
<p><input type="text" name="auth_message" size="50"
|
||||
value="<?php echo $core->blog->settings->httppassword_message; ?>" />
|
||||
<br />
|
||||
<input type="submit" value="Modifier"/>
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce().
|
||||
form::hidden(array('p'),'httpPassword').
|
||||
form::hidden(array('httppasswordaction'),'auth_message');
|
||||
?> </p>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div<?php echo $form_block; ?>>
|
||||
<form method="post">
|
||||
<p><textarea name="txt" rows="30" cols="30">
|
||||
<?php
|
||||
foreach(array_keys($u) as $login)
|
||||
echo "$login\n";
|
||||
?>
|
||||
</textarea><br />
|
||||
<input type="submit" value="Modifier" />
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce().
|
||||
form::hidden(array('p'),'httpPassword').
|
||||
form::hidden(array('httppasswordaction'),'mod');
|
||||
?> </p>
|
||||
</form>
|
||||
</div>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
|
||||
<div id="histo" class="multi-part"
|
||||
title="Historique des dernières connexions">
|
||||
<p>Nous sommes le <?php echo date('d-m-Y H:i'); ?></p>
|
||||
<table>
|
||||
<?php
|
||||
if (count($httpPasswordLastLogin)>0) {
|
||||
$i = 0;
|
||||
$logins = array_keys($httpPasswordLastLogin);
|
||||
sort($logins);
|
||||
foreach($logins as $login)
|
||||
echo '<tr style="row-' .
|
||||
(($i++ % 2 == 0) ? 'odd' : 'even') .
|
||||
'"><td>' . $login . '</td><td>' .
|
||||
$httpPasswordLastLogin[$login] .
|
||||
'</td></tr>' . "\n";
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
['part' => $part]
|
||||
);
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="aide" class="multi-part" title="Aide">
|
||||
<h3>Gestion des accès restreints</h3>
|
||||
<p>Ce plugin permet la gestion d'identifiants et de mots de
|
||||
passe pour limiter les accès à votre blog aux
|
||||
personnes que vous aurez choisies.</p>
|
||||
<p>Le formulaire de droite présente la liste des
|
||||
utilisateurs existants (sans leur mot de passe)</p>
|
||||
<h3>Ajout d'un utilisateur</h3>
|
||||
<p>Pour ajouter un utilisateur, ajouter une nouvelle ligne
|
||||
de la forme :</p>
|
||||
<p class="fp-code"><tt>login:motdepasse</tt></p>
|
||||
<h3>Modifier un mot de passe</h3>
|
||||
<p>Pour modifier un mot de passe d'un utilisateur, ajouter
|
||||
à la suite de son identifiant (sur la même ligne)
|
||||
le texte suivant :</p>
|
||||
<p class="fp-code"><tt>:motdepasse</tt></p>
|
||||
<h3>Suppression d'un utilisateur</h3>
|
||||
<p>Pour supprimer un utilisateur, supprimer la ligne de
|
||||
l'utilisateur.</p>
|
||||
</div>
|
||||
if ('savelogins' == $action) {
|
||||
$logs = dcCore::app()->log->getLogs(['log_table' => basename(__DIR__)]);
|
||||
if (!$logs->isEmpty()) {
|
||||
$ids = [];
|
||||
while ($logs->fetch()) {
|
||||
$ids[] = $logs->__get('log_id');
|
||||
}
|
||||
$logs = dcCore::app()->log->delLogs($ids);
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Logs successfully cleared.')
|
||||
);
|
||||
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
['part' => $part]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ('savepasswords' == $action) {
|
||||
$lines = [];
|
||||
if (!empty($_POST['login']) && !empty($_POST['password'])) {
|
||||
$lines[$_POST['login']] = httpPassword::crypt($_POST['password']);
|
||||
}
|
||||
foreach ($passwords as $l => $p) {
|
||||
// add login
|
||||
if (array_key_exists($l, $lines)) {
|
||||
continue;
|
||||
}
|
||||
// delete login
|
||||
if (!empty($_POST['delete']) && array_key_exists($l, $_POST['delete'])) {
|
||||
continue;
|
||||
}
|
||||
// change password
|
||||
if (!empty($_POST['edit']) && array_key_exists($l, $_POST['edit'])
|
||||
&& !empty($_POST['newpassword']) && array_key_exists($l, $_POST['newpassword'])
|
||||
) {
|
||||
$lines[$l] = httpPassword::crypt($_POST['newpassword'][$l]);
|
||||
} else {
|
||||
$lines[$l] = $p;
|
||||
}
|
||||
}
|
||||
|
||||
$contents = '';
|
||||
foreach ($lines as $l => $p) {
|
||||
$contents .= sprintf("%s:%s\r\n", $l, $p);
|
||||
}
|
||||
file_put_contents($pwd_file, $contents);
|
||||
|
||||
dcCore::app()->blog->triggerBlog();
|
||||
|
||||
dcAdminNotices::addSuccessNotice(
|
||||
__('Logins successfully updated.')
|
||||
);
|
||||
|
||||
dcCore::app()->adminurl->redirect(
|
||||
'admin.plugin.' . basename(__DIR__),
|
||||
['part' => $part]
|
||||
);
|
||||
}
|
||||
|
||||
<div id="moddebug" class="multi-part" title="Debug">
|
||||
<p>Le plugin a été développé pour
|
||||
fonctionner sur une installation "standard" de serveur Web
|
||||
(PHP en module Apache).</p>
|
||||
<p>Certains hébergeurs utilisent des installations de
|
||||
PHP en mode CGI, parfois assez spécifiques et
|
||||
sur lesquelles ce plugin ne fonctionnera pas</p>
|
||||
<p>Le mode debug permet de collecter des informations
|
||||
nécessaires au développeur pour adapter le plugin
|
||||
à des contextes particuliers.</p>
|
||||
<h3>Quand l'activer</h3>
|
||||
<ul>
|
||||
<li>Vous avez installé la dernière version du plugin
|
||||
(voir sur http://lab.dotclear.org/plugin/httpPassword)</li>
|
||||
<li>Vous avez activé le plugin</li>
|
||||
<li>Vous avez créé un compte</li>
|
||||
<li>Lorsque vous vous authentifiez sur le site, vous ne parvenez
|
||||
pas à accéder à la partie publique avec le
|
||||
compte que vous avez créé</li>
|
||||
</ul>
|
||||
<h3>MISE EN GARDE</h3>
|
||||
<p>le mode debug est
|
||||
dangeureux. Il est imperatif de le desactiver juste apres
|
||||
les tests.</p>
|
||||
<h3>Protocole à suivre</h3>
|
||||
<p>Le protocole est le suivant. Merci de le suivre pas à pas.</p>
|
||||
<ol>
|
||||
<li>Creer un compte "debug" dont le mot de passe est "test"</li>
|
||||
<li>Activer le plugin</li>
|
||||
<li>Activer le mode debug</li>
|
||||
<li>Faire un essai d'authentification</li>
|
||||
<li>Revenir sur cette page et copier le texte de la section "Resultats"
|
||||
dans un mail</li>
|
||||
<li>Joindre a ce mail le fichier .debugmode que vous trouverez
|
||||
dans le répertoire public du blog</li>
|
||||
<li>Envoyer le mail à dotclear@frederic.ple.name</li>
|
||||
<li>Desactiver le mode debug</li>
|
||||
<li>Supprimer le de compte "debug"</li>
|
||||
<li>Attendre patiemment la réponse du gentil
|
||||
développeur</li>
|
||||
</ol>
|
||||
<h3>Activer / Dédactiver le mode DEBUG</h3>
|
||||
<form method="post">
|
||||
<p><input type="radio" name="debugmode" value="false" <?php if ($core->blog->settings->httppassword_debugmode === false) echo 'checked="checked" '; ?>/>Mode normal</p>
|
||||
<p><input type="radio" name="debugmode" value="true" <?php if ($core->blog->settings->httppassword_debugmode === true) echo 'checked="checked" '; ?>/>Mode Debug</p>
|
||||
<p><input type="submit" value="Modifier"/></p>
|
||||
<?php
|
||||
echo
|
||||
$core->formNonce().
|
||||
form::hidden(array('p'),'httpPassword').
|
||||
form::hidden(array('httppasswordaction'),'debugmode');
|
||||
?> </p>
|
||||
</form>
|
||||
<?php
|
||||
if (is_file($debugmodefile)) {
|
||||
//if (true) {
|
||||
?>
|
||||
<h3>Résultats</h3>
|
||||
<div class="fp-code"><tt>
|
||||
<?php
|
||||
echo "* INFOS BLOG *<br />\n";
|
||||
echo "URL: " . $core->blog->url . "<br />\n";
|
||||
echo "IP: " . $_SERVER['SERVER_ADDR'] . "<br />\n";
|
||||
echo "DocumentRoot: " . $_SERVER['DOCUMENT_ROOT'] . "<br />\n";
|
||||
echo "DC2 version: " . $core->getVersion('core') . "<br />\n";
|
||||
echo "DC2 path: " ."-" . "<br />\n";
|
||||
echo "Plugins path: " . realpath(dirname(__FILE__) . '/..') . "<br />\n";
|
||||
echo "Public path: " . $core->blog->public_path . "<br />\n";
|
||||
echo "* INFOS HTTPPASSWD *<br />\n";
|
||||
echo "Version: " . $core->getVersion('httpPassword') . "<br />\n";
|
||||
//echo ".... \$_SERVER ....<br />" . str_replace("\n","<br />\n",var_export($_SERVER,true)) . "<br />\n";
|
||||
//echo ".... \$_ENV ....<br />" . str_replace("\n","<br />\n",var_export($_ENV,true)) . "<br />\n";
|
||||
//echo ".... HTTP Apache HEADERS ....<br />" . str_replace("\n","<br />\n",var_export(apache_request_headers(),true)) . "<br />\n";
|
||||
//echo str_replace("\n","<br />\n",htmlentities(file_get_contents($debugmodefile)));
|
||||
?>
|
||||
</tt></div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
'<html><head><title>' . __('Http password') . '</title>' .
|
||||
dcPage::jsPageTabs() .
|
||||
dcPage::jsModuleLoad(basename(__DIR__) . '/js/index.js') .
|
||||
'</head><body>' .
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
__('Http password') => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)),
|
||||
array_search($part, $section_menu) => '',
|
||||
]) .
|
||||
dcPage::notices() .
|
||||
|
||||
<div id="credits" class="multi-part" title="Crédits">
|
||||
<h3>Plugin</h3>
|
||||
<ul>
|
||||
<li><a href="http://frederic.ple.name/DC2-plugin-httpPassword">
|
||||
Plugin Dotclear httpPassword</a></li>
|
||||
<li>Ce plugin est distribué sous licence GPLv2</li>
|
||||
</ul>
|
||||
# Filters select menu list
|
||||
'<form method="get" action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)) . '" id="section_menu">' .
|
||||
'<p class="anchor-nav"><label for="part" class="classic">' . __('Select section:') . ' </label>' .
|
||||
form::combo('part', $section_menu, $part) . ' ' .
|
||||
'<input type="submit" value="' . __('Ok') . '" />' .
|
||||
form::hidden('p', basename(__DIR__)) . '</p>' .
|
||||
'</form>' .
|
||||
'<h3>' . array_search($part, $section_menu) . '</h3>';
|
||||
|
||||
<h3>Développeur</h3>
|
||||
<ul>
|
||||
<li>Frédéric PLÉ <dotclear@frederic.ple.name></li>
|
||||
</ul>
|
||||
<h3>Remerciements</h3>
|
||||
<ul>
|
||||
<li>Aux développeurs de Dotclear pour la grande qualité du code</li>
|
||||
<li>A Tomtom33, Moe, et les autres qui m'ont aidé sur le
|
||||
<a href="http://forum.dotclear.net/">forum</a></li>
|
||||
<li>A Pep de <a href="http://www.dotaddict.org/">Dotaddict</a></li>
|
||||
<li>Stephanie "piloue" pour ses tests, ses suggestions et sa patience</li>
|
||||
<li>Gabriel Recope pour ses tests et reports de bugs.</li>
|
||||
</ul>
|
||||
if ('settings' == $part) {
|
||||
echo '
|
||||
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'settings']) . '">
|
||||
|
||||
<div style="text-align: right; font-size: 0.8em; border-top: dashed 3px #d0d0d0; padding: 2px 10px 0 0;margin-top: 15px;">Plugin réalisé v.<?php echo $core->getVersion('httpPassword'); ?> par <a href="http://frederic.ple.name/" style="text-decoration: none; color: black;">Frédéric PLÉ</a>
|
||||
<dotclear@frederic.ple.name></div>
|
||||
</div>
|
||||
<p><label for="active">' .
|
||||
form::checkbox('active', '1', (bool) $s->get('active')) .
|
||||
__('Enable http password protection on this blog') . '</label></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<p><label for="crypt">' . __('Crypt algorithm:') . '</label> ' .
|
||||
form::combo('crypt', httpPassword::getCryptCombo(), (string) $s->get('crypt')) . '</p>
|
||||
<p class="form-note">' .
|
||||
__('Some web servers does not surpport plaintext (no) encryption.') . ' ' .
|
||||
__('If you change crypt algo, you must edit and resave each users passwords.') .
|
||||
'</p>
|
||||
|
||||
<p><label for="message">' . __('Authentication message:') . '</label>' .
|
||||
form::field('message', 60, 255, html::escapeHTML((string) $s->get('message'))) . '
|
||||
</p>
|
||||
|
||||
<div class="clear">
|
||||
<p>' .
|
||||
dcCore::app()->formNonce() .
|
||||
form::hidden(['action'], 'savesettings') .
|
||||
form::hidden(['part'], $part) . '
|
||||
<input type="submit" name="save" value="' . __('Save') . '" />
|
||||
</p></form>';
|
||||
}
|
||||
|
||||
if ('logins' == $part) {
|
||||
$logs = dcCore::app()->log->getLogs(['log_table' => basename(__DIR__)]);
|
||||
if ($logs->isEmpty()) {
|
||||
echo
|
||||
'<p>' . __('Logins history is empty.') . '</p>';
|
||||
} else {
|
||||
echo '
|
||||
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'logins']) . '">
|
||||
<p>' .
|
||||
dcCore::app()->formNonce() .
|
||||
form::hidden(['action'], 'savelogins') .
|
||||
form::hidden(['part'], $part) . '
|
||||
<input type="submit" name="save" value="' . __('Clear logs') . '" />
|
||||
</p></form>' .
|
||||
|
||||
'<div class="table-outer"><table>' .
|
||||
'<caption>' . sprintf(__('List of %s last logins.'), $logs->count()) . '</caption>' .
|
||||
'<thead><tr>' .
|
||||
'<th scope="col" class="first">' . __('Login') . '</th>' .
|
||||
'<th scope="col">' . __('Date') . '</th>' .
|
||||
'</tr></thead<tbody>';
|
||||
|
||||
while ($logs->fetch()) {
|
||||
echo
|
||||
'<tr class="line">' .
|
||||
'<td class="nowrap maximal">' . html::escapeHTML($logs->__get('log_msg')) . '</td>' .
|
||||
'<td class="nowrap count">' . html::escapeHTML(dt::dt2str(__('%Y-%m-%d %H:%M'), $logs->__get('log_dt'))) . '</td>' .
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
echo
|
||||
'</table></div>';
|
||||
}
|
||||
}
|
||||
|
||||
if ('passwords' == $part) {
|
||||
if (empty($passwords)) {
|
||||
echo
|
||||
'<p>' . __('Authorized users list is empty.') . '</p>';
|
||||
} else {
|
||||
echo
|
||||
'<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => $part]) . '">' .
|
||||
'<div class="table-outer"><table>' .
|
||||
'<caption>' . sprintf(__('List of %s authorized users.'), count($passwords)) . '</caption>' .
|
||||
'<thead><tr>' .
|
||||
'<th scope="col" class="first nowrap">' . __('Login') . '</th>' .
|
||||
'<th scope="col" class="first nowrap">' . __('New password') . '</th>' .
|
||||
'<th scope="col" class="nowrap">' . __('Action') . '</th>' .
|
||||
'</tr></thead<tbody>';
|
||||
|
||||
foreach ($passwords as $login => $pwd) {
|
||||
echo
|
||||
'<tr class="line">' .
|
||||
'<td class="nowrap maximal">' .
|
||||
html::escapeHTML($login) .
|
||||
'</td>' .
|
||||
'<td class="nowrap">' .
|
||||
form::field(['newpassword[' . html::escapeHTML($login) . ']'], 60, 255, '') .
|
||||
'</td>' .
|
||||
'<td class="nowrap">' .
|
||||
'<input type="submit" name="edit[' . html::escapeHTML($login) . ']" value="' . __('Change password') . '" /> ' .
|
||||
'<input type="submit" class="delete" name="delete[' . html::escapeHTML($login) . ']" value="' . __('Delete') . '" />' .
|
||||
'</td>' .
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
echo
|
||||
'</table></div>
|
||||
<p>' .
|
||||
dcCore::app()->formNonce() .
|
||||
form::hidden(['action'], 'savepasswords') .
|
||||
form::hidden(['part'], $part) . '
|
||||
</p></form>';
|
||||
}
|
||||
|
||||
echo '
|
||||
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => $part]) . '">
|
||||
<h3>' . __('Add a user') . '</h3>
|
||||
|
||||
<p><label for="login">' . __('Login:') . '</label>' .
|
||||
form::field('login', 60, 255, '') . '
|
||||
</p>
|
||||
|
||||
<p><label for="password">' . __('Password:') . '</label>' .
|
||||
form::field('password', 60, 255, '') . '
|
||||
</p>
|
||||
|
||||
<p>' .
|
||||
dcCore::app()->formNonce() .
|
||||
form::hidden(['action'], 'savepasswords') .
|
||||
form::hidden(['part'], $part) . '
|
||||
<input type="submit" name="add" value="' . __('Save') . '" />
|
||||
</p></form>';
|
||||
}
|
||||
|
||||
echo
|
||||
'</body></html>';
|
||||
|
13
js/index.js
Normal file
13
js/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*global $, dotclear */
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
$('#section_menu input[type=submit]').hide();
|
||||
$('#section_menu #part').on('change', function () {this.form.submit();});
|
||||
|
||||
$('.checkboxes-helpers').each(function () {
|
||||
dotclear.checkboxesHelpers(this, undefined, '#form-records td input[type=checkbox]', '#form-records #del-action');
|
||||
});
|
||||
$('#form-records td input[type=checkbox]').enableShiftClick();
|
||||
dotclear.condSubmit('#form-records td input[type=checkbox]', '#form-records #del-action');
|
||||
});
|
84
locales/fr/main.po
Normal file
84
locales/fr/main.po
Normal file
@ -0,0 +1,84 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: httpPassword 1.0\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: 2022-12-31T00:45:53+00:00\n"
|
||||
"Last-Translator: Jean-Christian Denis\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
msgid "Manage http password blog protection"
|
||||
msgstr "Gérer la protection du blog par mot de passe HTTP"
|
||||
|
||||
msgid "No encryption"
|
||||
msgstr "pas de cryptage"
|
||||
|
||||
msgid "Logins history"
|
||||
msgstr "Historique des logins"
|
||||
|
||||
msgid "Authorized users"
|
||||
msgstr "Utilisateurs autorisés"
|
||||
|
||||
msgid "No write permissions on blogs directories."
|
||||
msgstr "Aucun droit d'écriture sur le répertoire du blog."
|
||||
|
||||
msgid "Settings successfully updated."
|
||||
msgstr "Paramètres mis à jour."
|
||||
|
||||
msgid "Logs successfully cleared."
|
||||
msgstr "Logs effacé."
|
||||
|
||||
msgid "Logins successfully updated."
|
||||
msgstr "Logins mis à jour."
|
||||
|
||||
msgid "Select section:"
|
||||
msgstr "Sélectionner une section :"
|
||||
|
||||
msgid "Enable http password protection on this blog"
|
||||
msgstr "Activer la protection du blog par mot de passe http"
|
||||
|
||||
msgid "Crypt algorithm:"
|
||||
msgstr "Algorithme de cryptage :"
|
||||
|
||||
msgid "Some web servers does not surpport plaintext (no) encryption."
|
||||
msgstr "Certains serveurs web ne supportent pas le cryptage \"plaintext\"."
|
||||
|
||||
msgid "If you change crypt algo, you must edit and resave each users passwords."
|
||||
msgstr "Si vous changer l'algorithme de cryptage, vous devrez modifier et sauver tous les mots de passes."
|
||||
|
||||
msgid "Authentication message:"
|
||||
msgstr "Message d'authentification :"
|
||||
|
||||
msgid "Logins history is empty."
|
||||
msgstr "L'historique des logins est vide."
|
||||
|
||||
msgid "Clear logs"
|
||||
msgstr "Effacer les logs"
|
||||
|
||||
msgid "List of %s last logins."
|
||||
msgstr "Liste des %s derniers logins."
|
||||
|
||||
msgid "Authorized users list is empty."
|
||||
msgstr "La listes des utilisateurs autorisés est vide."
|
||||
|
||||
msgid "List of %s authorized users."
|
||||
msgstr "Liste des %s utilisateurs autorisés."
|
||||
|
||||
msgid "New password"
|
||||
msgstr "Nouveau mot de passe"
|
||||
|
||||
msgid "Change password"
|
||||
msgstr "Modifier le mot de passe"
|
||||
|
||||
msgid "Add a user"
|
||||
msgstr "Ajouter un utilisateur"
|
||||
|
||||
msgid "Login:"
|
||||
msgstr "Identifiant :"
|
||||
|
||||
msgid "Manage .htpasswd file to make the blog private"
|
||||
msgstr "Gestion du fichier .htpasswd pour rendre le blog privé."
|
||||
|
Loading…
Reference in New Issue
Block a user