PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/symfony/2.0.0pr2/src/vendor/symfony/src/Symfony/Components/OutputEscaper/Escaper.php

https://github.com/padraic/php-framework-benchmarks
PHP | 373 lines | 151 code | 41 blank | 181 comment | 20 complexity | 53292f3ef7eb38b9f82ab35a773241ce MD5 | raw file
  1. <?php
  2. namespace Symfony\Components\OutputEscaper;
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * Abstract class that provides an interface for escaping of output.
  13. *
  14. * @package Symfony
  15. * @subpackage Components_OutputEscaper
  16. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  17. * @author Mike Squire <mike@somosis.co.uk>
  18. */
  19. abstract class Escaper
  20. {
  21. /**
  22. * The value that is to be escaped.
  23. *
  24. * @var mixed
  25. */
  26. protected $value;
  27. /**
  28. * The escaper (a PHP callable) that is going to be applied to the value and its
  29. * children.
  30. *
  31. * @var string
  32. */
  33. protected $escaper;
  34. static protected $charset = 'UTF-8';
  35. static protected $safeClasses = array();
  36. static protected $escapers;
  37. /**
  38. * Constructor.
  39. *
  40. * Since Escaper is an abstract class, instances cannot be created
  41. * directly but the constructor will be inherited by sub-classes.
  42. *
  43. * @param string $callable A PHP callable
  44. * @param string $value Escaping value
  45. */
  46. public function __construct($escaper, $value)
  47. {
  48. if (null === self::$escapers) {
  49. self::initializeEscapers();
  50. }
  51. $this->escaper = is_string($escaper) && isset(self::$escapers[$escaper]) ? self::$escapers[$escaper] : $escaper;
  52. $this->value = $value;
  53. }
  54. /**
  55. * Decorates a PHP variable with something that will escape any data obtained
  56. * from it.
  57. *
  58. * The following cases are dealt with:
  59. *
  60. * - The value is null or false: null or false is returned.
  61. * - The value is scalar: the result of applying the escaping method is
  62. * returned.
  63. * - The value is an array or an object that implements the ArrayAccess
  64. * interface: the array is decorated such that accesses to elements yield
  65. * an escaped value.
  66. * - The value implements the Traversable interface (either an Iterator, an
  67. * IteratorAggregate or an internal PHP class that implements
  68. * Traversable): decorated much like the array.
  69. * - The value is another type of object: decorated such that the result of
  70. * method calls is escaped.
  71. *
  72. * The escaping method is actually a PHP callable. This class hosts a set
  73. * of standard escaping strategies.
  74. *
  75. * @param string $escaper The escaping method (a PHP callable) to apply to the value
  76. * @param mixed $value The value to escape
  77. *
  78. * @return mixed Escaped value
  79. *
  80. * @throws \InvalidArgumentException If the escaping fails
  81. */
  82. static public function escape($escaper, $value)
  83. {
  84. if (null === $value) {
  85. return $value;
  86. }
  87. if (null === self::$escapers) {
  88. self::initializeEscapers();
  89. }
  90. if (is_string($escaper) && isset(self::$escapers[$escaper])) {
  91. $escaper = self::$escapers[$escaper];
  92. }
  93. // Scalars are anything other than arrays, objects and resources.
  94. if (is_scalar($value)) {
  95. return call_user_func($escaper, $value);
  96. }
  97. if (is_array($value)) {
  98. return new ArrayDecorator($escaper, $value);
  99. }
  100. if (is_object($value)) {
  101. if ($value instanceof Escaper) {
  102. // avoid double decoration
  103. $copy = clone $value;
  104. $copy->escaper = $escaper;
  105. return $copy;
  106. }
  107. if (self::isClassMarkedAsSafe(get_class($value))) {
  108. // the class or one of its children is marked as safe
  109. // return the unescaped object
  110. return $value;
  111. }
  112. if ($value instanceof SafeDecorator) {
  113. // do not escape objects marked as safe
  114. // return the original object
  115. return $value->getValue();
  116. }
  117. if ($value instanceof \Traversable) {
  118. return new IteratorDecorator($escaper, $value);
  119. }
  120. return new ObjectDecorator($escaper, $value);
  121. }
  122. // it must be a resource; cannot escape that.
  123. throw new \InvalidArgumentException(sprintf('Unable to escape value "%s".', var_export($value, true)));
  124. }
  125. /**
  126. * Unescapes a value that has been escaped previously with the escape() method.
  127. *
  128. * @param mixed $value The value to unescape
  129. *
  130. * @return mixed Unescaped value
  131. *
  132. * @throws \InvalidArgumentException If the escaping fails
  133. */
  134. static public function unescape($value)
  135. {
  136. if (null === $value || is_bool($value)) {
  137. return $value;
  138. }
  139. if (is_scalar($value)) {
  140. return html_entity_decode($value, ENT_QUOTES, self::$charset);
  141. }
  142. if (is_array($value)) {
  143. foreach ($value as $name => $v) {
  144. $value[$name] = self::unescape($v);
  145. }
  146. return $value;
  147. }
  148. if (is_object($value)) {
  149. return $value instanceof Escaper ? $value->getRawValue() : $value;
  150. }
  151. return $value;
  152. }
  153. /**
  154. * Returns true if the class if marked as safe.
  155. *
  156. * @param string $class A class name
  157. *
  158. * @return bool true if the class if safe, false otherwise
  159. */
  160. static public function isClassMarkedAsSafe($class)
  161. {
  162. if (in_array($class, self::$safeClasses)) {
  163. return true;
  164. }
  165. foreach (self::$safeClasses as $safeClass) {
  166. if (is_subclass_of($class, $safeClass)) {
  167. return true;
  168. }
  169. }
  170. return false;
  171. }
  172. /**
  173. * Marks an array of classes (and all its children) as being safe for output.
  174. *
  175. * @param array $classes An array of class names
  176. */
  177. static public function markClassesAsSafe(array $classes)
  178. {
  179. self::$safeClasses = array_unique(array_merge(self::$safeClasses, $classes));
  180. }
  181. /**
  182. * Marks a class (and all its children) as being safe for output.
  183. *
  184. * @param string $class A class name
  185. */
  186. static public function markClassAsSafe($class)
  187. {
  188. self::markClassesAsSafe(array($class));
  189. }
  190. /**
  191. * Returns the raw value associated with this instance.
  192. *
  193. * Concrete instances of Escaper classes decorate a value which is
  194. * stored by the constructor. This returns that original, unescaped, value.
  195. *
  196. * @return mixed The original value used to construct the decorator
  197. */
  198. public function getRawValue()
  199. {
  200. return $this->value;
  201. }
  202. /**
  203. * Gets a value from the escaper.
  204. *
  205. * @param string $var Value to get
  206. *
  207. * @return mixed Value
  208. */
  209. public function __get($var)
  210. {
  211. return $this->escape($this->escaper, $this->value->$var);
  212. }
  213. /**
  214. * Sets the current charset.
  215. *
  216. * @param string $charset The current charset
  217. */
  218. static public function setCharset($charset)
  219. {
  220. self::$charset = $charset;
  221. }
  222. /**
  223. * Gets the current charset.
  224. *
  225. * @return string The current charset
  226. */
  227. static public function getCharset()
  228. {
  229. return self::$charset;
  230. }
  231. /**
  232. * Adds a named escaper.
  233. *
  234. * @param string $name The escaper name
  235. * @param mixed $escaper A PHP callable
  236. */
  237. static public function setEscaper($name, $escaper)
  238. {
  239. self::$escapers[$name] = $escaper;
  240. }
  241. /**
  242. * Initializes the built-in escapers.
  243. *
  244. * Each function specifies a way for applying a transformation to a string
  245. * passed to it. The purpose is for the string to be "escaped" so it is
  246. * suitable for the format it is being displayed in.
  247. *
  248. * For example, the string: "It's required that you enter a username & password.\n"
  249. * If this were to be displayed as HTML it would be sensible to turn the
  250. * ampersand into '&amp;' and the apostrophe into '&aps;'. However if it were
  251. * going to be used as a string in JavaScript to be displayed in an alert box
  252. * it would be right to leave the string as-is, but c-escape the apostrophe and
  253. * the new line.
  254. *
  255. * For each function there is a define to avoid problems with strings being
  256. * incorrectly specified.
  257. */
  258. static function initializeEscapers()
  259. {
  260. self::$escapers = array(
  261. 'htmlspecialchars' =>
  262. /**
  263. * Runs the PHP function htmlspecialchars on the value passed.
  264. *
  265. * @param string $value the value to escape
  266. *
  267. * @return string the escaped value
  268. */
  269. function ($value)
  270. {
  271. // Numbers and boolean values get turned into strings which can cause problems
  272. // with type comparisons (e.g. === or is_int() etc).
  273. return is_string($value) ? htmlspecialchars($value, ENT_QUOTES, Escaper::getCharset()) : $value;
  274. },
  275. 'entities' =>
  276. /**
  277. * Runs the PHP function htmlentities on the value passed.
  278. *
  279. * @param string $value the value to escape
  280. * @return string the escaped value
  281. */
  282. function ($value)
  283. {
  284. // Numbers and boolean values get turned into strings which can cause problems
  285. // with type comparisons (e.g. === or is_int() etc).
  286. return is_string($value) ? htmlentities($value, ENT_QUOTES, Escaper::getCharset()) : $value;
  287. },
  288. 'raw' =>
  289. /**
  290. * An identity function that merely returns that which it is given, the purpose
  291. * being to be able to specify that the value is not to be escaped in any way.
  292. *
  293. * @param string $value the value to escape
  294. * @return string the escaped value
  295. */
  296. function ($value)
  297. {
  298. return $value;
  299. },
  300. 'js' =>
  301. /**
  302. * A function that c-escapes a string after applying (cf. entities). The
  303. * assumption is that the value will be used to generate dynamic HTML in some
  304. * way and the safest way to prevent mishap is to assume the value should have
  305. * HTML entities set properly.
  306. *
  307. * The (cf. js_no_entities) method should be used to escape a string
  308. * that is ultimately not going to end up as text in an HTML document.
  309. *
  310. * @param string $value the value to escape
  311. * @return string the escaped value
  312. */
  313. function ($value)
  314. {
  315. return str_replace(array("\\" , "\n" , "\r" , "\"" , "'" ), array("\\\\", "\\n" , "\\r", "\\\"", "\\'"), (is_string($value) ? htmlentities($value, ENT_QUOTES, Escaper::getCharset()) : $value));
  316. },
  317. 'js_no_entities' =>
  318. /**
  319. * A function the c-escapes a string, making it suitable to be placed in a
  320. * JavaScript string.
  321. *
  322. * @param string $value the value to escape
  323. * @return string the escaped value
  324. */
  325. function ($value)
  326. {
  327. return str_replace(array("\\" , "\n" , "\r" , "\"" , "'" ), array("\\\\", "\\n" , "\\r", "\\\"", "\\'"), $value);
  328. },
  329. );
  330. }
  331. }