Skip to content

Commit

Permalink
WIP Captcha module architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Nov 6, 2024
1 parent f2c89f6 commit 84c343c
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 133 deletions.
82 changes: 34 additions & 48 deletions htdocs/admin/security_captcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
}

$action = GETPOST('action', 'aZ09');

$handler = GETPOST('handler', 'aZ09');


/*
Expand All @@ -70,34 +70,13 @@
} else {
dol_print_error($db);
}
} elseif ($action == 'updateform') {
$res1 = 1;
$res2 = 1;
$res3 = 1;
$res4 = 1;
$res5 = 1;
if (GETPOSTISSET('MAIN_APPLICATION_TITLE')) {
$res1 = dolibarr_set_const($db, "MAIN_APPLICATION_TITLE", GETPOST("MAIN_APPLICATION_TITLE", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
}
if (GETPOSTISSET('MAIN_SESSION_TIMEOUT')) {
$res2 = dolibarr_set_const($db, "MAIN_SESSION_TIMEOUT", GETPOST("MAIN_SESSION_TIMEOUT", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
}
if (GETPOSTISSET('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT')) {
$res3 = dolibarr_set_const($db, "MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT", GETPOST("MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT", 'alphanohtml'), 'int', 0, '', $conf->entity);
}
if (GETPOSTISSET('MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS')) {
$res4 = dolibarr_set_const($db, "MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS", GETPOST("MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS", 'alphanohtml'), 'int', 0, '', $conf->entity);
}
if (GETPOSTISSET('MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS')) {
$res5 = dolibarr_set_const($db, "MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", GETPOST("MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", 'alphanohtml'), 'int', 0, '', $conf->entity);
}
if ($res1 && $res2 && $res3 && $res4 && $res5) {
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
} elseif ($action == 'setcaptchahandler') {
if (!dolibarr_set_const($db, 'MAIN_SECURITY_ENABLECAPTCHA_HANDLER', GETPOST("value", "aZ09"), 'chaine', 0, '', $conf->entity)) {
dol_print_error($db);
}
}



/*
* View
*/
Expand All @@ -112,28 +91,37 @@
print '<span class="opacitymedium">'.$langs->trans("CaptchaDesc")."</span><br>\n";
print "<br>\n";

$dirModCaptcha = array_merge(array('/core/modules/security/captcha'), is_array($conf->modules_parts['captcha']) ? $conf->modules_parts['captcha'] : array());
foreach ($conf->modules_parts['captcha'] as $mo) {
//Add more models
$dirModCaptcha[] = $mo.'core/modules/security/captcha';
}

// Load array with all captcha generation modules
$dir = DOL_DOCUMENT_ROOT."/core/modules/security/captcha";
clearstatcache();
$handle = opendir($dir);
$i = 1;
$arrayhandler = array();
if (is_resource($handle)) {
while (($file = readdir($handle)) !== false) {
$reg = array();
if (preg_match('/(modCaptcha[a-z]+)\.class\.php$/i', $file, $reg)) {
// Charging the numbering class
$classname = $reg[1];
require_once $dir.'/'.$file;

$obj = new $classname($db, $conf, $langs, $user);
'@phan-var-force ModeleCaptcha $obj';
$arrayhandler[$obj->id] = $obj;
$i++;

foreach ($dirModCaptcha as $dirroot) {
$dir = dol_buildpath($dirroot, 0);

$handle = @opendir($dir);

$i = 1;
if (is_resource($handle)) {
while (($file = readdir($handle)) !== false) {
$reg = array();
if (preg_match('/(modCaptcha[a-z]+)\.class\.php$/i', $file, $reg)) {
// Charging the numbering class
$classname = $reg[1];
require_once $dir.'/'.$file;

$obj = new $classname($db, $conf, $langs, $user);
'@phan-var-force ModeleCaptcha $obj';
$arrayhandler[$obj->id] = $obj;
$i++;
}
}
closedir($handle);
}
closedir($handle);
}
asort($arrayhandler);

Expand Down Expand Up @@ -215,13 +203,11 @@

if (function_exists("imagecreatefrompng")) {
if ($key != $selectedcaptcha) {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=enabledcaptchahandler&token='.newToken().'&handler=standard"><input type="checkbox"></a>';
print '<a href="'.$_SERVER['PHP_SELF'].'?action=setcaptchahandler&token='.newToken().'&value='.$key.'">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print '</a>';
} else {
print '<a href="'.$_SERVER['PHP_SELF'].'?action=disablecaptchahandler&token='.newToken().'&handler=standard"><input type="checkbox" checked="checked"';
if (count($arrayhandler) <= 1) {
print 'disabled="disabled"';
}
print '></a>';
print img_picto($langs->trans("Enabled"), 'switch_on');
}
} else {
$desc = $form->textwithpicto('', $langs->transnoentities("EnableGDLibraryDesc"), 1, 'warning');
Expand Down
7 changes: 6 additions & 1 deletion htdocs/admin/ticket_public.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,16 @@
print '<br><br>';


print load_fiche_titre($langs->trans("Emails"));
//print load_fiche_titre($langs->trans("Emails"));

print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';

print '<tr class="liste_titre"><td>'.$langs->trans("Emails").'</td>';
print '<td class="left">';
print '</td>';
print '</tr>';

// Activate email creation to user
print '<tr class="oddeven"><td>';
print $form->textwithpicto($langs->trans("TicketsDisableCustomerEmail"), $langs->trans("TicketsDisableEmailHelp"), 1, 'help');
Expand Down
2 changes: 2 additions & 0 deletions htdocs/core/class/conf.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,8 @@ public function setValues($db)
$newvalue = '/'.$modulename.'/core/'.$partname.'/';
} elseif (in_array($partname, array('models', 'theme', 'websitetemplates'))) {
$newvalue = '/'.$modulename.'/';
} elseif (in_array($partname, array('captcha'))) {
$newvalue = '/'.$modulename.'/core/modules/security/'.$partname.'/';
} elseif ($value == 1) {
$newvalue = '/'.$modulename.'/core/modules/'.$partname.'/'; // ex: partname = societe
} else { // $partname can be any other value like 'sms', ...
Expand Down
62 changes: 28 additions & 34 deletions htdocs/core/class/html.formticket.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -569,40 +569,6 @@ function groupticketchange() {
$doleditor->Create();
print '</td></tr>';

$captcha = '';
if ($public && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET')) {
print '<tr><td class="titlefield">';

require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$captcha = getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_HANDLER', 'standard');

$classfile = DOL_DOCUMENT_ROOT."/core/modules/security/captcha/modCaptcha".ucfirst($captcha).'.class.php';
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$captchaobj = null;
if (dol_is_file($classfile)) {
// Charging the numbering class
$classname = "modCaptcha".ucfirst($captcha);
require_once $classfile;

$captchaobj = new $classname($this->db, $conf, $langs, $user);
}

if (is_object($captchaobj) && method_exists($captchaobj, 'getCaptchaCodeForForm')) {
// TODO: get this code using a method of captcha
} else {
print '<label for="email"><span class="fieldrequired">'.$langs->trans("SecurityCode").'</span></label></td><td>';
print '<span class="span-icon-security inline-block">';
print '<input id="securitycode" placeholder="'.$langs->trans("SecurityCode").'" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" />';
print '</span>';
print '<span class="nowrap inline-block">';
print '<img class="inline-block valignmiddle" src="'.DOL_URL_ROOT.'/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />';
print '<a class="inline-block valignmiddle" href="" tabindex="4" data-role="button">'.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'</a>';
print '</span>';
}

print '</td></tr>';
}

// Categories
if (isModEnabled('category') && !$public) {
include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
Expand Down Expand Up @@ -819,6 +785,34 @@ function(response) {
}
}

// Show line with Captcha
$captcha = '';
if ($public && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET')) {
print '<tr><td class="titlefield"></td><td><br>';

require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$captcha = getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_HANDLER', 'standard');

$classfile = DOL_DOCUMENT_ROOT."/core/modules/security/captcha/modCaptcha".ucfirst($captcha).'.class.php';
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$captchaobj = null;
if (dol_is_file($classfile)) {
// Charging the numbering class
$classname = "modCaptcha".ucfirst($captcha);
require_once $classfile;

$captchaobj = new $classname($this->db, $conf, $langs, $user);
}

if (is_object($captchaobj) && method_exists($captchaobj, 'getCaptchaCodeForForm')) {
print $captchaobj->getCaptchaCodeForForm();
} else {
print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method getCaptchaCodeForForm()';
}

print '<br></td></tr>';
}

print '</table>';

if ($withdolfichehead) {
Expand Down
39 changes: 36 additions & 3 deletions htdocs/core/modules/security/captcha/modCaptchaStandard.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
* \brief File to manage captcha generation according to dolibarr native code
*/

require_once DOL_DOCUMENT_ROOT.'/core/modules/security/captcha/modules_captcha.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/security/generate/modGeneratePassStandard.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/security/captcha/modules_captcha.php';
require_once DOL_DOCUMENT_ROOT.'/core/modules/security/generate/modGeneratePassStandard.class.php';


/**
Expand All @@ -49,7 +49,7 @@ class modCaptchaStandard extends ModeleCaptcha
*/
public function __construct($db, $conf, $langs, $user)
{
$this->id = "standard";
$this->id = strtolower(preg_replace('/^modCaptcha/i', '', get_class()));

$this->db = $db;
$this->conf = $conf;
Expand Down Expand Up @@ -95,6 +95,39 @@ public function getExample()
return '<img class="inline-block valignmiddle" src="data:image/png;base64,' . base64_encode($image_data) . '" border="0" width="80" height="32" />';
}

/**
* Return the HTML content to output on a form that need the captcha
*
* @param string $php_self An URL for the a href link
* @return int 0 if KO, >0 if OK
*/
public function getCaptchaCodeForForm($php_self = '')
{
global $langs;

// TODO Replace the a link with a post of form.

$out .= '<!-- Captcha -->
<div class="trinputlogin">
<div class="tagtd tdinputlogin nowrap none valignmiddle">
<span class="fa fa-unlock"></span>
<span class="nofa span-icon-security inline-block">
<input id="securitycode" placeholder="'.$langs->trans("SecurityCode").'" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" autocomplete="off" />
</span>
<span class="nowrap inline-block">
<img class="inline-block valignmiddle" src="'.DOL_URL_ROOT.'/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />
<a class="inline-block valignmiddle" href="'.$php_self.'" tabindex="4" data-role="button">'.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'</a>
</span>
</div>
</div>
<!-- End code for Captcha -->'."\n";

return $out;
}



/**
* Validate a captcha
Expand Down
28 changes: 9 additions & 19 deletions htdocs/core/tpl/login.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
@phan-var-force int<0,1> $forgetpasslink
';


header('Cache-Control: Public, must-revalidate');

if (GETPOST('dol_hide_topmenu')) {
Expand All @@ -105,6 +104,13 @@
$conf->use_javascript_ajax = 1;
}

// $captcha is defined


/*
* View
*/

$php_self = empty($php_self) ? dol_escape_htmltag($_SERVER['PHP_SELF']) : $php_self;
if (!empty($_SERVER["QUERY_STRING"]) && dol_escape_htmltag($_SERVER["QUERY_STRING"])) {
$php_self .= '?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]);
Expand Down Expand Up @@ -313,25 +319,9 @@
}

if (is_object($captchaobj) && method_exists($captchaobj, 'getCaptchaCodeForForm')) {
// TODO: get this code using a method of captcha
print $captchaobj->getCaptchaCodeForForm($php_self);
} else {
?>
<!-- Captcha -->
<div class="trinputlogin">
<div class="tagtd none valignmiddle tdinputlogin nowrap">

<span class="fa fa-unlock"></span>
<span class="span-icon-security inline-block">
<input id="securitycode" placeholder="<?php echo $langs->trans("SecurityCode"); ?>" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" autocomplete="off" />
</span>
<span class="nowrap inline-block">
<img class="inline-block valignmiddle" src="<?php echo DOL_URL_ROOT ?>/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />
<a class="inline-block valignmiddle" href="<?php echo $php_self; ?>" tabindex="4" data-role="button"><?php echo img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"'); ?></a>
</span>

</div>
</div>
<?php
print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method getCaptchaCodeForForm()';
}
}

Expand Down
27 changes: 9 additions & 18 deletions htdocs/core/tpl/passwordforgotten.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@
$conf->use_javascript_ajax = 1;
}

// $captcha is defined


/*
* View
*/

$php_self = $_SERVER['PHP_SELF'];
$php_self .= dol_escape_htmltag($_SERVER["QUERY_STRING"]) ? '?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]) : '';
$php_self = str_replace('action=validatenewpassword', '', $php_self);
Expand Down Expand Up @@ -179,25 +186,9 @@
}

if (is_object($captchaobj) && method_exists($captchaobj, 'getCaptchaCodeForForm')) {
// TODO: get this code using a method of captcha
print $captchaobj->getCaptchaCodeForForm($php_self);
} else {
?>
<!-- Captcha -->
<div class="trinputlogin">
<div class="tagtd tdinputlogin nowrap none valignmiddle">

<span class="fa fa-unlock"></span>
<span class="nofa inline-block">
<input id="securitycode" placeholder="<?php echo $langs->trans("SecurityCode"); ?>" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" autocomplete="off" />
</span>
<span class="nowrap inline-block">
<img class="inline-block valignmiddle" src="<?php echo DOL_URL_ROOT ?>/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />
<a class="inline-block valignmiddle" href="<?php echo $php_self; ?>" tabindex="4"><?php echo img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"'); ?></a>
</span>

</div>
</div>
<?php
print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method getCaptchaCodeForForm()';
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ public function __construct($db)
// Set this to 1 if features of module are opened to external users
'moduleforexternal' => 0,
// Set this to 1 if the module provides a website template into doctemplates/websites/website_template-mytemplate
'websitetemplates' => 0
'websitetemplates' => 0,
// Set this to 1 if the module provides a captcha driver
'captcha' => 0
);

// Data directories to create when module is enabled.
Expand Down
Loading

0 comments on commit 84c343c

Please sign in to comment.