Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/*
4
 * This file is part of the symfony package.
5
 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
 
11
/**
12
 * Abstract class that provides an interface for escaping of output.
13
 *
14
 * @package    symfony
15
 * @subpackage view
16
 * @author     Mike Squire <mike@somosis.co.uk>
17
 * @version    SVN: $Id: sfOutputEscaper.class.php 21908 2009-09-11 12:06:21Z fabien $
18
 */
19
abstract class sfOutputEscaper
20
{
21
  /**
22
   * The value that is to be escaped.
23
   *
24
   * @var mixed
25
   */
26
  protected $value;
27
 
28
  /**
29
   * The escaping method that is going to be applied to the value and its
30
   * children. This is actually the name of a PHP callable.
31
   *
32
   * @var string
33
   */
34
  protected $escapingMethod;
35
 
36
  static protected $safeClasses = array();
37
 
38
  /**
39
   * Constructor stores the escaping method and value.
40
   *
41
   * Since sfOutputEscaper is an abstract class, instances cannot be created
42
   * directly but the constructor will be inherited by sub-classes.
43
   *
44
   * @param string $escapingMethod  Escaping method
45
   * @param string $value           Escaping value
46
   */
47
  public function __construct($escapingMethod, $value)
48
  {
49
    $this->value          = $value;
50
    $this->escapingMethod = $escapingMethod;
51
  }
52
 
53
  /**
54
   * Decorates a PHP variable with something that will escape any data obtained
55
   * from it.
56
   *
57
   * The following cases are dealt with:
58
   *
59
   *    - The value is null or false: null or false is returned.
60
   *    - The value is scalar: the result of applying the escaping method is
61
   *      returned.
62
   *    - The value is an array or an object that implements the ArrayAccess
63
   *      interface: the array is decorated such that accesses to elements yield
64
   *      an escaped value.
65
   *    - The value implements the Traversable interface (either an Iterator, an
66
   *      IteratorAggregate or an internal PHP class that implements
67
   *      Traversable): decorated much like the array.
68
   *    - The value is another type of object: decorated such that the result of
69
   *      method calls is escaped.
70
   *
71
   * The escaping method is actually the name of a PHP callable. There are a set
72
   * of standard escaping methods listed in the escaping helper
73
   * (EscapingHelper.php).
74
   *
75
   * @param  string $escapingMethod  The escaping method (a PHP callable) to apply to the value
76
   * @param  mixed  $value           The value to escape
77
   *
78
   * @return mixed Escaping value
79
   *
80
   * @throws InvalidArgumentException If the escaping fails
81
   */
82
  public static function escape($escapingMethod, $value)
83
  {
84
    if (null === $value)
85
    {
86
      return $value;
87
    }
88
 
89
    // Scalars are anything other than arrays, objects and resources.
90
    if (is_scalar($value))
91
    {
92
      return call_user_func($escapingMethod, $value);
93
    }
94
 
95
    if (is_array($value))
96
    {
97
      return new sfOutputEscaperArrayDecorator($escapingMethod, $value);
98
    }
99
 
100
    if (is_object($value))
101
    {
102
      if ($value instanceof sfOutputEscaper)
103
      {
104
        // avoid double decoration
105
        $copy = clone $value;
106
 
107
        $copy->escapingMethod = $escapingMethod;
108
 
109
        return $copy;
110
      }
111
      else if (self::isClassMarkedAsSafe(get_class($value)))
112
      {
113
        // the class or one of its children is marked as safe
114
        // return the unescaped object
115
        return $value;
116
      }
117
      else if ($value instanceof sfOutputEscaperSafe)
118
      {
119
        // do not escape objects marked as safe
120
        // return the original object
121
        return $value->getValue();
122
      }
123
      else if ($value instanceof Traversable)
124
      {
125
        return new sfOutputEscaperIteratorDecorator($escapingMethod, $value);
126
      }
127
      else
128
      {
129
        return new sfOutputEscaperObjectDecorator($escapingMethod, $value);
130
      }
131
    }
132
 
133
    // it must be a resource; cannot escape that.
134
    throw new InvalidArgumentException(sprintf('Unable to escape value "%s".', var_export($value, true)));
135
  }
136
 
137
  /**
138
   * Unescapes a value that has been escaped previously with the escape() method.
139
   *
140
   * @param  mixed $value The value to unescape
141
   *
142
   * @return mixed Unescaped value
143
   *
144
   * @throws InvalidArgumentException If the escaping fails
145
   */
146
  static public function unescape($value)
147
  {
148
    if (null === $value || is_bool($value))
149
    {
150
      return $value;
151
    }
152
 
153
    if (is_scalar($value))
154
    {
155
      return html_entity_decode($value, ENT_QUOTES, sfConfig::get('sf_charset'));
156
    }
157
    elseif (is_array($value))
158
    {
159
      foreach ($value as $name => $v)
160
      {
161
        $value[$name] = self::unescape($v);
162
      }
163
 
164
      return $value;
165
    }
166
    elseif (is_object($value))
167
    {
168
      return $value instanceof sfOutputEscaper ? $value->getRawValue() : $value;
169
    }
170
 
171
    return $value;
172
  }
173
 
174
  /**
175
   * Returns true if the class if marked as safe.
176
   *
177
   * @param  string  $class  A class name
178
   *
179
   * @return bool true if the class if safe, false otherwise
180
   */
181
  static public function isClassMarkedAsSafe($class)
182
  {
183
    if (in_array($class, self::$safeClasses))
184
    {
185
      return true;
186
    }
187
 
188
    foreach (self::$safeClasses as $safeClass)
189
    {
190
      if (is_subclass_of($class, $safeClass))
191
      {
192
        return true;
193
      }
194
    }
195
 
196
    return false;
197
  }
198
 
199
  /**
200
   * Marks an array of classes (and all its children) as being safe for output.
201
   *
202
   * @param array $classes  An array of class names
203
   */
204
  static public function markClassesAsSafe(array $classes)
205
  {
206
    self::$safeClasses = array_unique(array_merge(self::$safeClasses, $classes));
207
  }
208
 
209
  /**
210
   * Marks a class (and all its children) as being safe for output.
211
   *
212
   * @param string $class  A class name
213
   */
214
  static public function markClassAsSafe($class)
215
  {
216
    self::markClassesAsSafe(array($class));
217
  }
218
 
219
  /**
220
   * Returns the raw value associated with this instance.
221
   *
222
   * Concrete instances of sfOutputEscaper classes decorate a value which is
223
   * stored by the constructor. This returns that original, unescaped, value.
224
   *
225
   * @return mixed The original value used to construct the decorator
226
   */
227
  public function getRawValue()
228
  {
229
    return $this->value;
230
  }
231
 
232
  /**
233
   * Gets a value from the escaper.
234
   *
235
   * @param  string $var  Value to get
236
   *
237
   * @return mixed Value
238
   */
239
  public function __get($var)
240
  {
241
    return $this->escape($this->escapingMethod, $this->value->$var);
242
  }
243
}