Commit aa9e22f7 authored by sanjayk's avatar sanjayk Committed by Jakob Perry
Browse files

Issue #2501699 by ddrozdik, sanjayk, naveenvalecha, m1r1k, rahulrasgon,...

Issue #2501699 by ddrozdik, sanjayk, naveenvalecha, m1r1k, rahulrasgon, rpayanm, nmatja, yogeshchaugule8: Fix Image CAPTCHA settings form
parent 162bb5d1
......@@ -4,5 +4,5 @@ description: Provides an image based CAPTCHA.
package: Spam control
core_version_requirement: ^8.8 || ^9
dependencies:
- captcha
- captcha:captcha
configure: admin/config/people/captcha/image_captcha
......@@ -38,7 +38,7 @@ function image_captcha_install() {
$config = \Drupal::configFactory()->getEditable('image_captcha.settings');
$config->set('image_captcha_fonts', [
drupal_get_path('module', 'image_captcha') . '/fonts/Tesox/tesox.ttf',
drupal_get_path('module', 'image_captcha') . '/fonts/Tuffy/Tuffy.ttf',
hash('sha256', drupal_get_path('module', 'image_captcha') . '/fonts/Tesox/tesox.ttf'),
hash('sha256', drupal_get_path('module', 'image_captcha') . '/fonts/Tuffy/Tuffy.ttf'),
])->save(TRUE);
}
image_captcha.settings:
title: 'Image Captcha'
route_name: image_captcha.settings
description: 'Configure Image Captcha Settings.'
parent: captcha.settings
weight: -1
image_captcha.settings:
title: 'Image Captcha'
route_name: image_captcha.settings
base_route: captcha_settings
weight: -1
......@@ -8,6 +8,8 @@
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Drupal\Core\DrupalKernel;
use Drupal\Core\File;
define('IMAGE_CAPTCHA_ALLOWED_CHARACTERS', 'aAbBCdEeFfGHhijKLMmNPQRrSTtWXYZ23456789');
......@@ -47,6 +49,61 @@ function _image_captcha_get_enabled_fonts() {
}
}
/**
* Helper function to get font(s).
*
* @return string|array
* URI of file hash or List of font paths.
*/
function _image_captcha_get_font_uri($token = NULL) {
$fonts = [
'BUILTIN' => 'BUILTIN',
];
$available_fonts = _image_captcha_get_available_fonts_from_directories();
foreach ($available_fonts as $file_token => $font_info) {
$fonts[$file_token] = $font_info['uri'];
}
return ((!empty($token) && !empty($fonts[$token])) ? $fonts[$token] : $fonts);
}
/**
* Helper function to get fonts from the given directories.
*
* @param array|null $directories
* (Optional) an array of directories
* to recursively search through, if not given, the default
* directories will be used.
*
* @return array
* Fonts file objects (with fields 'name',
* 'basename' and 'filename'), keyed on the sha256 hash of the font
* path (to have an easy token that can be used in an url
* without en/decoding issues).
*/
function _image_captcha_get_available_fonts_from_directories($directories = NULL) {
// If no fonts directories are given: use the default.
if ($directories === NULL) {
$request = \Drupal::service('request_stack')->getCurrentRequest();
$directories = [
drupal_get_path('module', 'image_captcha') . '/fonts',
'sites/all/libraries/fonts',
DrupalKernel::findSitePath($request) . '/libraries/fonts',
];
}
// Collect the font information.
$fonts = [];
foreach ($directories as $directory) {
if (\Drupal::service('file_system')->prepareDirectory($directory)) {
$files = \Drupal::service('file_system')->scanDirectory($directory, '/\.[tT][tT][fF]$/');
foreach ($files as $filename => $font) {
$fonts[hash('sha256', $filename)] = (array) $font;
}
}
}
return $fonts;
}
/**
* Helper function for checking if the specified fonts are available.
*
......
......@@ -79,7 +79,7 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('image_captcha.settings');
// Add CSS and JS for theming and added usability on admin form.
$form['#attached']['library'][] = 'captcha_image/base';
$form['#attached']['library'][] = 'image_captcha/base';
// First some error checking.
$setup_status = _image_captcha_check_setup(FALSE);
......@@ -274,6 +274,10 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
}
$readable_fonts = [];
$available_fonts = _image_captcha_get_font_uri();
foreach ($fonts as $token) {
$fonts[$token] = $available_fonts[$token];
}
list($readable_fonts, $problem_fonts) = _image_captcha_check_fonts($fonts);
if (count($problem_fonts) > 0) {
$form_state->setErrorByName('image_captcha_fonts', $this->t('The following fonts are not readable: %fonts.', ['%fonts' => implode(', ', $problem_fonts)]));
......@@ -295,13 +299,21 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$imageSettings = $form_state->cleanValues()->getValues();
if (!isset($form['image_captcha_font_settings']['no_ttf_support'])) {
// Filter the image_captcha fonts array to pick out the selected ones.
$fonts = array_filter($form_state->getValue('image_captcha_fonts'));
$this->config('image_captcha.settings')
->set('image_captcha_fonts', $fonts)
->save();
$image_captcha_fonts = $form_state->getValue('image_captcha_fonts');
$imageSettings['image_captcha_fonts'] = array_filter($imageSettings['image_captcha_fonts']);
}
$config = $this->config('image_captcha.settings');
// Exclude few fields from config.
$exclude = ['image', 'captcha_sid', 'captcha_token', 'captcha_response'];
foreach ($imageSettings as $configName => $configValue) {
if (!in_array($configName, $exclude)) {
$config->set($configName, $configValue);
}
}
$config->save();
parent::SubmitForm($form, $form_state);
}
......@@ -339,7 +351,7 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
$available_fonts = [];
// List of folders to search through for TrueType fonts.
$fonts = $this->getAvailableFontsFromDirectories();
$fonts = _image_captcha_get_available_fonts_from_directories();
// Cache the list of previewable fonts. All the previews are done
// in separate requests, and we don't want to rescan the filesystem
// every time, so we cache the result.
......@@ -358,20 +370,16 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
'title' => $title,
'alt' => $title,
];
$available_fonts[$font['uri']] = '<img' . new Attribute($attributes) . ' />';
$available_fonts[$token] = '<img' . new Attribute($attributes) . ' />';
}
// Append the PHP built-in font at the end.
$title = $this->t('Preview of built-in font');
$attributes = [
'src' => Url::fromRoute('image_captcha.font_preview', ['token' => 'BUILTIN'])
$available_fonts['BUILTIN'] = $this->t('PHP built-in font: <img src="@font_preview_url" alt="@title" title="@title"', [
'@font_preview_url' => Url::fromRoute('image_captcha.font_preview', ['token' => 'BUILTIN'])
->toString(),
'alt' => $title,
'title' => $title,
];
$available_fonts['BUILTIN'] = (string) $this->t('PHP built-in font: font_preview', [
'font_preview' => '<img' . new Attribute($attributes) . ' />',
]);
'@title' => $title,
])->__toString();
$default_fonts = _image_captcha_get_enabled_fonts();
$conf_path = DrupalKernel::findSitePath($this->getRequest());
......@@ -426,38 +434,4 @@ class ImageCaptchaSettingsForm extends ConfigFormBase {
return $form;
}
/**
* Helper function to get fonts from the given directories.
*
* @param array|null $directories
* (Optional) an array of directories
* to recursively search through, if not given, the default
* directories will be used.
*
* @return array
* Fonts file objects (with fields 'name',
* 'basename' and 'filename'), keyed on the sha256 hash of the font
* path (to have an easy token that can be used in an url
* without en/decoding issues).
*/
protected function getAvailableFontsFromDirectories($directories = NULL) {
// If no fonts directories are given: use the default.
if ($directories === NULL) {
$directories = [
drupal_get_path('module', 'image_captcha') . '/fonts',
'sites/all/libraries/fonts',
DrupalKernel::findSitePath($this->getRequest()) . '/libraries/fonts',
];
}
// Collect the font information.
$fonts = [];
foreach ($directories as $directory) {
foreach ($this->fileSystem->scanDirectory($directory, '/\.[tT][tT][fF]$/') as $filename => $font) {
$fonts[hash('sha256', $filename)] = $font;
}
}
return $fonts;
}
}
......@@ -371,6 +371,7 @@ class CaptchaImageResponse extends Response {
// Pick a random font from the list.
$font = $fonts[array_rand($fonts)];
$font = _image_captcha_get_font_uri($font);
// Get character dimensions for TrueType fonts.
if ($font != 'BUILTIN') {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment