Current File : /home/pacjaorg/.trash/libraries.1/vendor/joomla/filter/src/InputFilter.php |
<?php
/**
* Part of the Joomla Framework Filter Package
*
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\Filter;
use Joomla\String\StringHelper;
/**
* InputFilter is a class for filtering input from any data source
*
* Forked from the php input filter library by: Daniel Morris <dan@rootcube.com>
* Original Contributors: Gianpaolo Racca, Ghislain Picard, Marco Wandschneider, Chris Tobin and Andrew Eddie.
*
* @since 1.0
*/
class InputFilter
{
/**
* Defines the InputFilter instance should only allow the supplied list of HTML tags.
*
* @var integer
* @since 1.4.0
*/
public const ONLY_ALLOW_DEFINED_TAGS = 0;
/**
* Defines the InputFilter instance should block the defined list of HTML tags and allow all others.
*
* @var integer
* @since 1.4.0
*/
public const ONLY_BLOCK_DEFINED_TAGS = 1;
/**
* Defines the InputFilter instance should only allow the supplied list of attributes.
*
* @var integer
* @since 1.4.0
*/
public const ONLY_ALLOW_DEFINED_ATTRIBUTES = 0;
/**
* Defines the InputFilter instance should block the defined list of attributes and allow all others.
*
* @var integer
* @since 1.4.0
*/
public const ONLY_BLOCK_DEFINED_ATTRIBUTES = 1;
/**
* The array of permitted tags.
*
* @var array
* @since 1.0
*/
public $tagsArray;
/**
* The array of permitted tag attributes.
*
* @var array
* @since 1.0
*/
public $attrArray;
/**
* The method for sanitising tags
*
* @var integer
* @since 1.0
*/
public $tagsMethod;
/**
* The method for sanitising attributes
*
* @var integer
* @since 1.0
*/
public $attrMethod;
/**
* A flag for XSS checks. Only auto clean essentials = 0, Allow clean blocked tags/attr = 1
*
* @var integer
* @since 1.0
*/
public $xssAuto;
/**
* The list the blocked tags for the instance.
*
* @var string[]
* @since 1.0
*/
public $blockedTags = [
'applet',
'body',
'bgsound',
'base',
'basefont',
'canvas',
'embed',
'frame',
'frameset',
'head',
'html',
'id',
'iframe',
'ilayer',
'layer',
'link',
'meta',
'name',
'object',
'script',
'style',
'title',
'xml',
];
/**
* The list of blocked tag attributes for the instance.
*
* @var string[]
* @since 1.0
*/
public $blockedAttributes = [
'action',
'background',
'codebase',
'dynsrc',
'formaction',
'lowsrc',
];
/**
* A special list of blocked characters.
*
* @var string[]
* @since 1.3.3
*/
private $blockedChars = [
'&tab;',
'&space;',
':',
'&column;',
];
/**
* Constructor for InputFilter class.
*
* @param array $tagsArray List of permitted HTML tags
* @param array $attrArray List of permitted HTML tag attributes
* @param integer $tagsMethod Method for filtering tags, should be one of the `ONLY_*_DEFINED_TAGS` constants
* @param integer $attrMethod Method for filtering attributes, should be one of the `ONLY_*_DEFINED_ATTRIBUTES` constants
* @param integer $xssAuto Only auto clean essentials = 0, Allow clean blocked tags/attributes = 1
*
* @since 1.0
*/
public function __construct(
array $tagsArray = [],
array $attrArray = [],
$tagsMethod = self::ONLY_ALLOW_DEFINED_TAGS,
$attrMethod = self::ONLY_ALLOW_DEFINED_ATTRIBUTES,
$xssAuto = 1
) {
// Make sure user defined arrays are in lowercase
$tagsArray = array_map('strtolower', (array) $tagsArray);
$attrArray = array_map('strtolower', (array) $attrArray);
// Assign member variables
$this->tagsArray = $tagsArray;
$this->attrArray = $attrArray;
$this->tagsMethod = $tagsMethod;
$this->attrMethod = $attrMethod;
$this->xssAuto = $xssAuto;
}
/**
* Cleans the given input source based on the instance configuration and specified data type
*
* @param string|string[]|object $source Input string/array-of-string/object to be 'cleaned'
* @param string $type The return type for the variable:
* INT: An integer
* UINT: An unsigned integer
* FLOAT: A floating point number
* BOOLEAN: A boolean value
* WORD: A string containing A-Z or underscores only (not case sensitive)
* ALNUM: A string containing A-Z or 0-9 only (not case sensitive)
* CMD: A string containing A-Z, 0-9, underscores, periods or hyphens (not case
* sensitive)
* BASE64: A string containing A-Z, 0-9, forward slashes, plus or equals (not case
* sensitive)
* STRING: A fully decoded and sanitised string (default)
* HTML: A sanitised string
* ARRAY: An array
* PATH: A sanitised file path
* TRIM: A string trimmed from normal, non-breaking and multibyte spaces
* USERNAME: Do not use (use an application specific filter)
* RAW: The raw string is returned with no filtering
* unknown: An unknown filter will act like STRING. If the input is an array it will
* return an array of fully decoded and sanitised strings.
*
* @return mixed 'Cleaned' version of the `$source` parameter
*
* @since 1.0
*/
public function clean($source, $type = 'string')
{
$type = ucfirst(strtolower($type));
if ($type === 'Array') {
return (array) $source;
}
if ($type === 'Raw') {
return $source;
}
if (\is_array($source)) {
$result = [];
foreach ($source as $key => $value) {
$result[$key] = $this->clean($value, $type);
}
return $result;
}
if (\is_object($source)) {
foreach (get_object_vars($source) as $key => $value) {
$source->$key = $this->clean($value, $type);
}
return $source;
}
$method = 'clean' . $type;
if (method_exists($this, $method)) {
return $this->$method((string) $source);
}
// Unknown filter method
if (\is_string($source) && !empty($source)) {
// Filter source for XSS and other 'bad' code etc.
return $this->cleanString($source);
}
// Not an array or string... return the passed parameter
return $source;
}
/**
* Function to determine if contents of an attribute are safe
*
* @param array $attrSubSet A 2 element array for attribute's name, value
*
* @return boolean True if bad code is detected
*
* @since 1.0
*/
public static function checkAttribute($attrSubSet)
{
$attrSubSet[0] = strtolower($attrSubSet[0]);
$attrSubSet[1] = html_entity_decode(strtolower($attrSubSet[1]), ENT_QUOTES | ENT_HTML401, 'UTF-8');
return (strpos($attrSubSet[1], 'expression') !== false && $attrSubSet[0] === 'style')
|| preg_match('/(?:(?:java|vb|live)script|behaviour|mocha)(?::|:|&column;)/', $attrSubSet[1]) !== 0;
}
/**
* Internal method to iteratively remove all unwanted tags and attributes
*
* @param string $source Input string to be 'cleaned'
*
* @return string 'Cleaned' version of input parameter
*
* @since 1.0
*/
protected function remove($source)
{
// Iteration provides nested tag protection
do {
$temp = $source;
$source = $this->cleanTags($source);
} while ($temp !== $source);
return $source;
}
/**
* Internal method to strip a string of disallowed tags
*
* @param string $source Input string to be 'cleaned'
*
* @return string 'Cleaned' version of input parameter
*
* @since 1.0
*/
protected function cleanTags($source)
{
// First, pre-process this for illegal characters inside attribute values
$source = $this->escapeAttributeValues($source);
// In the beginning we don't really have a tag, so everything is postTag
$preTag = null;
$postTag = $source;
$currentSpace = false;
// Setting to null to deal with undefined variables
$attr = '';
// Is there a tag? If so it will certainly start with a '<'.
$tagOpenStart = strpos($source, '<');
while ($tagOpenStart !== false) {
// Get some information about the tag we are processing
$preTag .= substr($postTag, 0, $tagOpenStart);
$postTag = substr($postTag, $tagOpenStart);
$fromTagOpen = substr($postTag, 1);
$tagOpenEnd = strpos($fromTagOpen, '>');
// Check for mal-formed tag where we have a second '<' before the first '>'
$nextOpenTag = (strlen($postTag) > $tagOpenStart) ? strpos($postTag, '<', $tagOpenStart + 1) : false;
if (($nextOpenTag !== false) && ($nextOpenTag < $tagOpenEnd)) {
// At this point we have a mal-formed tag -- remove the offending open
$postTag = substr($postTag, 0, $tagOpenStart) . substr($postTag, $tagOpenStart + 1);
$tagOpenStart = strpos($postTag, '<');
continue;
}
// Let's catch any non-terminated tags and skip over them
if ($tagOpenEnd === false) {
$postTag = substr($postTag, $tagOpenStart + 1);
$tagOpenStart = strpos($postTag, '<');
continue;
}
// Do we have a nested tag?
$tagOpenNested = strpos($fromTagOpen, '<');
if (($tagOpenNested !== false) && ($tagOpenNested < $tagOpenEnd)) {
$preTag .= substr($postTag, 1, $tagOpenNested);
$postTag = substr($postTag, ($tagOpenNested + 1));
$tagOpenStart = strpos($postTag, '<');
continue;
}
// Let's get some information about our tag and setup attribute pairs
$tagOpenNested = (strpos($fromTagOpen, '<') + $tagOpenStart + 1);
$currentTag = substr($fromTagOpen, 0, $tagOpenEnd);
$tagLength = strlen($currentTag);
$tagLeft = $currentTag;
$attrSet = [];
$currentSpace = strpos($tagLeft, ' ');
// Are we an open tag or a close tag?
if (substr($currentTag, 0, 1) === '/') {
// Close Tag
$isCloseTag = true;
list($tagName) = explode(' ', $currentTag);
$tagName = substr($tagName, 1);
} else {
// Open Tag
$isCloseTag = false;
list($tagName) = explode(' ', $currentTag);
}
/*
* Exclude all "non-regular" tagnames
* OR no tagname
* OR remove if xssauto is on and tag is blocked
*/
if (
(!preg_match('/^[a-z][a-z0-9]*$/i', $tagName))
|| (!$tagName)
|| ((\in_array(strtolower($tagName), $this->blockedTags)) && $this->xssAuto)
) {
$postTag = substr($postTag, ($tagLength + 2));
$tagOpenStart = strpos($postTag, '<');
// Strip tag
continue;
}
/*
* Time to grab any attributes from the tag... need this section in
* case attributes have spaces in the values.
*/
while ($currentSpace !== false) {
$attr = '';
$fromSpace = substr($tagLeft, ($currentSpace + 1));
$nextEqual = strpos($fromSpace, '=');
$nextSpace = strpos($fromSpace, ' ');
$openQuotes = strpos($fromSpace, '"');
$closeQuotes = strpos(substr($fromSpace, ($openQuotes + 1)), '"') + $openQuotes + 1;
$startAtt = '';
$startAttPosition = 0;
// Find position of equal and open quotes ignoring
if (preg_match('#\s*=\s*\"#', $fromSpace, $matches, \PREG_OFFSET_CAPTURE)) {
$stringBeforeAttr = substr($fromSpace, 0, $matches[0][1]);
$startAttPosition = strlen($stringBeforeAttr);
$startAtt = $matches[0][0];
$closeQuotePos = strpos(
substr($fromSpace, ($startAttPosition + strlen($startAtt))),
'"'
);
$closeQuotes = $closeQuotePos + $startAttPosition + strlen($startAtt);
$nextEqual = $startAttPosition + strpos($startAtt, '=');
$openQuotes = $startAttPosition + strpos($startAtt, '"');
$nextSpace = strpos(substr($fromSpace, $closeQuotes), ' ') + $closeQuotes;
}
// Do we have an attribute to process? [check for equal sign]
if ($fromSpace !== '/' && (($nextEqual && $nextSpace && $nextSpace < $nextEqual) || !$nextEqual)) {
if (!$nextEqual) {
$attribEnd = strpos($fromSpace, '/') - 1;
} else {
$attribEnd = $nextSpace - 1;
}
// If there is an ending, use this, if not, do not worry.
if ($attribEnd > 0) {
$fromSpace = substr($fromSpace, $attribEnd + 1);
}
}
if (strpos($fromSpace, '=') !== false) {
/*
* If the attribute value is wrapped in quotes we need to grab the substring from the closing quote,
* otherwise grab until the next space.
*/
if (
($openQuotes !== false)
&& (strpos(substr($fromSpace, ($openQuotes + 1)), '"') !== false)
) {
$attr = substr($fromSpace, 0, ($closeQuotes + 1));
} else {
$attr = substr($fromSpace, 0, $nextSpace);
}
} else {
// No more equal signs so add any extra text in the tag into the attribute array [eg. checked]
if ($fromSpace !== '/') {
$attr = substr($fromSpace, 0, $nextSpace);
}
}
// Last Attribute Pair
if (!$attr && $fromSpace !== '/') {
$attr = $fromSpace;
}
// Add attribute pair to the attribute array
$attrSet[] = $attr;
// Move search point and continue iteration
$tagLeft = substr($fromSpace, strlen($attr));
$currentSpace = strpos($tagLeft, ' ');
}
// Is our tag in the user input array?
$tagFound = \in_array(strtolower($tagName), $this->tagsArray);
// If the tag is allowed let's append it to the output string.
if ((!$tagFound && $this->tagsMethod) || ($tagFound && !$this->tagsMethod)) {
// Reconstruct tag with allowed attributes
if (!$isCloseTag) {
// Open or single tag
$attrSet = $this->cleanAttributes($attrSet);
$preTag .= '<' . $tagName;
for ($i = 0, $count = \count($attrSet); $i < $count; $i++) {
$preTag .= ' ' . $attrSet[$i];
}
// Reformat single tags to XHTML
if (strpos($fromTagOpen, '</' . $tagName)) {
$preTag .= '>';
} else {
$preTag .= ' />';
}
} else {
// Closing tag
$preTag .= '</' . $tagName . '>';
}
}
// Find next tag's start and continue iteration
$postTag = substr($postTag, ($tagLength + 2));
$tagOpenStart = strpos($postTag, '<');
}
// Append any code after the end of tags and return
if ($postTag !== '<') {
$preTag .= $postTag;
}
return $preTag;
}
/**
* Internal method to strip a tag of disallowed attributes
*
* @param array $attrSet Array of attribute pairs to filter
*
* @return array Filtered array of attribute pairs
*
* @since 1.0
*/
protected function cleanAttributes(array $attrSet)
{
$newSet = [];
$count = \count($attrSet);
// Iterate through attribute pairs
for ($i = 0; $i < $count; $i++) {
// Skip blank spaces
if (!$attrSet[$i]) {
continue;
}
// Split into name/value pairs
$attrSubSet = explode('=', trim($attrSet[$i]), 2);
// Take the last attribute in case there is an attribute with no value
$attrSubSet0 = explode(' ', trim($attrSubSet[0]));
$attrSubSet[0] = array_pop($attrSubSet0);
$attrSubSet[0] = strtolower($attrSubSet[0]);
$quoteStyle = \ENT_QUOTES | \ENT_HTML401;
// Remove all spaces as valid attributes does not have spaces.
$attrSubSet[0] = html_entity_decode($attrSubSet[0], $quoteStyle, 'UTF-8');
$attrSubSet[0] = preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $attrSubSet[0]);
$attrSubSet[0] = preg_replace('/\s+/u', '', $attrSubSet[0]);
// Remove blocked chars from the attribute name
foreach ($this->blockedChars as $blockedChar) {
$attrSubSet[0] = str_ireplace($blockedChar, '', $attrSubSet[0]);
}
// Remove all symbols
$attrSubSet[0] = preg_replace('/[^\p{L}\p{N}\-\s]/u', '', $attrSubSet[0]);
// Remove all "non-regular" attribute names
// AND blocked attributes
if (
(!preg_match('/[a-z]*$/i', $attrSubSet[0]))
|| ($this->xssAuto && ((\in_array(strtolower($attrSubSet[0]), $this->blockedAttributes))
|| substr($attrSubSet[0], 0, 2) == 'on'))
) {
continue;
}
// XSS attribute value filtering
if (!isset($attrSubSet[1])) {
continue;
}
// Remove blocked chars from the attribute value
foreach ($this->blockedChars as $blockedChar) {
$attrSubSet[1] = str_ireplace($blockedChar, '', $attrSubSet[1]);
}
// Trim leading and trailing spaces
$attrSubSet[1] = trim($attrSubSet[1]);
// Strips unicode, hex, etc
$attrSubSet[1] = str_replace('&#', '', $attrSubSet[1]);
// Strip normal newline within attr value
$attrSubSet[1] = preg_replace('/[\n\r]/', '', $attrSubSet[1]);
// Strip double quotes
$attrSubSet[1] = str_replace('"', '', $attrSubSet[1]);
// Convert single quotes from either side to doubles (Single quotes shouldn't be used to pad attr values)
if ((substr($attrSubSet[1], 0, 1) == "'") && (substr($attrSubSet[1], (\strlen($attrSubSet[1]) - 1), 1) == "'")) {
$attrSubSet[1] = substr($attrSubSet[1], 1, (\strlen($attrSubSet[1]) - 2));
}
// Strip slashes
$attrSubSet[1] = stripslashes($attrSubSet[1]);
// Autostrip script tags
if (static::checkAttribute($attrSubSet)) {
continue;
}
// Is our attribute in the user input array?
$attrFound = \in_array(strtolower($attrSubSet[0]), $this->attrArray);
// If the tag is allowed lets keep it
if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) {
// Does the attribute have a value?
if (empty($attrSubSet[1]) === false) {
$newSet[] = $attrSubSet[0] . '="' . $attrSubSet[1] . '"';
} elseif ($attrSubSet[1] === '0') {
// Special Case
// Is the value 0?
$newSet[] = $attrSubSet[0] . '="0"';
} else {
// Leave empty attributes alone
$newSet[] = $attrSubSet[0] . '=""';
}
}
}
return $newSet;
}
/**
* Try to convert to plaintext
*
* @param string $source The source string.
*
* @return string Plaintext string
*
* @since 1.0
* @deprecated This method will be removed once support for PHP 5.3 is discontinued.
*/
protected function decode($source)
{
return html_entity_decode($source, \ENT_QUOTES, 'UTF-8');
}
/**
* Escape < > and " inside attribute values
*
* @param string $source The source string.
*
* @return string Filtered string
*
* @since 1.0
*/
protected function escapeAttributeValues($source)
{
$alreadyFiltered = '';
$remainder = $source;
$badChars = ['<', '"', '>'];
$escapedChars = ['<', '"', '>'];
// Process each portion based on presence of =" and "<space>, "/>, or ">
// See if there are any more attributes to process
while (preg_match('#<[^>]*?=\s*?(\"|\')#s', $remainder, $matches, \PREG_OFFSET_CAPTURE)) {
$stringBeforeTag = substr($remainder, 0, $matches[0][1]);
$tagPosition = strlen($stringBeforeTag);
// Get the character length before the attribute value
$nextBefore = $tagPosition + strlen($matches[0][0]);
// Figure out if we have a single or double quote and look for the matching closing quote
// Closing quote should be "/>, ">, "<space>, or " at the end of the string
$quote = substr($matches[0][0], -1);
$pregMatch = ($quote == '"') ? '#(\"\s*/\s*>|\"\s*>|\"\s+|\"$)#' : "#(\'\s*/\s*>|\'\s*>|\'\s+|\'$)#";
// Get the portion after attribute value
$attributeValueRemainder = substr($remainder, $nextBefore);
if (preg_match($pregMatch, $attributeValueRemainder, $matches, \PREG_OFFSET_CAPTURE)) {
$stringBeforeQuote = substr($attributeValueRemainder, 0, $matches[0][1]);
$closeQuoteChars = strlen($stringBeforeQuote);
$nextAfter = $nextBefore + $closeQuoteChars;
} else {
// No closing quote
$nextAfter = strlen($remainder);
}
// Get the actual attribute value
$attributeValue = substr($remainder, $nextBefore, $nextAfter - $nextBefore);
// Escape bad chars
$attributeValue = str_replace($badChars, $escapedChars, $attributeValue);
$attributeValue = $this->stripCssExpressions($attributeValue);
$alreadyFiltered .= substr($remainder, 0, $nextBefore) . $attributeValue . $quote;
$remainder = substr($remainder, $nextAfter + 1);
}
// At this point, we just have to return the $alreadyFiltered and the $remainder
return $alreadyFiltered . $remainder;
}
/**
* Remove CSS Expressions in the form of <property>:expression(...)
*
* @param string $source The source string.
*
* @return string Filtered string
*
* @since 1.0
*/
protected function stripCssExpressions($source)
{
// Strip any comments out (in the form of /*...*/)
$test = preg_replace('#\/\*.*\*\/#U', '', $source);
// Test for :expression
if (!stripos($test, ':expression')) {
// Not found, so we are done
return $source;
}
// At this point, we have stripped out the comments and have found :expression
// Test stripped string for :expression followed by a '('
if (preg_match_all('#:expression\s*\(#', $test, $matches)) {
// If found, remove :expression
return str_ireplace(':expression', '', $test);
}
return $source;
}
/**
* Integer filter
*
* @param string $source The string to be filtered
*
* @return integer The filtered value
*/
private function cleanInt($source)
{
$pattern = '/[-+]?[0-9]+/';
preg_match($pattern, $source, $matches);
return isset($matches[0]) ? (int) $matches[0] : 0;
}
/**
* Alias for cleanInt()
*
* @param string $source The string to be filtered
*
* @return integer The filtered value
*/
private function cleanInteger($source)
{
return $this->cleanInt($source);
}
/**
* Unsigned integer filter
*
* @param string $source The string to be filtered
*
* @return integer The filtered value
*/
private function cleanUint($source)
{
$pattern = '/[-+]?[0-9]+/';
preg_match($pattern, $source, $matches);
return isset($matches[0]) ? abs((int) $matches[0]) : 0;
}
/**
* Float filter
*
* @param string $source The string to be filtered
*
* @return float The filtered value
*/
private function cleanFloat($source)
{
$pattern = '/[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?/';
preg_match($pattern, $source, $matches);
return isset($matches[0]) ? (float) $matches[0] : 0.0;
}
/**
* Alias for cleanFloat()
*
* @param string $source The string to be filtered
*
* @return float The filtered value
*/
private function cleanDouble($source)
{
return $this->cleanFloat($source);
}
/**
* Boolean filter
*
* @param string $source The string to be filtered
*
* @return boolean The filtered value
*/
private function cleanBool($source)
{
return (bool) $source;
}
/**
* Alias for cleanBool()
*
* @param string $source The string to be filtered
*
* @return boolean The filtered value
*/
private function cleanBoolean($source)
{
return $this->cleanBool($source);
}
/**
* Word filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanWord($source)
{
$pattern = '/[^A-Z_]/i';
return preg_replace($pattern, '', $source);
}
/**
* Alphanumerical filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanAlnum($source)
{
$pattern = '/[^A-Z0-9]/i';
return preg_replace($pattern, '', $source);
}
/**
* Command filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanCmd($source)
{
$pattern = '/[^A-Z0-9_\.-]/i';
$result = preg_replace($pattern, '', $source);
$result = ltrim($result, '.');
return $result;
}
/**
* Base64 filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanBase64($source)
{
$pattern = '/[^A-Z0-9\/+=]/i';
return preg_replace($pattern, '', $source);
}
/**
* String filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanString($source)
{
return $this->remove($this->decode($source));
}
/**
* HTML filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanHtml($source)
{
return $this->remove($source);
}
/**
* Path filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanPath($source)
{
$linuxPattern = '/^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';
if (preg_match($linuxPattern, $source)) {
return preg_replace('~/+~', '/', $source);
}
$windowsPattern = '/^([A-Za-z]:(\\\\|\/))?[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*((\\\\|\/)+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';
if (preg_match($windowsPattern, $source)) {
return preg_replace('~(\\\\|\/)+~', '\\', $source);
}
return '';
}
/**
* Trim filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanTrim($source)
{
$result = trim($source);
$result = StringHelper::trim($result, \chr(0xE3) . \chr(0x80) . \chr(0x80));
$result = StringHelper::trim($result, \chr(0xC2) . \chr(0xA0));
return $result;
}
/**
* Username filter
*
* @param string $source The string to be filtered
*
* @return string The filtered string
*/
private function cleanUsername($source)
{
$pattern = '/[\x00-\x1F\x7F<>"\'%&]/';
return preg_replace($pattern, '', $source);
}
}