1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
<?php
/*
* This file is part of SwiftMailer.
* (c) 2004-2009 Chris Corbyn
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Processes bytes as they pass through a buffer and replaces sequences in it.
*
* This stream filter deals with Byte arrays rather than simple strings.
*
* @author Chris Corbyn
*/
class Swift_StreamFilters_ByteArrayReplacementFilter implements Swift_StreamFilter
{
/** The needle(s) to search for */
private $_search;
/** The replacement(s) to make */
private $_replace;
/** The Index for searching */
private $_index;
/** The Search Tree */
private $_tree = array();
/** Gives the size of the largest search */
private $_treeMaxLen = 0;
private $_repSize;
/**
* Create a new ByteArrayReplacementFilter with $search and $replace.
*
* @param array $search
* @param array $replace
*/
public function __construct($search, $replace)
{
$this->_search = $search;
$this->_index = array();
$this->_tree = array();
$this->_replace = array();
$this->_repSize = array();
$tree = null;
$i = null;
$last_size = $size = 0;
foreach ($search as $i => $search_element) {
if ($tree !== null) {
$tree[-1] = min (count($replace) - 1, $i - 1);
$tree[-2] = $last_size;
}
$tree = &$this->_tree;
if (is_array ($search_element)) {
foreach ($search_element as $k => $char) {
$this->_index[$char] = true;
if (!isset($tree[$char])) {
$tree[$char] = array();
}
$tree = &$tree[$char];
}
$last_size = $k+1;
$size = max($size, $last_size);
} else {
$last_size = 1;
if (!isset($tree[$search_element])) {
$tree[$search_element] = array();
}
$tree = &$tree[$search_element];
$size = max($last_size, $size);
$this->_index[$search_element] = true;
}
}
if ($i !== null) {
$tree[-1] = min (count ($replace) - 1, $i);
$tree[-2] = $last_size;
$this->_treeMaxLen = $size;
}
foreach ($replace as $rep) {
if (!is_array($rep)) {
$rep = array ($rep);
}
$this->_replace[] = $rep;
}
for ($i = count($this->_replace) - 1; $i >= 0; --$i) {
$this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
$this->_repSize[$i] = count($rep);
}
}
/**
* Returns true if based on the buffer passed more bytes should be buffered.
*
* @param array $buffer
*
* @return bool
*/
public function shouldBuffer($buffer)
{
$endOfBuffer = end($buffer);
return isset ($this->_index[$endOfBuffer]);
}
/**
* Perform the actual replacements on $buffer and return the result.
*
* @param array $buffer
* @param int $_minReplaces
*
* @return array
*/
public function filter($buffer, $_minReplaces = -1)
{
if ($this->_treeMaxLen == 0) {
return $buffer;
}
$newBuffer = array();
$buf_size = count($buffer);
for ($i = 0; $i < $buf_size; ++$i) {
$search_pos = $this->_tree;
$last_found = PHP_INT_MAX;
// We try to find if the next byte is part of a search pattern
for ($j = 0; $j <= $this->_treeMaxLen; ++$j) {
// We have a new byte for a search pattern
if (isset ($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]])) {
$search_pos = $search_pos[$buffer[$p]];
// We have a complete pattern, save, in case we don't find a better match later
if (isset($search_pos[- 1]) && $search_pos[-1] < $last_found
&& $search_pos[-1] > $_minReplaces) {
$last_found = $search_pos[-1];
$last_size = $search_pos[-2];
}
}
// We got a complete pattern
elseif ($last_found !== PHP_INT_MAX) {
// Adding replacement datas to output buffer
$rep_size = $this->_repSize[$last_found];
for ($j = 0; $j < $rep_size; ++$j) {
$newBuffer[] = $this->_replace[$last_found][$j];
}
// We Move cursor forward
$i += $last_size - 1;
// Edge Case, last position in buffer
if ($i >= $buf_size) {
$newBuffer[] = $buffer[$i];
}
// We start the next loop
continue 2;
} else {
// this byte is not in a pattern and we haven't found another pattern
break;
}
}
// Normal byte, move it to output buffer
$newBuffer[] = $buffer[$i];
}
return $newBuffer;
}
}
|