Pour le fun je me suis amusé à reprendre le petit utilitaire écrit il y a bien longtemps, en août 2008, par Oleksandr Syenchuk pour permettre de modifier le mot de passe d’un utilisateur qui aurait perdu le sien ; fichier nommé password.php et à placer dans le dossier admin de l’installation avant de se rendre à l’URL correspondante : https://ma.belle.admin.com/admin/password.php.
À l’époque le code était celui-ci :
<?php
# Script permettant de réinitialiser les mots de passe Dotclear
# Version Dotclear compatible : 2.0
#
# Script distribué sous licence GNU GPL version 2
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# Copyright (c) 2007-2008 Oleksandr Syenchuk
#
# Un bref historique :
# Version 3.2 (31/08/2008)
# * Compatibilité PostgreSQL, ça n'était pas bon avant
# * Correction des problèmes de régression bizarres
# Version 3 (17/06/2008)
# * Compatibilité PostgreSQL
# * Réécriture
# Version 2.1 (10/05/2008)
# Version 2 (16/09/2007)
# Ceci est l'adresse IP autorisée à réinitialiser le mot de passe
define('ALLOWIP', '::1');
# Ce fichier est à placer dans le dossier /admin
require dirname(__FILE__) . '/../inc/admin/prepend.php';
# Check if user is allowed to reset passwords
if ($_SERVER['REMOTE_ADDR'] !== ALLOWIP) {
http::head(412, 'Precondition Failed');
header('Content-Type: text/plain; charset=UTF-8');
echo "Vous ne pouvez pas accéder à cette page.\n\n" .
'Adresse IP autorisée : ' . ALLOWIP . "\n" .
'Votre adresse IP : ' . $_SERVER['REMOTE_ADDR'] . "\n\n" .
"Si vous êtes l'administrateur, modifiez ce fichier " .
"pour y définir votre propre adresse IP.\n";
exit;
}
header('Content-Type: text/html; charset=UTF-8');
/* Initialization
--------------------------------------------------------- */
$con = & $core->con;
# Loading locales for detected language
$dlang = http::getAcceptLanguage();
if ($dlang != 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/', $dlang)) {
l10n::lang($dlang);
l10n::set(dirname(__FILE__) . '/../locales/' . $dlang . '/main');
}
# Users combo
$users_combo = [];
$rs = $con->select('SELECT user_id FROM ' . DC_DBPREFIX . 'user');
while ($rs->fetch()) {
$id = html::escapeHTML($rs->user_id);
$users_combo[$id] = $id;
}
$user_id = '';
$make_super = false;
$show_password = false;
if (isset($_POST['act_reset'])) {
$user_id = (string) $_POST['user_id'];
$make_super = !empty($_POST['make_super']);
}
/* Perform requests
--------------------------------------------------------- */
if ($user_id !== '' && in_array($user_id, $users_combo)) {
$user_pwd = crypt::createPassword();
$cur = $con->openCursor(DC_DBPREFIX . 'user');
$cur->user_pwd = crypt::hmac(DC_MASTER_KEY, $user_pwd, DC_CRYPT_ALGO);
$cur->user_status = 1;
$cur->user_recover_key = null;
if ($make_super) {
$cur->user_super = 1;
}
$cur->update("WHERE user_id = '" . $con->escape($user_id) . "'");
$show_password = true;
}
/* DISPLAY
*
*/
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8;" />
<meta name="MSSmartTagsPreventParsing" content="TRUE" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="robots" content="noarchive,noindex,nofollow" />
<style type="text/css">
@import url(style/default.css);
</style>
<title><?php echo __('Password reset'); ?></title>
</head>
<body id="dotclear-admin" class="auth">
<div id="login-screen">
<h1><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></h1>
<?php if ($show_password): ?>
<fieldset><legend><?php echo __('Your new password'); ?></legend>
<p><strong><?php echo __('Username:'); ?></strong>
<?php echo html::escapeHTML($user_id); ?></p>
<p><strong><?php echo __('Password:'); ?></strong>
<?php echo html::escapeHTML($user_pwd); ?></p>
</fieldset>
<p><a href="auth.php"><?php echo __('Back to login screen'); ?></a></p>
<?php else: ?>
<form method="post" action="<?php echo http::getSelfURI(); ?>">
<fieldset><legend><?php echo __('Password reset'); ?></legend>
<p class="field"><label><?php echo __('User:'); ?>
<?php echo form::combo('user_id', $users_combo, $user_id); ?></label></p>
<p><label class="classic"><?php echo form::checkbox('make_super', 1); ?>
<?php echo __('Super administrator'); ?></label></p>
</fieldset>
<p><input type="submit" name="act_reset" value="<?php echo __('Change your password'); ?>"/></p>
</form>
<?php endif; ?>
</div>
</body></html>
<?php $con->close(); ?>
Aujourd’hui il est comme ça :
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* Script permettant de réinitialiser les mots de passe Dotclear
* Version Dotclear compatible : 2.24
*
* @copyright Oleksandr Syenchuk & Association Dotclear
* @copyright GPL-2.0-only
*/
// Ceci est l'adresse IP autorisée à réinitialiser le mot de passe
define('ALLOWIP', '::1');
// Ce fichier est à placer dans le dossier /admin
require dirname(__FILE__) . '/../inc/admin/prepend.php';
class adminPassword
{
/**
* Initializes the page.
*/
public static function init()
{
// Check if user is allowed to reset passwords
if ($_SERVER['REMOTE_ADDR'] !== ALLOWIP) {
http::head(412, 'Precondition Failed');
header('Content-Type: text/plain; charset=UTF-8');
$allow_ip = ALLOWIP;
$current_ip = $_SERVER['REMOTE_ADDR'];
echo <<<HTML_HEAD
Vous ne pouvez pas accéder à cette page.
Adresse IP autorisée : {$allow_ip}
Votre adresse IP : {$current_ip}
Si vous êtes l'administrateur, modifiez ce fichier pour y définir votre propre adresse IP.
HTML_HEAD;
exit;
}
header('Content-Type: text/html; charset=UTF-8');
// Loading locales for detected language
$dlang = http::getAcceptLanguage();
if ($dlang !== 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/', $dlang)) {
l10n::lang($dlang);
l10n::set(dirname(__FILE__) . '/../locales/' . $dlang . '/main');
}
// Users combo
$users_combo = [];
$rs = dcCore::app()->con->select('SELECT user_id FROM ' . DC_DBPREFIX . 'user');
while ($rs->fetch()) {
$id = html::escapeHTML($rs->user_id);
$users_combo[$id] = $id;
}
dcCore::app()->admin->users_combo = $users_combo;
}
/**
* Processes the request(s).
*/
public static function process()
{
dcCore::app()->admin->user_id = '';
dcCore::app()->admin->make_super = false;
dcCore::app()->admin->show_password = false;
if (isset($_POST['act_reset'])) {
dcCore::app()->admin->user_id = (string) $_POST['user_id'];
dcCore::app()->admin->make_super = !empty($_POST['make_super']);
}
if (dcCore::app()->admin->user_id !== '' && in_array(dcCore::app()->admin->user_id, dcCore::app()->admin->users_combo)) {
dcCore::app()->admin->user_pwd = crypt::createPassword();
$cur = dcCore::app()->con->openCursor(DC_DBPREFIX . 'user');
$cur->user_pwd = dcCore::app()->auth->crypt(dcCore::app()->admin->user_pwd);
$cur->user_status = 1;
$cur->user_recover_key = null;
if (dcCore::app()->admin->make_super) {
$cur->user_super = 1;
}
$sql = new dcUpdateStatement();
$sql->where('user_id = ' . $sql->quote(dcCore::app()->admin->user_id));
$sql->update($cur);
dcCore::app()->admin->show_password = true;
}
}
/**
* Renders the page.
*/
public static function render()
{
$head = <<<HTML_HEAD
<!DOCTYPE html>
<html lang="fr">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8;" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="robots" content="noarchive,noindex,nofollow" />
<link rel="stylesheet" href="style/default.css" type="text/css" media="screen" />
<title><?php echo %s; ?></title>
</head>
HTML_HEAD;
$body = <<<HTML_BODY
<body id="dotclear-admin" class="auth">
<div id="login-screen">
<h1><?php echo %s; ?></h1>
%s
</div>
</body>
</html>
HTML_BODY;
$form = '';
if (dcCore::app()->admin->show_password) {
$form = (new formFieldset())
->fields([
(new formLegend(__('Your new password'))),
(new formPara())
->items([
(new formText('strong'))->text(__('Username:')),
(new formText())->text(html::escapeHTML(dcCore::app()->admin->user_id)),
]),
(new formPara())
->items([
(new formText('strong'))->text(__('Password:')),
(new formText())->text(html::escapeHTML(dcCore::app()->admin->user_pwd)),
]),
])
->render() .
(new formPara())
->items([
(new formLink())
->href(dcCore::app()->adminurl->get('admin.auth'))
->text(__('Back to login screen')),
])
->render();
} else {
$form = (new formForm('reset'))
->action(http::getSelfURI())
->method('post')
->fields([
(new formFieldset())
->fields([
(new formLegend(__('Password reset'))),
(new formPara())
->class('field')
->items([
(new formSelect('user_id'))
->label(new formLabel(__('User:')))
->items(dcCore::app()->admin->users_combo)
->default(dcCore::app()->admin->user_id),
]),
(new formPara())
->items([
(new formCheckbox('make_super'))
->value(1)
->label((new formLabel(__('Super administrator'), formLabel::INSIDE_TEXT_AFTER))
->class('classic')),
]),
]),
(new formPara())
->items([
(new formSubmit('act_reset', __('Change your password'))),
]),
(new formHidden('xd_check', dcCore::app()->getNonce())),
])
->render();
}
echo sprintf($head, __('Password reset')) . sprintf($body, html::escapeHTML(DC_VENDOR_NAME), $form);
}
}
adminPassword::init();
adminPassword::process();
adminPassword::render();
Je le mets en pièce jointe si jamais vous en auriez besoin, mais pas avant la prochaine 2.24 de Dotclear ;-)
1 De Bernard -
Je suis un peu étonné de la syntaxe (chaine text) de type <<<X … X; Je ne connaissais pas cette Syntaxe Heredoc En tout c’est super (plus simple) !