Initial commit - Typo3 11.5.41
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\View\AudioPlayer;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
|
||||
* All rights reserved
|
||||
*
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||||
*
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
use SJBR\SrFreecap\Utility\AudioContentUtility;
|
||||
use SJBR\SrFreecap\Utility\EncryptionUtility;
|
||||
use SJBR\SrFreecap\Utility\LocalizationUtility;
|
||||
use TYPO3Fluid\Fluid\View\ViewInterface;
|
||||
|
||||
/**
|
||||
* Abstract class for rendering an audio version of the CAPTCHA
|
||||
*/
|
||||
class AbstractPlayFormat implements ViewInterface
|
||||
{
|
||||
/**
|
||||
* @var string Name of the extension this view helper belongs to
|
||||
*/
|
||||
protected $extensionName = 'SrFreecap';
|
||||
|
||||
/**
|
||||
* @var string Key of the extension this view helper belongs to
|
||||
*/
|
||||
protected $extensionKey = 'sr_freecap';
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Core\Domain\Model\Word
|
||||
*/
|
||||
protected $word;
|
||||
|
||||
/**
|
||||
* Add a variable to the view data collection.
|
||||
* Can be chained, so $this->view->assign(..., ...)->assign(..., ...); is possible
|
||||
*
|
||||
* @param string $key Key of variable
|
||||
* @param mixed $value Value of object
|
||||
* @return ViewInterface an instance of $this, to enable chaining
|
||||
*/
|
||||
public function assign($key, $value)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'word':
|
||||
$this->word = $value;
|
||||
break;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple variables to the view data collection
|
||||
*
|
||||
* @param array $values array in the format array(key1 => value1, key2 => value2)
|
||||
* @return ViewInterface an instance of $this, to enable chaining
|
||||
*/
|
||||
public function assignMultiple(array $values)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the audio version of captcha
|
||||
*
|
||||
* @return string The audio output to play
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
// Get the catcha word
|
||||
$word = $this->getWord();
|
||||
// Get the letter rensering files
|
||||
$letterRenderingFiles = $this->getLetterRenderingFiles($word);
|
||||
// Join the files
|
||||
$audioContent = AudioContentUtility::joinAudioFiles($letterRenderingFiles);
|
||||
// Output proper headers and echo audio content
|
||||
$this->sendHeaders($audioContent);
|
||||
// Send audio content
|
||||
$this->sendAudioContent($audioContent);
|
||||
// Return the audio content
|
||||
return $audioContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the word that was stored in session data
|
||||
* @return string the retrieved and decoded word
|
||||
*/
|
||||
protected function getWord()
|
||||
{
|
||||
// Get cypher from session data
|
||||
$cypher = $this->word->getWordCypher();
|
||||
// Decrypt the word
|
||||
$decryptedString = EncryptionUtility::decrypt($cypher);
|
||||
return implode('-', preg_split('//', $decryptedString, -1, PREG_SPLIT_NO_EMPTY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an array of letter rendering files in the specified format
|
||||
*
|
||||
* @param string $word: the word to be spelled and played
|
||||
* @param string $extension: the audio file extension being used
|
||||
* @return array array of file names
|
||||
*/
|
||||
protected function getLetterRenderingFiles($word, $extension = 'wav')
|
||||
{
|
||||
$letterRenderingFiles = [];
|
||||
// Split the word
|
||||
$letters = preg_split('//', $word, -1, PREG_SPLIT_NO_EMPTY);
|
||||
// Get the directory containing the wav files
|
||||
$voicesDirectory = LocalizationUtility::getVoicesDirectory();
|
||||
// Assemble the file names
|
||||
foreach ($letters as $letter){
|
||||
// Word lists are encoded in ISO-8859-1 (possibly in ISO-8859-2?)
|
||||
$file = $voicesDirectory . ((isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) && $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) ? utf8_encode($letter) : $letter) . '.' . $extension;
|
||||
if (is_file($file)) {
|
||||
$letterRenderingFiles[] = $file;
|
||||
}
|
||||
}
|
||||
return $letterRenderingFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends headers appropriate for audio content
|
||||
*
|
||||
* @param string $audioContent: the audio content that will be sent
|
||||
* @param string $mimeType: the audio mime type being used
|
||||
* @return void
|
||||
*/
|
||||
protected function sendHeaders($audioContent, $mimeType = 'x-wav')
|
||||
{
|
||||
header('Content-Type: audio/' . $mimeType);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Length: ' . strlen($audioContent));
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
header('Pragma: no-cache');
|
||||
header('Cache-Control: no-cache, no-store, must-revalidate');
|
||||
// Setting privacy policy header for IE in popup window
|
||||
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends audio content
|
||||
*
|
||||
* @param string $audioContent: the audio content that will be sent
|
||||
* @return void
|
||||
*/
|
||||
protected function sendAudioContent($audioContent)
|
||||
{
|
||||
echo $audioContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a given section.
|
||||
*
|
||||
* @param string $sectionName Name of section to render
|
||||
* @param array $variables The variables to use
|
||||
* @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
|
||||
* @return string rendered template for the section
|
||||
* @throws Exception\InvalidSectionException
|
||||
*/
|
||||
public function renderSection($sectionName, array $variables = [], $ignoreUnknown = false)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a partial.
|
||||
*
|
||||
* @param string $partialName
|
||||
* @param string $sectionName
|
||||
* @param array $variables
|
||||
* @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
|
||||
* @return string
|
||||
*/
|
||||
public function renderPartial($partialName, $sectionName, array $variables, $ignoreUnknown = false)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\View\AudioPlayer;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2013-2018 Stanislas Rolland <typo3(arobas)sjbr.ca>
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||||
*
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
|
||||
use SJBR\SrFreecap\Utility\AudioContentUtility;
|
||||
|
||||
/**
|
||||
* Renders a mp3 audio version of the CAPTCHA
|
||||
*/
|
||||
class PlayMp3 extends AbstractPlayFormat
|
||||
{
|
||||
/**
|
||||
* Renders the audio version of captcha
|
||||
*
|
||||
* @return string The audio output to play
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
// Get the catcha word
|
||||
$word = $this->getWord();
|
||||
// Get the letter rensering files
|
||||
$letterRenderingFiles = $this->getLetterRenderingFiles($word, 'mp3');
|
||||
// Join the files
|
||||
$audioContent = AudioContentUtility::joinAudioFiles($letterRenderingFiles, 'mp3');
|
||||
// Output proper headers
|
||||
$this->sendHeaders($audioContent, 'mpeg');
|
||||
// Send audio content
|
||||
$this->sendAudioContent($audioContent);
|
||||
// Return the audio content
|
||||
return $audioContent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\View\AudioPlayer;
|
||||
/***************************************************************
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-2013 Stanislas Rolland <typo3(arobas)sjbr.ca>
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||||
*
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
***************************************************************/
|
||||
/**
|
||||
* Renders a wav audio version of the CAPTCHA
|
||||
*
|
||||
* @author Stanislas Rolland <typo3(arobas)sjbr.ca>
|
||||
*/
|
||||
class PlayWav extends AbstractPlayFormat {
|
||||
}
|
||||
264
typo3conf/ext/sr_freecap/Classes/View/ImageGenerator/ShowPng.php
Normal file
264
typo3conf/ext/sr_freecap/Classes/View/ImageGenerator/ShowPng.php
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\View\ImageGenerator;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2005-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
|
||||
* All rights reserved
|
||||
*
|
||||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||||
* free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The GNU General Public License can be found at
|
||||
* http://www.gnu.org/copyleft/gpl.html.
|
||||
* A copy is found in the textfile GPL.txt and important notices to the license
|
||||
* from the author is found in LICENSE.txt distributed with these scripts.
|
||||
*
|
||||
*
|
||||
* This script is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This copyright notice MUST APPEAR in all copies of the script!
|
||||
*/
|
||||
/*
|
||||
* Integrates freeCap v1.4.1 into TYPO3 and generates the freeCap CAPTCHA image.
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* freeCap v1.4.1 Copyright 2005 Howard Yeend
|
||||
* www.puremango.co.uk
|
||||
*
|
||||
* This file is part of freeCap.
|
||||
*
|
||||
* freeCap is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* freeCap is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with freeCap; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
use SJBR\SrFreecap\Domain\Model\Word;
|
||||
use SJBR\SrFreecap\Domain\Repository\WordRepository;
|
||||
use SJBR\SrFreecap\Utility\EncryptionUtility;
|
||||
use SJBR\SrFreecap\Utility\ImageContentUtility;
|
||||
use SJBR\SrFreecap\Utility\RandomContentUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
use TYPO3Fluid\Fluid\View\ViewInterface;
|
||||
|
||||
/**
|
||||
* Renders a png image of the CAPTCHA
|
||||
*/
|
||||
class ShowPng implements ViewInterface
|
||||
{
|
||||
/**
|
||||
* @var string Name of the extension this view helper belongs to
|
||||
*/
|
||||
protected $extensionName = 'SrFreecap';
|
||||
|
||||
/**
|
||||
* @var string Name of the plugin this view helper belongs to
|
||||
*/
|
||||
protected $pluginName = 'ImageGenerator';
|
||||
|
||||
/**
|
||||
* @var string Key of the extension this view helper belongs to
|
||||
*/
|
||||
protected $extensionKey = 'sr_freecap';
|
||||
|
||||
/**
|
||||
* @var Word
|
||||
*/
|
||||
protected $word;
|
||||
|
||||
/**
|
||||
* @var array Configuration of this view
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Add a variable to the view data collection.
|
||||
* Can be chained, so $this->view->assign(..., ...)->assign(..., ...); is possible
|
||||
*
|
||||
* @param string $key Key of variable
|
||||
* @param mixed $value Value of object
|
||||
* @return SJBR\SrFreecap\View\ImageGenerator\ShowPng an instance of $this, to enable chaining
|
||||
* @api
|
||||
*/
|
||||
public function assign($key, $value)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'word':
|
||||
$this->word = $value;
|
||||
break;
|
||||
case 'settings':
|
||||
$this->settings = $value;
|
||||
break;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple variables to the view data collection
|
||||
*
|
||||
* @param array $values array in the format array(key1 => value1, key2 => value2)
|
||||
* @return SJBR\SrFreecap\View\ImageGenerator\ShowPng an instance of $this, to enable chaining
|
||||
* @api
|
||||
*/
|
||||
public function assignMultiple(array $values)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the captcha image
|
||||
*
|
||||
* @return string empty string (the image is sent here)
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
// Avoid Brute Force Attacks:
|
||||
if (!$this->word->getAttempts()) {
|
||||
$this->word->setAttempts(1);
|
||||
} else {
|
||||
$this->word->setAttempts($this->word->getAttempts() + 1);
|
||||
// if more than ($this->settings['maxAttempts']) refreshes, block further refreshes
|
||||
// can be negated by connecting with new session id
|
||||
// could get round this by storing num attempts in database against IP
|
||||
// could get round that by connecting with different IP (eg, using proxy servers)
|
||||
// in short, there's little point trying to avoid brute forcing
|
||||
// the best way to protect against BF attacks is to ensure the dictionary is not
|
||||
// accessible via the web or use random string option
|
||||
if ($this->word->getAttempts() > $this->settings['maxAttempts']) {
|
||||
$this->word->setWordHash('');
|
||||
$this->word->setWordCypher([]);
|
||||
$this->word->setHashFunction('');
|
||||
// Get an instance of the word repository
|
||||
$wordRepository = GeneralUtility::makeInstance(WordRepository::class);
|
||||
// Reset the word
|
||||
$wordRepository->setWord($this->word);
|
||||
$string = LocalizationUtility::translate('max_attempts', $this->extensionName);
|
||||
$font = 5;
|
||||
$width = imagefontwidth($font) * strlen($string);
|
||||
$height = imagefontheight($font);
|
||||
$image = ImageCreate($width+2, $height+20);
|
||||
$background = ImageColorAllocate($image, 255,255,255);
|
||||
ImageColorTransparent($image, $background);
|
||||
$red = ImageColorAllocate($image, 255, 0, 0);
|
||||
ImageString($image, $font, 1, 10, $string, $red);
|
||||
ImageContentUtility::sendImage($image, $this->settings['imageFormat']);
|
||||
ImageDestroy($image);
|
||||
// Return an empty string
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Get random word
|
||||
$word = RandomContentUtility::getRandomWord($this->settings['useWordsList'], $this->settings['wordsListLocation'], $this->settings['generateNumbers'] ?? 0, $this->settings['maxWordLength']);
|
||||
|
||||
// Save hash of word for comparison
|
||||
// using hash so that if there's an insecurity elsewhere (eg on the form processor),
|
||||
// an attacker could only get the hash
|
||||
// also, shared servers usually give all users access to the session files
|
||||
// echo `ls /tmp`; and echo `more /tmp/someone_elses_session_file`; usually work
|
||||
// so even if your site is 100% secure, someone else's site on your server might not be
|
||||
// hence, even if attackers can read the session file, they can't get the freeCap word
|
||||
// (though most hashes are easy to brute force for simple strings)
|
||||
$this->word->setWordHash(md5($word));
|
||||
|
||||
// We use a simple encrypt to prevent the session from being exposed
|
||||
if ($this->settings['accessibleOutput'] ?? false) {
|
||||
$this->word->setWordCypher(EncryptionUtility::encrypt($word));
|
||||
}
|
||||
|
||||
// Build the image
|
||||
$image = $this->buildImage($word, $this->settings['imageWidth'], $this->settings['imageHeight'], $this->settings['backgroundType']);
|
||||
|
||||
// Send the image
|
||||
ImageContentUtility::sendImage($image, $this->settings['imageFormat']);
|
||||
|
||||
// Cleanup
|
||||
ImageDestroy($image);
|
||||
|
||||
// Return an empty string
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the CAPTCHA image
|
||||
*
|
||||
* @param string $word
|
||||
* @return string GD image identifier of image
|
||||
*/
|
||||
protected function buildImage($word, $width, $height, $backgroundType)
|
||||
{
|
||||
$image = ImageCreate($width, $height);
|
||||
$background = ImageColorAllocate($image, 254, 254, 254);
|
||||
|
||||
// Write word on image
|
||||
$image = ImageContentUtility::writeWordOnImage($width, $height, $word, $this->settings['textColor'], $this->settings['textPosition'], $this->settings['colorMaximum'], $backgroundType, $this->settings['fontLocations'], $this->settings['fontWidths'], $this->settings['morphFactor']);
|
||||
|
||||
// Blur edges
|
||||
// Doesn't really add any security, but looks a lot nicer, and renders text a little easier to read
|
||||
// for humans (hopefully not for OCRs, but if you know better, feel free to disable this function)
|
||||
// (and if you do, let me know why)
|
||||
$image = ImageContentUtility::blurImage($image);
|
||||
|
||||
if ($this->settings['imageFormat'] != 'jpg' && $backgroundType == ImageContentUtility::BACKGROUND_TYPE_TRANSPARENT) {
|
||||
// Make background transparent
|
||||
ImageColorTransparent($image, $background);
|
||||
}
|
||||
|
||||
if ($backgroundType != ImageContentUtility::BACKGROUND_TYPE_TRANSPARENT) {
|
||||
// Get noisy background
|
||||
$image3 = ImageContentUtility::generateNoisyBackground($width, $height, $word, $backgroundType, $this->settings['backgroundImages'], $this->settings['backgroundMorph'], $this->settings['backgroundBlur']);
|
||||
// Merge with obfuscated background
|
||||
$image = ImageContentUtility::mergeCaptchaWithBackground($width, $height, $image, $image3, $backgroundType, $this->settings['mergeWithBackground']);
|
||||
ImageDestroy($image3);
|
||||
}
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a given section.
|
||||
*
|
||||
* @param string $sectionName Name of section to render
|
||||
* @param array $variables The variables to use
|
||||
* @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
|
||||
* @return string rendered template for the section
|
||||
* @throws Exception\InvalidSectionException
|
||||
*/
|
||||
public function renderSection($sectionName, array $variables = [], $ignoreUnknown = false)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a partial.
|
||||
*
|
||||
* @param string $partialName
|
||||
* @param string $sectionName
|
||||
* @param array $variables
|
||||
* @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
|
||||
* @return string
|
||||
*/
|
||||
public function renderPartial($partialName, $sectionName, array $variables, $ignoreUnknown = false)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user