Initial commit - Typo3 11.5.41
This commit is contained in:
128
typo3conf/ext/sr_freecap/Classes/Utility/AudioContentUtility.php
Normal file
128
typo3conf/ext/sr_freecap/Classes/Utility/AudioContentUtility.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-2020 Stanislas Rolland <typo32020(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!
|
||||
*/
|
||||
/**
|
||||
* Utility dealing with audio content
|
||||
*/
|
||||
class AudioContentUtility
|
||||
{
|
||||
/**
|
||||
* Joins multiple audio files
|
||||
*
|
||||
* @param array $files: the array of audio files
|
||||
* @param string $format: the audio format
|
||||
* @return string the contents of joined audio file
|
||||
*/
|
||||
public static function joinAudioFiles($files, $format = 'wav') {
|
||||
switch ($format) {
|
||||
case 'mp3':
|
||||
return self::joinMp3Files($files);
|
||||
break;
|
||||
case 'wav':
|
||||
default:
|
||||
return self::joinWavFiles($files);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins multiple wav files
|
||||
*
|
||||
* All wave files need to have the same format and need to be uncompressed.
|
||||
* The headers of the last file will be used (with recalculated datasize
|
||||
* of course)
|
||||
*
|
||||
* @link http://ccrma.stanford.edu/CCRMA/Courses/422/projects/WaveFormat/
|
||||
* @link http://www.thescripts.com/forum/thread3770.html
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Andreas Gohr <gohr@cosmocode.de>
|
||||
*
|
||||
* @param array $wavs: the array of wav files
|
||||
* @return string the contents of joined wav file
|
||||
*/
|
||||
protected static function joinWavFiles($wavs)
|
||||
{
|
||||
$fields = join('/', array(
|
||||
'H8Format',
|
||||
'H8Subchunk1ID',
|
||||
'VSubchunk1Size',
|
||||
'vAudioFormat',
|
||||
'vNumChannels',
|
||||
'VSampleRate',
|
||||
'VByteRate',
|
||||
'vBlockAlign',
|
||||
'vBitsPerSample'
|
||||
));
|
||||
$data = '';
|
||||
foreach ($wavs as $wav){
|
||||
$fp = fopen($wav, 'rb');
|
||||
// Read ChunkID
|
||||
$headerPart1 = fread($fp, 4);
|
||||
// Read ChunkSize
|
||||
$headerPart2 = fread($fp, 4);
|
||||
// Read following fields
|
||||
$headerPart3 = fread($fp, 28);
|
||||
$info = unpack($fields, $headerPart3);
|
||||
// Read optional extra stuff
|
||||
// We will not use this since AudioFormat of all our sound files is PCM
|
||||
if ($info['Subchunk1Size'] > 16) {
|
||||
$headerPart3 .= fread($fp, ($info['Subchunk1Size']-16));
|
||||
}
|
||||
// Read SubChunk2ID
|
||||
$headerPart3 .= fread($fp, 4);
|
||||
// Read Subchunk2Size
|
||||
$size = unpack('VSubChunk2Size', fread($fp, 4));
|
||||
$size = $size['SubChunk2Size'];
|
||||
// Read data
|
||||
$data .= fread($fp, $size);
|
||||
fclose($fp);
|
||||
}
|
||||
return $headerPart1 . pack('V', 36 + strlen($data)) . $headerPart3 . pack('V', strlen($data)) . $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins multiple mp3 files
|
||||
*
|
||||
* All mp3 files need to have the same format and need to be uncompressed.
|
||||
* The headers of the last file will be used (with recalculated datasize
|
||||
* of course)
|
||||
*
|
||||
* @link http://www.theblog.ca/merge-mp3s-php
|
||||
* @param array $files: the array of mp3 files
|
||||
* @return string the contents of joined mp3 file
|
||||
*/
|
||||
protected static function joinMp3Files($files)
|
||||
{
|
||||
$data = '';
|
||||
foreach ($files as $file) {
|
||||
$mp3 = new Mp3ContentUtility($file);
|
||||
$data .= $mp3->striptags();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-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!
|
||||
*/
|
||||
|
||||
class EncryptionUtility
|
||||
{
|
||||
/**
|
||||
* Salt
|
||||
*/
|
||||
const SALT = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
|
||||
|
||||
/**
|
||||
* Encrypts a string
|
||||
*
|
||||
* @param array $string: the string to be encrypted
|
||||
* @return array an array with the string as the first element and the initialization vector as the second element
|
||||
*/
|
||||
public static function encrypt($string)
|
||||
{
|
||||
if (in_array('openssl', get_loaded_extensions())) {
|
||||
$encryptionAlgorithm = strtolower($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['encryptionAlgorithm'] ?? 'aes-256-cbc');
|
||||
$availableAlgorithms = openssl_get_cipher_methods(true);
|
||||
if (in_array($encryptionAlgorithm, $availableAlgorithms)) {
|
||||
$key = md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] ?? 0, true);
|
||||
$iv_size = openssl_cipher_iv_length($encryptionAlgorithm);
|
||||
$salt = (isset($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['salt']) && trim($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['salt'])) ? trim($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['salt']) : self::SALT;
|
||||
$hash = hash('sha256', $salt . $key . $salt);
|
||||
$iv = substr($hash, strlen($hash) - $iv_size);
|
||||
$key = substr($hash, 0, 32);
|
||||
$string = openssl_encrypt($string, $encryptionAlgorithm, $key, OPENSSL_RAW_DATA, $iv);
|
||||
$cypher = [base64_encode($string), base64_encode($iv)];
|
||||
} else {
|
||||
$cypher = [base64_encode($string)];
|
||||
}
|
||||
} else {
|
||||
$cypher = [base64_encode($string)];
|
||||
}
|
||||
return $cypher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a string
|
||||
*
|
||||
* @param array $cypher: an array as returned by encrypt()
|
||||
* @return string the decrypted string
|
||||
*/
|
||||
public static function decrypt($cypher)
|
||||
{
|
||||
if (in_array('openssl', get_loaded_extensions())) {
|
||||
$encryptionAlgorithm = strtolower($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['encryptionAlgorithm'] ?? 'aes-256-cbc');
|
||||
$availableAlgorithms = openssl_get_cipher_methods(true);
|
||||
if (in_array($encryptionAlgorithm, $availableAlgorithms)) {
|
||||
$key = md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] ?? 0, true);
|
||||
$salt = isset($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['salt']) ? trim($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['sr_freecap']['salt']) : self::SALT;
|
||||
$hash = hash('sha256', $salt . $key . $salt);
|
||||
$key = substr($hash, 0, 32);
|
||||
$string = trim(openssl_decrypt(base64_decode($cypher[0]), $encryptionAlgorithm, $key, OPENSSL_RAW_DATA, base64_decode($cypher[1])));
|
||||
} else {
|
||||
$string = base64_decode($cypher[0]);
|
||||
}
|
||||
} else {
|
||||
$string = base64_decode($cypher[0]);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
146
typo3conf/ext/sr_freecap/Classes/Utility/FontMakingUtility.php
Normal file
146
typo3conf/ext/sr_freecap/Classes/Utility/FontMakingUtility.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-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!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Utility for making GD fonts
|
||||
*/
|
||||
class FontMakingUtility
|
||||
{
|
||||
/**
|
||||
* Returns an image displaying a list of characters with specified font file and character size
|
||||
*
|
||||
* @param string $characters: text to display on the image
|
||||
* @param string $font: specified True Type font file name
|
||||
* @param integer $width: width of each character
|
||||
* @param string $height: height of the image
|
||||
* @return array image file info array
|
||||
*/
|
||||
public static function makeFontImage($characters, $font, $width = 34, $height = 50)
|
||||
{
|
||||
$size = intval($height * .8);
|
||||
$vertOffset = intval($height * .7);
|
||||
$color = '#000000';
|
||||
$bgColor = 'white';
|
||||
$align = 'left';
|
||||
|
||||
$charactersArray = explode(',', $characters);
|
||||
$charactersCount = count($charactersArray);
|
||||
|
||||
$gifObjArray = array();
|
||||
$gifObjArray['backColor'] = $bgColor;
|
||||
$gifObjArray['transparentBackground'] = 0;
|
||||
$gifObjArray['reduceColors'] = '';
|
||||
$gifObjArray['maxWidth'] = ($charactersCount * $width) + 1;
|
||||
$gifObjArray['XY'] = ($charactersCount * $width) . ',' . $height;
|
||||
|
||||
for ($ic = 1; $ic < $charactersCount+1; $ic++) {
|
||||
$gifObjArray[$ic . '0'] = 'TEXT';
|
||||
$gifObjArray[$ic . '0.']['text'] = $charactersArray[$ic-1];
|
||||
$bbox = imagettfbbox($size, 0, GeneralUtility::getFileAbsFileName($font), $charactersArray[$ic-1]);
|
||||
$hOffset = intval(($width - ($bbox[4] - $bbox[6]))/2);
|
||||
$vOffset = intval(($width - ($bbox[7] - $bbox[1]))/2);
|
||||
|
||||
$gifObjArray[$ic . '0.']['niceText'] = 0;
|
||||
$gifObjArray[$ic . '0.']['antiAlias'] = 1;
|
||||
$gifObjArray[$ic . '0.']['align'] = $align;
|
||||
$gifObjArray[$ic . '0.']['fontSize'] = $size;
|
||||
$gifObjArray[$ic . '0.']['fontFile'] = '../' . $font;
|
||||
$gifObjArray[$ic . '0.']['fontColor'] = $color;
|
||||
$gifObjArray[$ic . '0.']['maxWidth'] = $width;
|
||||
$gifObjArray[$ic . '0.']['offset'] = (($ic-1) * $width + $hOffset) . ',' . $vertOffset;
|
||||
}
|
||||
$gifCreator = GeneralUtility::makeInstance(GifBuilderUtility::class);
|
||||
if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] ?? false) {
|
||||
$gifCreator->start($gifObjArray, []);
|
||||
return $gifCreator->gifBuild();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************\
|
||||
*
|
||||
* GD Fontmaker Copyright 2005 Howard Yeend
|
||||
* www.puremango.co.uk
|
||||
*
|
||||
* This file is part of GD Fontmaker.
|
||||
*
|
||||
* GD Fontmaker 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.
|
||||
*
|
||||
* GD Fontmaker 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 GD Fontmaker; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
\************************************************************/
|
||||
public static function makeFont($image, $numchars, $startchar, $pixelwidth, $pixelheight, $endianness = 0)
|
||||
{
|
||||
$startchar = ord($startchar);
|
||||
// encode this at start of font
|
||||
if ($endianness) {
|
||||
// big-endian
|
||||
$fontdata = chr(0).chr(0).chr(0).chr($numchars).chr(0).chr(0).chr(0).chr($startchar).chr(0).chr(0).chr(0).chr($pixelwidth).chr(0).chr(0).chr(0).chr($pixelheight);
|
||||
} else {
|
||||
// little-endian
|
||||
$fontdata = chr($numchars).chr(0).chr(0).chr(0).chr($startchar).chr(0).chr(0).chr(0).chr($pixelwidth).chr(0).chr(0).chr(0).chr($pixelheight).chr(0).chr(0).chr(0);
|
||||
}
|
||||
// loop through each pixel of each character of the PNG
|
||||
// (we know the dimensions of the characters because the user told us what they were)
|
||||
$y = 0;
|
||||
$x = 0;
|
||||
$start_x = 0;
|
||||
for ($c = 0; $c < $numchars*$pixelwidth; $c += $pixelwidth) {
|
||||
for ($y = 0; $y < $pixelheight; $y++) {
|
||||
for ($x = $c; $x < $c+$pixelwidth; $x++) {
|
||||
// get colour of this pixel
|
||||
$rgb = ImageColorAt($image, $x, $y);
|
||||
if ($rgb == 0) {
|
||||
// it's black; font data
|
||||
$fontdata .= chr(255);
|
||||
} else {
|
||||
// it's not black; background
|
||||
$fontdata .= chr(0);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fontdata;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-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 TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
use TYPO3\CMS\Frontend\Imaging\GifBuilder;
|
||||
|
||||
/**
|
||||
* Utility extending Gif builder
|
||||
*/
|
||||
class GifBuilderUtility extends GifBuilder
|
||||
{
|
||||
/**
|
||||
* Returns the reference to a "resource" in TypoScript.
|
||||
*
|
||||
* @param string The resource value.
|
||||
* @return string Returns the relative filepath
|
||||
*/
|
||||
public function checkFile($file)
|
||||
{
|
||||
$file = GeneralUtility::getFileAbsFileName(Environment::getPublicPath() . '/' . $file);
|
||||
$file = PathUtility::stripPathSitePrefix($file);
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the input GDlib image pointer to file
|
||||
*
|
||||
* @param resource The GDlib image resource pointer
|
||||
* @param string The filename to write to
|
||||
* @param int $quality The image quality (for JPEGs)
|
||||
* @return mixed The output of either imageGif, imagePng or imageJpeg based on the filename to write
|
||||
* @see maskImageOntoImage(), scale(), output()
|
||||
*/
|
||||
public function ImageWrite($destImg, $theImage, $quality = 0)
|
||||
{
|
||||
return parent::ImageWrite($destImg, Environment::getPublicPath() . '/' . $theImage, $quality);
|
||||
}
|
||||
}
|
||||
446
typo3conf/ext/sr_freecap/Classes/Utility/ImageContentUtility.php
Normal file
446
typo3conf/ext/sr_freecap/Classes/Utility/ImageContentUtility.php
Normal file
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-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!
|
||||
*/
|
||||
/************************************************************\
|
||||
*
|
||||
* 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\Utility\RandomContentUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Utility dealing with image content
|
||||
*/
|
||||
class ImageContentUtility {
|
||||
|
||||
const BACKGROUND_TYPE_TRANSPARENT = 'Transparent';
|
||||
const BACKGROUND_TYPE_WHITE_WITH_GRID = 'White with grid';
|
||||
const BACKGROUND_TYPE_WHITE_WITH_SQUIGGLES = 'White with squiggles';
|
||||
const BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS = 'Morphed image blocks';
|
||||
const MERGE_BACKGROUND_OVER_CAPTCHA = 0;
|
||||
const MERGE_CAPTCHA_OVER_BACKGROUND = 1;
|
||||
const TEXT_COLOR_UNIFORM = 0;
|
||||
const TEXT_COLOR_ONE_PER_CHARACTER = 1;
|
||||
const SITE_TAG_POSITION_TOP = 0;
|
||||
const SITE_TAG_POSITION_BOTTOM = 1;
|
||||
const SITE_TAG_POSITION_BOTH = 2;
|
||||
|
||||
/**
|
||||
* Write word on image
|
||||
*
|
||||
* @param int $width: width of the image in pixels
|
||||
* @param int $height: width of the image in pixels
|
||||
* @param string $word: the captcha word
|
||||
* @param int $textColorType (see constants)
|
||||
* @param array $textPosition: 'horizontal' => horizontal starting position of text, 'vertical' => vertical starting position of text
|
||||
* @param int $colorMaximum: 'darkness' => maximum color darkness along any dimension, 'lightness' => maximum color lightness along any dimension
|
||||
* @param string $backgroundType (see constants)
|
||||
* @param array $fontLocations: array of font files locations
|
||||
* @param array $fontWidths: array of font widths
|
||||
* @param int $morphfactor: text morphing factor
|
||||
* @return string GD image identifier of noisy background
|
||||
*/
|
||||
public static function writeWordOnImage($width, $height, $word, $textColorType, $textPosition, $colorMaximum, $backgroundType, $fontLocations, $fontWidths, $morphFactor = 1)
|
||||
{
|
||||
|
||||
$image = ImageCreate($width, $height);
|
||||
$image2 = ImageCreate($width, $height);
|
||||
// Set background colour (can change to any colour not in possible $text_col range)
|
||||
// it doesn't matter as it'll be transparent or coloured over.
|
||||
// if you're using background type 'Morphed image blocks', you might want to try to ensure that the color chosen
|
||||
// below doesn't appear too much in any of your background images.
|
||||
$background = ImageColorAllocate($image, 254, 254, 254);
|
||||
$background2 = ImageColorAllocate($image2, 254, 254, 254);
|
||||
// Set transparencies
|
||||
ImageColorTransparent($image, $background);
|
||||
// $image2 transparent to allow characters to overlap slightly while morphing
|
||||
ImageColorTransparent($image2, $background2);
|
||||
// Fill backgrounds
|
||||
ImageFill($image, 0, 0, $background);
|
||||
ImageFill($image2, 0, 0, $background2);
|
||||
|
||||
// Write word in random starting X position
|
||||
$word_start_x = RandomContentUtility::getRandomNumberInRange(5, $textPosition['horizontal']);
|
||||
// Y positions jiggled about later
|
||||
$word_start_y = $textPosition['vertical'];
|
||||
// Get uniform color
|
||||
if ($textColorType == self::TEXT_COLOR_UNIFORM) {
|
||||
$textColor = RandomContentUtility::getRandomColor($colorMaximum['darkness'], $colorMaximum['lightness'], $backgroundType == self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS);
|
||||
$textColor2 = ImageColorAllocate($image2, $textColor[0], $textColor[1], $textColor[2]);
|
||||
}
|
||||
// Write each character in different font
|
||||
$textFontWidths = array();
|
||||
$x_pos = $word_start_x;
|
||||
for ($i = 0; $i < strlen($word); $i++) {
|
||||
// Get changing color
|
||||
if ($textColorType == self::TEXT_COLOR_ONE_PER_CHARACTER) {
|
||||
$textColor = RandomContentUtility::getRandomColor($colorMaximum['darkness'], $colorMaximum['lightness'], $backgroundType == self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS);
|
||||
$textColor2 = ImageColorAllocate($image2, $textColor[0], $textColor[1], $textColor[2]);
|
||||
}
|
||||
$fontIndex = RandomContentUtility::getRandomNumberInRange(0, sizeof($fontLocations)-1);
|
||||
$font = ImageLoadFont($fontLocations[$fontIndex]);
|
||||
ImageString($image2, $font, $x_pos, $word_start_y, $word[$i], $textColor2);
|
||||
$textFontWidths[$i] = $fontWidths[$fontIndex];
|
||||
$x_pos += $textFontWidths[$i];
|
||||
}
|
||||
|
||||
// Morph Image
|
||||
// Firstly move each character up or down a bit:
|
||||
$x_pos = $word_start_x;
|
||||
$y_pos = 0;
|
||||
for ($i = 0; $i < strlen($word); $i++) {
|
||||
// Move on Y axis
|
||||
// Deviate at least 4 pixels between each letter
|
||||
$prev_y = $y_pos;
|
||||
do {
|
||||
$y_pos = RandomContentUtility::getRandomNumberInRange(-5, 5);
|
||||
} while ($y_pos < $prev_y + 2 && $y_pos > $prev_y - 2);
|
||||
ImageCopy($image, $image2, $x_pos, $y_pos, $x_pos, 0, $textFontWidths[$i], $height);
|
||||
$x_pos += $textFontWidths[$i];
|
||||
}
|
||||
ImageFilledRectangle($image2, 0, 0, $width, $height, $background2);
|
||||
|
||||
// Randomly morph each character individually on x-axis
|
||||
// This is where the main distortion happens
|
||||
$y_chunk = 1;
|
||||
$morph_x = 0;
|
||||
$orig_x = $word_start_x - $textFontWidths[0];
|
||||
for ($j = 0; $j < strlen($word); $j++) {
|
||||
$orig_x += $textFontWidths[$j];
|
||||
$y_pos = 0;
|
||||
for ($i = 0; $i <= $height; $i += $y_chunk) {
|
||||
// morph x += so that instead of deviating from orig x each time, we deviate from where we last deviated to
|
||||
// get it? instead of a zig zag, we get more of a sine wave.
|
||||
// I wish we could deviate more but it looks crap if we do.
|
||||
$morph_x += RandomContentUtility::getRandomNumberInRange(-$morphFactor, $morphFactor);
|
||||
// had to change this to ImageCopyMerge when starting using ImageCreateTrueColor
|
||||
// according to the manual; "when (pct is) 100 this function behaves identically to imagecopy()"
|
||||
// but this is NOT true when dealing with transparencies...
|
||||
ImageCopyMerge($image2, $image, $orig_x + $morph_x, $i + $y_pos, $orig_x, $i, $textFontWidths[$j], $y_chunk, 100);
|
||||
}
|
||||
}
|
||||
ImageFilledRectangle($image, 0, 0, $width, $height, $background);
|
||||
|
||||
// Now do the same on the y-axis
|
||||
// (much easier because we can just do it across the whole image, don't have to do it char-by-char)
|
||||
$y_pos = 0;
|
||||
$x_chunk = 1;
|
||||
for ($i = 0; $i <= $width ; $i += $x_chunk) {
|
||||
// Can result in image going too far off on Y-axis;
|
||||
// not much I can do about that, apart from make image bigger
|
||||
// again, I wish I could do 1.5 pixels
|
||||
$y_pos += RandomContentUtility::getRandomNumberInRange(-1, 1);
|
||||
ImageCopy($image, $image2, $i, $y_pos, $i, 0, $x_chunk, $height);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImageDestroy($image2);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate noisy background
|
||||
*
|
||||
* @param int $width: width of the image in pixels
|
||||
* @param int $height: width of the image in pixels
|
||||
* @param string $word: the captcha word
|
||||
* @param string $backgroundType (see constants)
|
||||
* @param array $backgroundImages: array of background image file names
|
||||
* @param boolean $morphBackground: if TRUE, the background will be morphed
|
||||
* @param boolean $blurBackground: if TRUE, the background will be blurred
|
||||
* @return string GD image identifier of noisy background
|
||||
*/
|
||||
public static function generateNoisyBackground($width, $height, $word, $backgroundType, $backgroundImages = array(), $morphBackground = true, $blurBackground = true)
|
||||
{
|
||||
$image = ImageCreateTrueColor($width, $height);
|
||||
if ($backgroundType != self::BACKGROUND_TYPE_TRANSPARENT) {
|
||||
|
||||
// Generate noisy background, to be merged with CAPTCHA later
|
||||
// any suggestions on how best to do this much appreciated
|
||||
// sample code would be even better!
|
||||
// I'm not an OCR expert (hell, I'm not even an image expert; puremango.co.uk was designed in MsPaint)
|
||||
// so the noise models are based around my -guesswork- as to what would make it hard for an OCR prog
|
||||
// ideally, the character obfuscation would be strong enough not to need additional background noise
|
||||
// in any case, I hope at least one of the options given here provide some extra security!
|
||||
$tempBackground = ImageCreateTrueColor($width*1.5, $height*1.5);
|
||||
$background = ImageColorAllocate($image, 255, 255, 255);
|
||||
ImageFill($image, 0, 0, $background);
|
||||
$tempBackgroundColor = ImageColorAllocate($tempBackground, 255, 255, 255);
|
||||
ImageFill($tempBackground, 0, 0, $tempBackgroundColor);
|
||||
|
||||
// We draw all noise onto tempBackground
|
||||
// then if we're morphing, merge from tempBackground to image
|
||||
// or if not, just copy a $width x $height portion of $tempBackground to $image
|
||||
// tempBackground is much larger so that when morphing, the edges retain the noise.
|
||||
switch ($backgroundType) {
|
||||
case self::BACKGROUND_TYPE_WHITE_WITH_GRID:
|
||||
// Draw grid on x
|
||||
for ($i = RandomContentUtility::getRandomNumberInRange(6, 20); $i < $width*2; $i += RandomContentUtility::getRandomNumberInRange(10, 25)) {
|
||||
ImageSetThickness($tempBackground, RandomContentUtility::getRandomNumberInRange(2, 6));
|
||||
$textColor = RandomContentUtility::getRandomColor(100, 150);
|
||||
$textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
|
||||
ImageLine($tempBackground, $i, 0, $i, $height*2, $textColor2);
|
||||
}
|
||||
// Draw grid on y
|
||||
for ($i = RandomContentUtility::getRandomNumberInRange(6, 20); $i < $height*2 ; $i += RandomContentUtility::getRandomNumberInRange(10, 25)) {
|
||||
ImageSetThickness($tempBackground, RandomContentUtility::getRandomNumberInRange(2, 6));
|
||||
$textColor = RandomContentUtility::getRandomColor(100, 150);
|
||||
$textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
|
||||
ImageLine($tempBackground, 0, $i, $width*2, $i , $textColor2);
|
||||
}
|
||||
break;
|
||||
case self::BACKGROUND_TYPE_WHITE_WITH_SQUIGGLES:
|
||||
ImageSetThickness($tempBackground, 4);
|
||||
for ($i = 0; $i < strlen($word)+1; $i++) {
|
||||
$textColor = RandomContentUtility::getRandomColor(100, 150);
|
||||
$textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
|
||||
$points = Array();
|
||||
// Draw random squiggle for each character
|
||||
// the longer the loop, the more complex the squiggle
|
||||
// keep random so OCR can't say "if found shape has 10 points, ignore it"
|
||||
// each squiggle will, however, be a closed shape, so OCR could try to find
|
||||
// line terminations and start from there. (I don't think they're that advanced yet..)
|
||||
for ($j = 1; $j < RandomContentUtility::getRandomNumberInRange(5, 10); $j++) {
|
||||
$points[] = RandomContentUtility::getRandomNumberInRange(1*(20*($i+1)), 1*(50*($i+1)));
|
||||
$points[] = RandomContentUtility::getRandomNumberInRange(30, $height+30);
|
||||
}
|
||||
ImagePolygon($tempBackground, $points, intval(sizeof($points)/2), $textColor2);
|
||||
}
|
||||
break;
|
||||
case self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS:
|
||||
// Take random chunks of $backgroundImages and paste them onto the background
|
||||
for ($i = 0; $i < sizeof($backgroundImages); $i++) {
|
||||
// Read each image and its size
|
||||
$tempImages[$i] = ImageCreateFromJPEG(GeneralUtility::getFileAbsFileName($backgroundImages[$i]));
|
||||
$tempWidths[$i] = imagesx($tempImages[$i]);
|
||||
$tempHeights[$i] = imagesy($tempImages[$i]);
|
||||
}
|
||||
$blocksize = RandomContentUtility::getRandomNumberInRange(20, 60);
|
||||
for ($i = 0; $i < $width*2; $i += $blocksize) {
|
||||
// Could randomise blocksize here... hardly matters
|
||||
for ($j = 0; $j < $height*2; $j += $blocksize) {
|
||||
$imageIndex = RandomContentUtility::getRandomNumberInRange(0, sizeof($tempImages)-1);
|
||||
$cut_x = RandomContentUtility::getRandomNumberInRange(0, $tempWidths[$imageIndex]-$blocksize);
|
||||
$cut_y = RandomContentUtility::getRandomNumberInRange(0, $tempHeights[$imageIndex]-$blocksize);
|
||||
ImageCopy($tempBackground, $tempImages[$imageIndex], $i, $j, $cut_x, $cut_y, $blocksize, $blocksize);
|
||||
}
|
||||
}
|
||||
// Cleanup
|
||||
for ($i = 0; $i < sizeof($tempImages); $i++) {
|
||||
ImageDestroy($tempImages[$i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($morphBackground) {
|
||||
// Morph background
|
||||
// We do this separately to the main text morph because:
|
||||
// a) the main text morph is done char-by-char, this is done across whole image
|
||||
// b) if an attacker could un-morph the background, it would un-morph the CAPTCHA
|
||||
// hence background is morphed differently to text
|
||||
// why do we morph it at all? it might make it harder for an attacker to remove the background
|
||||
// morph_chunk 1 looks better but takes longer
|
||||
// this is a different and less perfect morph than the one we do on the CAPTCHA
|
||||
// occasonally you get some dark background showing through around the edges
|
||||
// it doesn't need to be perfect as it's only the background.
|
||||
$morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
|
||||
$morph_y = 0;
|
||||
for ($x = 0; $x < $width; $x += $morph_chunk) {
|
||||
$morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
|
||||
$morph_y += RandomContentUtility::getRandomNumberInRange(-1, 1);
|
||||
ImageCopy($image, $tempBackground, $x, 0, $x+30, 30+$morph_y, $morph_chunk, $height*2);
|
||||
}
|
||||
|
||||
ImageCopy($tempBackground, $image, 0, 0, 0, 0, $width, $height);
|
||||
|
||||
$morph_x = 0;
|
||||
for ($y = 0; $y <= $height; $y += $morph_chunk) {
|
||||
$morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
|
||||
$morph_x += RandomContentUtility::getRandomNumberInRange(-1, 1);
|
||||
ImageCopy($image, $tempBackground, $morph_x, $y, 0, $y, $width, $morph_chunk);
|
||||
|
||||
}
|
||||
} else {
|
||||
// Just copy tempBackground onto $image
|
||||
ImageCopy($image, $tempBackground, 0, 0, 30, 30, $width, $height);
|
||||
}
|
||||
// Cleanup
|
||||
ImageDestroy($tempBackground);
|
||||
|
||||
if ($blurBackground) {
|
||||
$image = self::blurImage($image);
|
||||
}
|
||||
}
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge captcha image with background
|
||||
*
|
||||
* @param int $width: width of the image in pixels
|
||||
* @param int $height: width of the image in pixels
|
||||
* @param string $captchaImage: a GD image identifier
|
||||
* @param string $backgroundImage: a GD image identifier
|
||||
* @param string $backgroundType (see constants)
|
||||
* @param int $mergeType: 0 - Background over captcha, 1 - Captcha over background (see constants)
|
||||
* @param int $backgroundFadePercentage: fading factor for background
|
||||
* @return string GD image identifier of merged image
|
||||
*/
|
||||
public static function mergeCaptchaWithBackground($width, $height, $captchaImage, $backgroundImage, $backgroundType, $mergeType)
|
||||
{
|
||||
if ($backgroundType != self::BACKGROUND_TYPE_TRANSPARENT) {
|
||||
// How faded should the background be? (100=totally gone, 0=bright as the day)
|
||||
// to test how much protection the bg noise gives, take a screenshot of the freeCap image
|
||||
// and take it into a photo editor. play with contrast and brightness.
|
||||
// If you can remove most of the background, then it's not a good enough percentage
|
||||
switch ($backgroundType) {
|
||||
case self::BACKGROUND_TYPE_WHITE_WITH_GRID:
|
||||
case self::BACKGROUND_TYPE_WHITE_WITH_SQUIGGLES:
|
||||
$backgroundFadePercentage = 65;
|
||||
break;
|
||||
case self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS:
|
||||
$backgroundFadePercentage = 50;
|
||||
break;
|
||||
}
|
||||
// Slightly randomize the background fade
|
||||
$backgroundFadePercentage += RandomContentUtility::getRandomNumberInRange(-2, 2);
|
||||
// Fade background
|
||||
if ($backgroundType != self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS) {
|
||||
$tempImage = ImageCreateTrueColor($width, $height);
|
||||
$white = ImageColorAllocate($tempImage, 255, 255, 255);
|
||||
ImageFill($tempImage, 0, 0, $white);
|
||||
ImageCopyMerge($backgroundImage, $tempImage, 0, 0, 0, 0, $width, $height, $backgroundFadePercentage);
|
||||
ImageDestroy($tempImage);
|
||||
$colorFadePercentage = 50;
|
||||
} else {
|
||||
$colorFadePercentage = $backgroundFadePercentage;
|
||||
}
|
||||
// Merge background image with CAPTCHA image to create smooth background
|
||||
if ($mergeType == self::MERGE_CAPTCHA_OVER_BACKGROUND) {
|
||||
// Might want to not blur if using this method, otherwise leaves white-ish border around each letter
|
||||
ImageCopyMerge($backgroundImage, $captchaImage, 0, 0, 0, 0, $width, $height, 100);
|
||||
ImageCopy($captchaImage, $backgroundImage, 0, 0, 0, 0, $width, $height);
|
||||
} else {
|
||||
// Background over captcha
|
||||
ImageCopyMerge($captchaImage, $backgroundImage, 0, 0, 0, 0, $width, $height, $colorFadePercentage);
|
||||
}
|
||||
}
|
||||
return $captchaImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blurs an image
|
||||
*
|
||||
* @param string $image: a GD image identifier
|
||||
* @return string GD image identifier of blurred image
|
||||
*/
|
||||
public static function blurImage($image)
|
||||
{
|
||||
// w00t. my very own blur function
|
||||
// in GD2, there's a gaussian blur function. bunch of bloody show-offs... :-)
|
||||
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
$temp_im = ImageCreateTrueColor($width, $height);
|
||||
$bg = ImageColorAllocate($temp_im, 150, 150, 150);
|
||||
|
||||
// preserves transparency if in orig image
|
||||
ImageColorTransparent($temp_im, $bg);
|
||||
|
||||
// fill bg
|
||||
ImageFill($temp_im, 0, 0, $bg);
|
||||
|
||||
// anything higher than 3 makes it totally unreadable
|
||||
// might be useful in a 'real' blur function, though (ie blurring pictures not text)
|
||||
$distance = 1;
|
||||
// use $distance=30 to have multiple copies of the word. not sure if this is useful.
|
||||
|
||||
// blur by merging with itself at different x/y offsets:
|
||||
ImageCopyMerge($temp_im, $image, 0, 0, 0, $distance, $width, $height-$distance, 70);
|
||||
ImageCopyMerge($image, $temp_im, 0, 0, $distance, 0, $width-$distance, $height, 70);
|
||||
ImageCopyMerge($temp_im, $image, 0, $distance, 0, 0, $width, $height, 70);
|
||||
ImageCopyMerge($image, $temp_im, $distance, 0, 0, 0, $width, $height, 70);
|
||||
// remove temp image
|
||||
ImageDestroy($temp_im);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the image with appropriate headers
|
||||
*
|
||||
* @param string $image: a GD image identifier
|
||||
* @param string $imageType: type of image (jpg, gif or png)
|
||||
* @return void
|
||||
*/
|
||||
public static function sendImage($image, $imageType)
|
||||
{
|
||||
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"');
|
||||
switch ($imageType) {
|
||||
case 'jpg':
|
||||
header('Content-Type: image/jpeg');
|
||||
ImageJPEG($image);
|
||||
break;
|
||||
case 'gif':
|
||||
header('Content-Type: image/gif');
|
||||
ImageGIF($image);
|
||||
break;
|
||||
case 'png':
|
||||
default:
|
||||
header('Content-Type: image/png');
|
||||
ImagePNG($image);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
typo3conf/ext/sr_freecap/Classes/Utility/LocalizationUtility.php
Normal file
159
typo3conf/ext/sr_freecap/Classes/Utility/LocalizationUtility.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2009 Sebastian Kurfürst <sebastian@typo3.org>
|
||||
* (c) 2013-2021 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.
|
||||
*
|
||||
* 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 Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Http\ApplicationType;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Localization\Locales;
|
||||
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
|
||||
use TYPO3\CMS\Core\Site\SiteFinder;
|
||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* Localization helper which should be used to fetch appropriate words list or voice rendering language
|
||||
*
|
||||
*/
|
||||
class LocalizationUtility
|
||||
{
|
||||
/**
|
||||
* Key of the extension to which this class belongs
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $extensionKey = 'sr_freecap';
|
||||
|
||||
/**
|
||||
* Gets the location of the words list based on configured language
|
||||
*
|
||||
* @param string $defaultWordsList: location of the default words list
|
||||
* @return string the location of the words list to be used
|
||||
*/
|
||||
public static function getWordsListLocation($defaultWordsList = '')
|
||||
{
|
||||
$languageKeys = static::getLanguageKeys();
|
||||
$initialWordsList = $defaultWordsList;
|
||||
if (!trim($initialWordsList)) {
|
||||
$initialWordsList = 'EXT:' . self::$extensionKey . '/Resources/Private/Captcha/Words/default_freecap_words';
|
||||
}
|
||||
$path = dirname(GeneralUtility::getFileAbsFileName($initialWordsList)) . '/';
|
||||
$wordsListLocation = $path . $languageKeys['languageKey'] . '_freecap_words';
|
||||
if (!is_file($wordsListLocation)) {
|
||||
foreach ($languageKeys['alternativeLanguageKeys'] as $language) {
|
||||
$wordsListLocation = $path . $language . '_freecap_words';
|
||||
if (is_file($wordsListLocation)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_file($wordsListLocation)) {
|
||||
$wordsListLocation = $path . 'default_freecap_words';
|
||||
if (!is_file($wordsListLocation)) {
|
||||
$wordsListLocation = '';
|
||||
}
|
||||
}
|
||||
return $wordsListLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory of wav files based on configured language
|
||||
*
|
||||
* @return string name of the directory containing the wav files to be used
|
||||
*/
|
||||
public static function getVoicesDirectory()
|
||||
{
|
||||
$languageKeys = static::getLanguageKeys();
|
||||
$path = ExtensionManagementUtility::extPath(self::$extensionKey) . 'Resources/Private/Captcha/Voices/';
|
||||
$voicesDirectory = $path . $languageKeys['languageKey'] . '/';
|
||||
if (!is_dir($voicesDirectory)) {
|
||||
foreach ($languageKeys['alternativeLanguageKeys'] as $language) {
|
||||
$voicesDirectory = $path . $language . '/';
|
||||
if (is_dir($voicesDirectory)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_dir($voicesDirectory)) {
|
||||
$voicesDirectory = $path . 'default/';
|
||||
}
|
||||
return $voicesDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the currently active language/language_alt keys.
|
||||
* Default values are "default" for language key and an empty array for language_alt key.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function getLanguageKeys(): array
|
||||
{
|
||||
$languageKeys = [
|
||||
'languageKey' => 'default',
|
||||
'alternativeLanguageKeys' => [],
|
||||
];
|
||||
if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
|
||||
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()
|
||||
) {
|
||||
$tsfe = static::getTypoScriptFrontendController();
|
||||
$pageId = $tsfe->id;
|
||||
$siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
|
||||
$currentSite = $siteFinder->getSiteByPageId($pageId);
|
||||
$languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
|
||||
// Current language
|
||||
$currentSiteLanguageId = $languageAspect->getId();
|
||||
$currentSiteLanguage = $currentSite->getLanguageById((int)$currentSiteLanguageId);
|
||||
$languageKeys['languageKey'] = $currentSiteLanguage->getTypo3Language();
|
||||
// Alternative languages
|
||||
$alternativeLanguageIds = $languageAspect->getFallbackChain();
|
||||
foreach ($alternativeLanguageIds as $alternativeLanguageId) {
|
||||
$alternativeLanguage = $currentSite->getLanguageById((int)$alternativeLanguageId);
|
||||
$languageKeys['alternativeLanguageKeys'][] = $alternativeLanguage->getTypo3Language();
|
||||
}
|
||||
if (empty($languageKeys['alternativeLanguageKeys'])) {
|
||||
$locales = GeneralUtility::makeInstance(Locales::class);
|
||||
if (in_array($languageKeys['languageKey'], $locales->getLocales())) {
|
||||
foreach ($locales->getLocaleDependencies($languageKeys['languageKey']) as $language) {
|
||||
$languageKeys['alternativeLanguageKeys'][] = $language;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$languageKeys['languageKey'] = $GLOBALS['BE_USER']->uc['lang'];
|
||||
}
|
||||
return $languageKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypoScriptFrontendController
|
||||
*/
|
||||
protected static function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-2020 Stanislas Rolland <typo32020(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!
|
||||
*/
|
||||
/**
|
||||
* Utility dealing with mp3 audio content
|
||||
* See http://www.theblog.ca/merge-mp3s-php
|
||||
*/
|
||||
class Mp3ContentUtility
|
||||
{
|
||||
var $mp3Content;
|
||||
|
||||
// Create a new mp3
|
||||
public function __construct($file = '')
|
||||
{
|
||||
if ($file != '') {
|
||||
$this->mp3Content = file_get_contents($file);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the mp3 content
|
||||
public function getContent()
|
||||
{
|
||||
return $this->mp3Content;
|
||||
}
|
||||
|
||||
// Calculate where's the beginning of the sound file
|
||||
protected function getStart()
|
||||
{
|
||||
$strlen = strlen($this->mp3Content);
|
||||
for ($i=0; $i < $strlen; $i++) {
|
||||
$v = substr($this->mp3Content, $i, 1);
|
||||
$value = ord($v);
|
||||
if ($value == 255) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate where's the end of the sound file
|
||||
protected function getIdvEnd()
|
||||
{
|
||||
$strlen = strlen($this->mp3Content);
|
||||
$str = substr($this->mp3Content, ($strlen - 128));
|
||||
$str1 = substr($str, 0, 3);
|
||||
if (strtolower($str1) == strtolower('TAG')) {
|
||||
return $str;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the ID3 tags
|
||||
public function striptags()
|
||||
{
|
||||
// Remove start stuff...
|
||||
$newStr = '';
|
||||
$s = $start = $this->getStart();
|
||||
if ($s === false) {
|
||||
return false;
|
||||
} else {
|
||||
$this->mp3Content = substr($this->mp3Content, $start);
|
||||
}
|
||||
//Remove end tag stuff
|
||||
$end = $this->getIdvEnd();
|
||||
if ($end !== false) {
|
||||
$this->mp3Content = substr($this->mp3Content, 0, (strlen($this->mp3Content)-129));
|
||||
}
|
||||
return $this->mp3Content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
namespace SJBR\SrFreecap\Utility;
|
||||
|
||||
/*
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2012-2020 Stanislas Rolland <typo32020(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!
|
||||
*/
|
||||
/**
|
||||
* Random content utility
|
||||
*/
|
||||
class RandomContentUtility
|
||||
{
|
||||
/**
|
||||
* Returns a random number within the given range
|
||||
*
|
||||
* @param int $min: the lower boundary of the range
|
||||
* @param int $max: the upper boundary of the range
|
||||
* @return int the generated number
|
||||
*/
|
||||
public static function getRandomNumberInRange($min, $max)
|
||||
{
|
||||
if ($min > $max) {
|
||||
$newMin = $max;
|
||||
$newMax = $min;
|
||||
} else {
|
||||
$newMin = $min;
|
||||
$newMax = $max;
|
||||
}
|
||||
return mt_rand($newMin, $newMax);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random color in a the form of an array of 3 numbers
|
||||
*
|
||||
* @param int $colorMaximumDarkness: maximum darkness along any dimension
|
||||
* @param int $colorMaximumLightness: maximum lightness along any dimension
|
||||
* @param boolean $darker: if true, produce a possibly darker image by default
|
||||
* @return array the random color
|
||||
*/
|
||||
public static function getRandomColor ($colorMaximumDarkness, $colorMaximumLightness, $darker = false)
|
||||
{
|
||||
$color = [];
|
||||
if ($darker) {
|
||||
// Needs darker colour..
|
||||
$minimum = isset($colorMaximumDarkness) ? $colorMaximumDarkness : 10;
|
||||
$maximum = isset($colorMaximumLightness) ? $colorMaximumLightness : 100;
|
||||
} else {
|
||||
$minimum = isset($colorMaximumDarkness) ? $colorMaximumDarkness : 30;
|
||||
$maximum = isset($colorMaximumLightness) ? $colorMaximumLightness : 140;
|
||||
}
|
||||
for ($i = 0; $i < 3 ; $i++) {
|
||||
$color[] = self::getRandomNumberInRange($minimum, $maximum);
|
||||
}
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random word
|
||||
*
|
||||
* @param boolean $useWordsList: if true, a word dictionary is used
|
||||
* @param string $wordsList: dictionary file location
|
||||
* @param boolean $numbersOnly: if true, use only numbers
|
||||
*
|
||||
* @return string random word
|
||||
*/
|
||||
public static function getRandomWord($useWordsList = false, $wordsList = '', $numbersOnly = false, $maxWordLength = 6)
|
||||
{
|
||||
if ($useWordsList && is_file($wordsList)) {
|
||||
// Load dictionary and choose random word
|
||||
// Keep dictionary in non-web accessible folder, or htaccess it
|
||||
// or modify so word comes from a database; SELECT word FROM words ORDER BY rand() LIMIT 1
|
||||
$words = @file($wordsList);
|
||||
$word = strtolower($words[self::getRandomNumberInRange(0, sizeof($words)-1)]);
|
||||
// Cut off line breaks
|
||||
$word = preg_replace('/['.preg_quote(chr(10).chr(13)).']+/', '', $word);
|
||||
unset($words);
|
||||
} else {
|
||||
// Based on code originally by breakzero at hotmail dot com
|
||||
// (http://uk.php.net/manual/en/function.rand.php)
|
||||
// generate pseudo-random string
|
||||
// doesn't use ijtf as are easily mistaken
|
||||
|
||||
// I'm not using numbers because the custom fonts I've created don't support anything other than
|
||||
// lowercase or space (but you can download new fonts or create your own using my GD fontmaker script)
|
||||
if ($numbersOnly) {
|
||||
$consonants = '123456789';
|
||||
$vowels = '123456789';
|
||||
} else {
|
||||
$consonants = 'bcdghklmnpqrsvwxyz';
|
||||
$vowels = 'aeuo';
|
||||
}
|
||||
$word = '';
|
||||
$wordlen = self::getRandomNumberInRange(5, $maxWordLength);
|
||||
for ($i = 0; $i < $wordlen; $i++) {
|
||||
// Don't allow to start with 'vowel'
|
||||
if (self::getRandomNumberInRange(0, 20) >= 10 && $i != 0) {
|
||||
$word .= $vowels[self::getRandomNumberInRange(0, strlen($vowels)-1)];
|
||||
} else {
|
||||
$word .= $consonants[self::getRandomNumberInRange(0, strlen($consonants)-1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user