Interpret the results of the attribute preg_match_all(). Emit errors as
appropriate and return an associative array.

@param array $matches
@return array
11430
protected function interpretAttribMatches( $matches ) {
		$attributes = [];
		foreach ( $matches as $m ) {
			if ( strlen( $m[self::MA_SLASH][0] ) ) {
				$this->error( 'unexpected bare slash', $m[self::MA_SLASH][1] );
				continue;
			}
			$name = $m[self::MA_NAME][0];
			$isSimple = isset( $m[self::MA_SIMPLE_NAME] ) &&
				( strlen( $name ) === strlen( $m[self::MA_SIMPLE_NAME][0] ) );
			if ( !$isSimple ) {
				// We can skip these steps if we already know the name is simple
				if ( !$this->ignoreErrors ) {
					$this->handleAsciiErrors( "\"'<=", $name, 0, strlen( $name ), $m[self::MA_NAME][1] );
				}
				if ( !$this->ignoreNulls ) {
					$name = $this->handleNulls( $m[self::MA_NAME][0], $m[self::MA_NAME][1] );
				}
				$name = strtolower( $name );
			}
			$additionalAllowedChar = '';
			$isSimple = true;
			if ( isset( $m[self::MA_DQUOTED] ) && $m[self::MA_DQUOTED][1] >= 0 ) {
				// Double-quoted attribute value
				$additionalAllowedChar = '"';
				$value = $m[self::MA_DQUOTED][0];
				$pos = $m[self::MA_DQUOTED][1];
				$isSimple = !strlen( $m[self::MA_DQUOTED_UNSIMPLE][0] );
				if ( $isSimple && strlen( $m[self::MA_DQUOTED_CHARREF][0] ) ) {
					// Efficiently handle well-behaved character references
					$value = strtr( $value, self::$commonEntities );
				}
			} elseif ( isset( $m[self::MA_SQUOTED] ) && $m[self::MA_SQUOTED][1] >= 0 ) {
				// Single-quoted attribute value
				$additionalAllowedChar = "'";
				$value = $m[self::MA_SQUOTED][0];
				$pos = $m[self::MA_SQUOTED][1];
				$isSimple = !strlen( $m[self::MA_SQUOTED_UNSIMPLE][0] );
				if ( $isSimple && strlen( $m[self::MA_SQUOTED_CHARREF][0] ) ) {
					// Efficiently handle well-behaved character references
					$value = strtr( $value, self::$commonEntities );
				}
			} elseif ( isset( $m[self::MA_UNQUOTED] ) && $m[self::MA_UNQUOTED][1] >= 0 ) {
				// Unquoted attribute value
				$value = $m[self::MA_UNQUOTED][0];
				$pos = $m[self::MA_UNQUOTED][1];
				$isSimple = !strlen( $m[self::MA_UNQUOTED_UNSIMPLE][0] );
				// Search for parse errors
				if ( !$this->ignoreErrors ) {
					if ( $value === '' ) {
						// ">" in the before attribute value state is a parse error
						$this->error( 'empty unquoted attribute', $pos );
					}
					if ( !$isSimple ) {
						$this->handleAsciiErrors( "\"'<=`", $value, 0, strlen( $value ), $pos );
					}
				}
			} else {
				$value = '';
			}
			if ( $additionalAllowedChar && !$this->ignoreErrors ) {
				// After attribute value (quoted) state
				// Quoted attributes must be followed by a space, "/" or ">"
				$aavPos = $m[0][1] + strlen( $m[0][0] );
				if ( $aavPos < $this->length ) {
					$aavChar = $this->text[$aavPos];
					if ( !preg_match( '~^[\t\n\f />]~', $aavChar ) ) {
						$this->error( 'missing space between attributes', $aavPos );
					}
				}
			}
			if ( !$isSimple && $value !== '' ) {
				if ( !$this->ignoreNulls ) {
					$value = $this->handleNulls( $value, $pos );
				}
				if ( !$this->ignoreCharRefs ) {
					$value = $this->handleCharRefs( $value, $pos, true, $additionalAllowedChar );
				}
			}
			if ( isset( $attributes[$name] ) ) {
				$this->error( "duplicate attribute", $m[0][1] );
			} else {
				$attributes[$name] = $value;
			}
		}
		return $attributes;
	}
1044859
private function func_arr_params_callback($matches) {
    	$func = $matches[1];
    	$params_str = $matches[2];
        $in_matches = [];
    	preg_match_all("/([a-z_]+)\=[\"\']?([^\"\']+)[\"\']?/i", stripslashes($params_str), $in_matches, PREG_SET_ORDER);
    	$params = null;
    	foreach($in_matches as $v) {
    		$params[$v[1]] = $v[2];
    	}
    	return "<?php print_r( " . $func . "(" . ArrayHelper::toRaw($params) . ') ); ?>';
    }
262643
protected function autolink($matches)
	{
		$href = $matches[0];

		if (substr($href, 0, 1) == '!')
		{
			return substr($href, 1);
		}

		$href = str_replace('"', '', $href);
		$href = str_replace("'", '', $href);
		$href = str_replace('&#8221', '', $href);

		$h = array('h', 'm', 'f', 'g', 'n');
		if (!in_array(substr($href, 0, 1), $h))
		{
			$href = substr($href, 1);
		}
		$name = trim($href);
		if (substr($name, 0, 7) == 'mailto:')
		{
			$name = substr($name, 7, strlen($name));
			$name = Str::obfuscate($name);

			$href = 'mailto:' . $name;
		}
		$l = sprintf(
			' <a class="ext-link" href="%s" rel="external">%s</a>', $href, $name
		);
		return $l;
	}
944642
protected function convertSection(array $matches)
    {
        $params = array();
        $index  = 1;
        while (!empty($matches[$index]) && $index < 13) {
            $params[$matches[$index]] = $matches[$index + 1];
            $index += 2;
        }

        return str_replace('[' . trim($params['name'], '"\'') . ']', '[$' . trim($params['name'], '"\'') . ']', $matches[0]);
    }
132751
protected function parseDocParameter( $matches )
	{
		$parameter	= new ADT_PHP_Parameter( $matches[4], $matches[2] );
		if( isset( $matches[5] ) )
			$parameter->setDescription( $matches[5] );
		return $parameter;
	}
875282
public function compile($matches)
    {
        $variable = rtrim($matches[2], ';');
        
        return $this->compiler->wrap(
            $this->compiler->stringDotsToArrayKeys($variable)
        );
    }
781875
private function findPattern($matches) {
        switch ($matches[1]) {
            case ':num':
                $replacement = '([0-9]';
                break;
            case ':alpha':
                $replacement = '([a-zA-Z]';
                break;
            case ':any':
                $replacement = '([^\/]';
                break;
        }


        if (isset($matches[3]) && is_numeric($matches[3])) {
            if (isset($matches[4]) && $matches[4] == '?') {
                $replacement .= '{0,' . $matches[3] . '})';
            } else {
                $replacement .= '{' . $matches[3] . '})';
            }
        } else {
            if (isset($matches[4]) && $matches[4] == '?') {
                $replacement .= '*)';
            } else {
                $replacement .= '+)';
            }
        }

        return $replacement;
    }
604363
protected function getMatchArgs(array $match)
    {
        // Remove the first element, the matching regex
        array_shift($match);

        // Iterate through the arguments and remove any unwanted slashes
        foreach ($match as &$arg) {
            $arg = trim($arg, '/');
        }

        return $match;
    }
284920
private function orElseMatch(Match $match)
    {
        return array_key_exists($this->subject->getName(), $this->matches)
            ? $this->matches[$this->subject->getName()]->get()
            : $match->get();
    }
390986
public function match(array $matches) {
        $params = explode(' ', $matches[1]);
        $paramsNum = count($params);
        $this->params[] = $params[0];

        if (1 == $paramsNum) {
            return sprintf($this->defaultRegx['char'], '+');
        }
        else if (2 == $paramsNum) {
            return sprintf($this->defaultRegx[$params[1]], '+');
        }
        else if (3 == $paramsNum) {
            return sprintf($this->defaultRegx[$params[1]], $params[2] > 0 ? '{' . $params[2] . '}' : '*');
        }
        else if (4 == $paramsNum) {
            return sprintf($this->defaultRegx[$params[1]], '{' . $params[2] . ',' . $params[3] . '}');
        }
    }
581318
private function computeUrlRegex(array $matches)
    {
        $this->names[] = $matches[1];

        if (isset($this->conditions[$matches[1]])) {
            return '(?P<' . $matches[1] . '>' . $this->conditions[$matches[1]] . ')';
        }

        if (substr($matches[0], -1) === '+') {

            $this->namesPath[$matches[1]] = 1;

            return '(?P<' . $matches[1] . '>.+)';
        }

        return '(?P<' . $matches[1] . '>[^/]+)';
    }
307803
protected function calculeInverted(array $matches): string
    {
        $prefix = $matches[1];
        $negation = '' === $matches[2] ? 'Not' : '';
        $name = $matches[3];

        $inverted = sprintf('%s%s%s', $prefix, $negation, $name);

        return $inverted;
    }
2158
protected static function sanitizeNaughtyHTML($matches)
    {
        // First, escape unclosed tags
        if (empty($matches[ 'closeTag' ])) {
            return '&lt;' . $matches[ 1 ];
        } // Is the element that we caught naughty? If so, escape it
        elseif (in_array(strtolower($matches[ 'tagName' ]), self::getConfig('naughty_tags'), true)) {
            return '&lt;' . $matches[ 1 ] . '&gt;';
        } // For other tags, see if their attributes are "evil" and strip those
        elseif (isset($matches[ 'attributes' ])) {
            // We'll store the already fitlered attributes here
            $attributes = [];

            // Attribute-catching pattern
            $attributesPattern = '#'
                . '(?<name>[^\s\042\047>/=]+)'
                // attribute characters
                // optional attribute-value
                . '(?:\s*=(?<value>[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*)))'
                // attribute-value separator
                . '#i';

            // Blacklist pattern for evil attribute names
            $is_evil_pattern = '#^(' . implode('|', self::getConfig('evil_attributes')) . ')$#i';

            // Each iteration filters a single attribute
            do {
                // Strip any non-alpha characters that may preceed an attribute.
                // Browsers often parse these incorrectly and that has been a
                // of numerous XSS issues we've had.
                $matches[ 'attributes' ] = preg_replace('#^[^a-z]+#i', '', $matches[ 'attributes' ]);

                if ( ! preg_match($attributesPattern, $matches[ 'attributes' ], $attribute, PREG_OFFSET_CAPTURE)) {
                    // No (valid) attribute found? Discard everything else inside the tag
                    break;
                }

                if (
                    // Is it indeed an "evil" attribute?
                    preg_match($is_evil_pattern, $attribute[ 'name' ][ 0 ])
                    // Or does it have an equals sign, but no value and not quoted? Strip that too!
                    OR (trim($attribute[ 'value' ][ 0 ]) === '')
                ) {
                    $attributes[] = 'xss=removed';
                } else {
                    $attributes[] = $attribute[ 0 ][ 0 ];
                }

                $matches[ 'attributes' ] = substr(
                    $matches[ 'attributes' ],
                    $attribute[ 0 ][ 1 ] + strlen($attribute[ 0 ][ 0 ])
                );
            } while ($matches[ 'attributes' ] !== '');
            $attributes = empty($attributes)
                ? ''
                : ' ' . implode(' ', $attributes);

            return '<' . $matches[ 'slash' ] . $matches[ 'tagName' ] . $attributes . '>';
        }

        return $matches[ 0 ];
    }
1303051
private function html_attr($matches){
		
		// could be empty?
		$url = trim($matches[2]);
		
		$schemes = array('data:', 'magnet:', 'about:', 'javascript:', 'mailto:', 'tel:', 'ios-app:', 'android-app:');
		if(starts_with($url, $schemes)){
			return $matches[0];
		}
		
		return str_replace($url, proxify_url($url, $this->base_url), $matches[0]);
	}
1009846
protected static function expandMatch(array $matches)
    {
        $parsed = self::parseExpression($matches[1]);
        $replacements = [];

        $prefix = $parsed['operator'];
        $separator = $parsed['operator'];
        $queryStringShouldBeUsed = false;
        switch ($parsed['operator']) {
            case '?':
                $separator = '&';
                $queryStringShouldBeUsed = true;
                break;
            case '#':
                $separator = ',';
                break;
            case '&':
            case ';':
                $queryStringShouldBeUsed = true;
                break;
            case '+':
            case '':
                $separator = ',';
                $prefix = '';
                break;
        }

        foreach ($parsed['values'] as $value) {
            if (!array_key_exists($value['value'], self::$variables) || self::$variables[$value['value']] === null) {
                continue;
            }

            $variable = self::$variables[$value['value']];
            $useQueryString = $queryStringShouldBeUsed;

            if (is_array($variable)) {
                $expanded = self::encodeArrayVariable($variable, $value, $parsed['operator'], $separator, $useQueryString);
            } else {
                if ($value['modifier'] === ':') {
                    $variable = substr($variable, 0, $value['position']);
                }
                $expanded = rawurlencode($variable);
                if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
                    $expanded = self::decodeReservedDelimiters($expanded);
                }
            }

            if ($useQueryString) {
                if ($expanded === '' && $separator !== '&') {
                    $expanded = $value['value'];
                } else {
                    $expanded = $value['value'] . '=' . $expanded;
                }
            }

            $replacements[] = $expanded;
        }

        $result = implode($separator, $replacements);
        if ($result !== '' && $prefix !== '') {
            return $prefix . $result;
        }

        return $result;
    }
577044
private function generateResults(array $matches): Generator
    {
        foreach ($matches as $match) {
            if ($match[1] == '[' && $match[6] == ']') {
                continue;
            }
            yield [
                'tag'        => $match[2],
                'content'    => isset($match[5]) ? $match[5] : null,
                'attributes' => isset($match[3]) ? $this->parseAttributes($match[3]) : [],
            ];
        }
    }
30065
private function decodeMatchedEntity($matches)
    {
        $body = $matches[4];
        if (strtoupper($matches[3]) === 'Q') {
            $body = quoted_printable_decode(str_replace('_', '=20', $body));
        } else {
            $body = base64_decode($body);
        }
        $language = $matches[2];
        $decoded = $this->convertEncoding($body, $matches[1], true);
        $this->addToLanguage($decoded, $language);
        return $decoded;
    }