PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/DevApp/library/ServerLibraries/ZendFramework/1.7/library/Zend/Filter/StripTags.php

http://firephp.googlecode.com/
PHP | 282 lines | 115 code | 31 blank | 136 comment | 20 complexity | d35508056d68eb7a04b3b358e922ef7e MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Filter
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: StripTags.php 20137 2010-01-07 22:47:10Z matthew $
  20. */
  21. /**
  22. * @see Zend_Filter_Interface
  23. */
  24. require_once 'Zend/Filter/Interface.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_Filter
  28. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Filter_StripTags implements Zend_Filter_Interface
  32. {
  33. /**
  34. * Unique ID prefix used for allowing comments
  35. */
  36. const UNIQUE_ID_PREFIX = '__Zend_Filter_StripTags__';
  37. /**
  38. * Whether comments are allowed
  39. *
  40. * If false (the default), then comments are removed from the input string.
  41. *
  42. * This setting is now deprecated, and ignored internally.
  43. *
  44. * @deprecated
  45. * @var boolean
  46. */
  47. public $commentsAllowed;
  48. /**
  49. * Array of allowed tags and allowed attributes for each allowed tag
  50. *
  51. * Tags are stored in the array keys, and the array values are themselves
  52. * arrays of the attributes allowed for the corresponding tag.
  53. *
  54. * @var array
  55. */
  56. protected $_tagsAllowed = array();
  57. /**
  58. * Array of allowed attributes for all allowed tags
  59. *
  60. * Attributes stored here are allowed for all of the allowed tags.
  61. *
  62. * @var array
  63. */
  64. protected $_attributesAllowed = array();
  65. /**
  66. * Sets the filter options
  67. *
  68. * @param array|string $tagsAllowed
  69. * @param array|string $attributesAllowed
  70. * @param boolean $allowComments
  71. * @return void
  72. */
  73. public function __construct($tagsAllowed = null, $attributesAllowed = null, $commentsAllowed = false)
  74. {
  75. $this->setTagsAllowed($tagsAllowed);
  76. $this->setAttributesAllowed($attributesAllowed);
  77. $this->commentsAllowed = (boolean) $commentsAllowed;
  78. }
  79. /**
  80. * Returns the tagsAllowed option
  81. *
  82. * @return array
  83. */
  84. public function getTagsAllowed()
  85. {
  86. return $this->_tagsAllowed;
  87. }
  88. /**
  89. * Sets the tagsAllowed option
  90. *
  91. * @param array|string $tagsAllowed
  92. * @return Zend_Filter_StripTags Provides a fluent interface
  93. */
  94. public function setTagsAllowed($tagsAllowed)
  95. {
  96. if (!is_array($tagsAllowed)) {
  97. $tagsAllowed = array($tagsAllowed);
  98. }
  99. foreach ($tagsAllowed as $index => $element) {
  100. // If the tag was provided without attributes
  101. if (is_int($index) && is_string($element)) {
  102. // Canonicalize the tag name
  103. $tagName = strtolower($element);
  104. // Store the tag as allowed with no attributes
  105. $this->_tagsAllowed[$tagName] = array();
  106. }
  107. // Otherwise, if a tag was provided with attributes
  108. else if (is_string($index) && (is_array($element) || is_string($element))) {
  109. // Canonicalize the tag name
  110. $tagName = strtolower($index);
  111. // Canonicalize the attributes
  112. if (is_string($element)) {
  113. $element = array($element);
  114. }
  115. // Store the tag as allowed with the provided attributes
  116. $this->_tagsAllowed[$tagName] = array();
  117. foreach ($element as $attribute) {
  118. if (is_string($attribute)) {
  119. // Canonicalize the attribute name
  120. $attributeName = strtolower($attribute);
  121. $this->_tagsAllowed[$tagName][$attributeName] = null;
  122. }
  123. }
  124. }
  125. }
  126. return $this;
  127. }
  128. /**
  129. * Returns the attributesAllowed option
  130. *
  131. * @return array
  132. */
  133. public function getAttributesAllowed()
  134. {
  135. return $this->_attributesAllowed;
  136. }
  137. /**
  138. * Sets the attributesAllowed option
  139. *
  140. * @param array|string $attributesAllowed
  141. * @return Zend_Filter_StripTags Provides a fluent interface
  142. */
  143. public function setAttributesAllowed($attributesAllowed)
  144. {
  145. if (!is_array($attributesAllowed)) {
  146. $attributesAllowed = array($attributesAllowed);
  147. }
  148. // Store each attribute as allowed
  149. foreach ($attributesAllowed as $attribute) {
  150. if (is_string($attribute)) {
  151. // Canonicalize the attribute name
  152. $attributeName = strtolower($attribute);
  153. $this->_attributesAllowed[$attributeName] = null;
  154. }
  155. }
  156. return $this;
  157. }
  158. /**
  159. * Defined by Zend_Filter_Interface
  160. *
  161. * @todo improve docblock descriptions
  162. *
  163. * @param string $value
  164. * @return string
  165. */
  166. public function filter($value)
  167. {
  168. // Strip HTML comments first
  169. $valueCopy = preg_replace('#<!--(?:[^<]+|<(?!\!--))*?(--\s*>)#us', '', (string) $value);
  170. // Initialize accumulator for filtered data
  171. $dataFiltered = '';
  172. // Parse the input data iteratively as regular pre-tag text followed by a
  173. // tag; either may be empty strings
  174. preg_match_all('/([^<]*)(<?[^>]*>?)/', (string) $valueCopy, $matches);
  175. // Iterate over each set of matches
  176. foreach ($matches[1] as $index => $preTag) {
  177. // If the pre-tag text is non-empty, strip any ">" characters from it
  178. if (strlen($preTag)) {
  179. $preTag = str_replace('>', '', $preTag);
  180. }
  181. // If a tag exists in this match, then filter the tag
  182. $tag = $matches[2][$index];
  183. if (strlen($tag)) {
  184. $tagFiltered = $this->_filterTag($tag);
  185. } else {
  186. $tagFiltered = '';
  187. }
  188. // Add the filtered pre-tag text and filtered tag to the data buffer
  189. $dataFiltered .= $preTag . $tagFiltered;
  190. }
  191. // Return the filtered data
  192. return $dataFiltered;
  193. }
  194. /**
  195. * Filters a single tag against the current option settings
  196. *
  197. * @param string $tag
  198. * @return string
  199. */
  200. protected function _filterTag($tag)
  201. {
  202. // Parse the tag into:
  203. // 1. a starting delimiter (mandatory)
  204. // 2. a tag name (if available)
  205. // 3. a string of attributes (if available)
  206. // 4. an ending delimiter (if available)
  207. $isMatch = preg_match('~(</?)(\w*)((/(?!>)|[^/>])*)(/?>)~', $tag, $matches);
  208. // If the tag does not match, then strip the tag entirely
  209. if (!$isMatch) {
  210. return '';
  211. }
  212. // Save the matches to more meaningfully named variables
  213. $tagStart = $matches[1];
  214. $tagName = strtolower($matches[2]);
  215. $tagAttributes = $matches[3];
  216. $tagEnd = $matches[5];
  217. // If the tag is not an allowed tag, then remove the tag entirely
  218. if (!isset($this->_tagsAllowed[$tagName])) {
  219. return '';
  220. }
  221. // Trim the attribute string of whitespace at the ends
  222. $tagAttributes = trim($tagAttributes);
  223. // If there are non-whitespace characters in the attribute string
  224. if (strlen($tagAttributes)) {
  225. // Parse iteratively for well-formed attributes
  226. preg_match_all('/(\w+)\s*=\s*(?:(")(.*?)"|(\')(.*?)\')/s', $tagAttributes, $matches);
  227. // Initialize valid attribute accumulator
  228. $tagAttributes = '';
  229. // Iterate over each matched attribute
  230. foreach ($matches[1] as $index => $attributeName) {
  231. $attributeName = strtolower($attributeName);
  232. $attributeDelimiter = $matches[2][$index];
  233. $attributeValue = $matches[3][$index];
  234. // If the attribute is not allowed, then remove it entirely
  235. if (!array_key_exists($attributeName, $this->_tagsAllowed[$tagName])
  236. && !array_key_exists($attributeName, $this->_attributesAllowed)) {
  237. continue;
  238. }
  239. // Add the attribute to the accumulator
  240. $tagAttributes .= " $attributeName=" . $attributeDelimiter
  241. . $attributeValue . $attributeDelimiter;
  242. }
  243. }
  244. // Reconstruct tags ending with "/>" as backwards-compatible XHTML tag
  245. if (strpos($tagEnd, '/') !== false) {
  246. $tagEnd = " $tagEnd";
  247. }
  248. // Return the filtered tag
  249. return $tagStart . $tagName . $tagAttributes . $tagEnd;
  250. }
  251. }