Security update for Core, with self-updated composer
[yaffs-website] / vendor / sebastian / global-state / src / Snapshot.php
1 <?php
2 /*
3  * This file is part of the GlobalState package.
4  *
5  * (c) Sebastian Bergmann <sebastian@phpunit.de>
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 namespace SebastianBergmann\GlobalState;
12
13 use ReflectionClass;
14 use Serializable;
15
16 /**
17  * A snapshot of global state.
18  */
19 class Snapshot
20 {
21     /**
22      * @var Blacklist
23      */
24     private $blacklist;
25
26     /**
27      * @var array
28      */
29     private $globalVariables = array();
30
31     /**
32      * @var array
33      */
34     private $superGlobalArrays = array();
35
36     /**
37      * @var array
38      */
39     private $superGlobalVariables = array();
40
41     /**
42      * @var array
43      */
44     private $staticAttributes = array();
45
46     /**
47      * @var array
48      */
49     private $iniSettings = array();
50
51     /**
52      * @var array
53      */
54     private $includedFiles = array();
55
56     /**
57      * @var array
58      */
59     private $constants = array();
60
61     /**
62      * @var array
63      */
64     private $functions = array();
65
66     /**
67      * @var array
68      */
69     private $interfaces = array();
70
71     /**
72      * @var array
73      */
74     private $classes = array();
75
76     /**
77      * @var array
78      */
79     private $traits = array();
80
81     /**
82      * Creates a snapshot of the current global state.
83      *
84      * @param Blacklist $blacklist
85      * @param bool      $includeGlobalVariables
86      * @param bool      $includeStaticAttributes
87      * @param bool      $includeConstants
88      * @param bool      $includeFunctions
89      * @param bool      $includeClasses
90      * @param bool      $includeInterfaces
91      * @param bool      $includeTraits
92      * @param bool      $includeIniSettings
93      * @param bool      $includeIncludedFiles
94      */
95     public function __construct(Blacklist $blacklist = null, $includeGlobalVariables = true, $includeStaticAttributes = true, $includeConstants = true, $includeFunctions = true, $includeClasses = true, $includeInterfaces = true, $includeTraits = true, $includeIniSettings = true, $includeIncludedFiles = true)
96     {
97         if ($blacklist === null) {
98             $blacklist = new Blacklist;
99         }
100
101         $this->blacklist = $blacklist;
102
103         if ($includeConstants) {
104             $this->snapshotConstants();
105         }
106
107         if ($includeFunctions) {
108             $this->snapshotFunctions();
109         }
110
111         if ($includeClasses || $includeStaticAttributes) {
112             $this->snapshotClasses();
113         }
114
115         if ($includeInterfaces) {
116             $this->snapshotInterfaces();
117         }
118
119         if ($includeGlobalVariables) {
120             $this->setupSuperGlobalArrays();
121             $this->snapshotGlobals();
122         }
123
124         if ($includeStaticAttributes) {
125             $this->snapshotStaticAttributes();
126         }
127
128         if ($includeIniSettings) {
129             $this->iniSettings = ini_get_all(null, false);
130         }
131
132         if ($includeIncludedFiles) {
133             $this->includedFiles = get_included_files();
134         }
135
136         if (function_exists('get_declared_traits')) {
137             $this->traits = get_declared_traits();
138         }
139     }
140
141     /**
142      * @return Blacklist
143      */
144     public function blacklist()
145     {
146         return $this->blacklist;
147     }
148
149     /**
150      * @return array
151      */
152     public function globalVariables()
153     {
154         return $this->globalVariables;
155     }
156
157     /**
158      * @return array
159      */
160     public function superGlobalVariables()
161     {
162         return $this->superGlobalVariables;
163     }
164
165     /**
166      * Returns a list of all super-global variable arrays.
167      *
168      * @return array
169      */
170     public function superGlobalArrays()
171     {
172         return $this->superGlobalArrays;
173     }
174
175     /**
176      * @return array
177      */
178     public function staticAttributes()
179     {
180         return $this->staticAttributes;
181     }
182
183     /**
184      * @return array
185      */
186     public function iniSettings()
187     {
188         return $this->iniSettings;
189     }
190
191     /**
192      * @return array
193      */
194     public function includedFiles()
195     {
196         return $this->includedFiles;
197     }
198
199     /**
200      * @return array
201      */
202     public function constants()
203     {
204         return $this->constants;
205     }
206
207     /**
208      * @return array
209      */
210     public function functions()
211     {
212         return $this->functions;
213     }
214
215     /**
216      * @return array
217      */
218     public function interfaces()
219     {
220         return $this->interfaces;
221     }
222
223     /**
224      * @return array
225      */
226     public function classes()
227     {
228         return $this->classes;
229     }
230
231     /**
232      * @return array
233      */
234     public function traits()
235     {
236         return $this->traits;
237     }
238
239     /**
240      * Creates a snapshot user-defined constants.
241      */
242     private function snapshotConstants()
243     {
244         $constants = get_defined_constants(true);
245
246         if (isset($constants['user'])) {
247             $this->constants = $constants['user'];
248         }
249     }
250
251     /**
252      * Creates a snapshot user-defined functions.
253      */
254     private function snapshotFunctions()
255     {
256         $functions = get_defined_functions();
257
258         $this->functions = $functions['user'];
259     }
260
261     /**
262      * Creates a snapshot user-defined classes.
263      */
264     private function snapshotClasses()
265     {
266         foreach (array_reverse(get_declared_classes()) as $className) {
267             $class = new ReflectionClass($className);
268
269             if (!$class->isUserDefined()) {
270                 break;
271             }
272
273             $this->classes[] = $className;
274         }
275
276         $this->classes = array_reverse($this->classes);
277     }
278
279     /**
280      * Creates a snapshot user-defined interfaces.
281      */
282     private function snapshotInterfaces()
283     {
284         foreach (array_reverse(get_declared_interfaces()) as $interfaceName) {
285             $class = new ReflectionClass($interfaceName);
286
287             if (!$class->isUserDefined()) {
288                 break;
289             }
290
291             $this->interfaces[] = $interfaceName;
292         }
293
294         $this->interfaces = array_reverse($this->interfaces);
295     }
296
297     /**
298      * Creates a snapshot of all global and super-global variables.
299      */
300     private function snapshotGlobals()
301     {
302         $superGlobalArrays = $this->superGlobalArrays();
303
304         foreach ($superGlobalArrays as $superGlobalArray) {
305             $this->snapshotSuperGlobalArray($superGlobalArray);
306         }
307
308         foreach (array_keys($GLOBALS) as $key) {
309             if ($key != 'GLOBALS' &&
310                 !in_array($key, $superGlobalArrays) &&
311                 $this->canBeSerialized($GLOBALS[$key]) &&
312                 !$this->blacklist->isGlobalVariableBlacklisted($key)) {
313                 $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key]));
314             }
315         }
316     }
317
318     /**
319      * Creates a snapshot a super-global variable array.
320      *
321      * @param $superGlobalArray
322      */
323     private function snapshotSuperGlobalArray($superGlobalArray)
324     {
325         $this->superGlobalVariables[$superGlobalArray] = array();
326
327         if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
328             foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
329                 $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value));
330             }
331         }
332     }
333
334     /**
335      * Creates a snapshot of all static attributes in user-defined classes.
336      */
337     private function snapshotStaticAttributes()
338     {
339         foreach ($this->classes as $className) {
340             $class    = new ReflectionClass($className);
341             $snapshot = array();
342
343             foreach ($class->getProperties() as $attribute) {
344                 if ($attribute->isStatic()) {
345                     $name = $attribute->getName();
346
347                     if ($this->blacklist->isStaticAttributeBlacklisted($className, $name)) {
348                         continue;
349                     }
350
351                     $attribute->setAccessible(true);
352                     $value = $attribute->getValue();
353
354                     if ($this->canBeSerialized($value)) {
355                         $snapshot[$name] = unserialize(serialize($value));
356                     }
357                 }
358             }
359
360             if (!empty($snapshot)) {
361                 $this->staticAttributes[$className] = $snapshot;
362             }
363         }
364     }
365
366     /**
367      * Returns a list of all super-global variable arrays.
368      *
369      * @return array
370      */
371     private function setupSuperGlobalArrays()
372     {
373         $this->superGlobalArrays = array(
374             '_ENV',
375             '_POST',
376             '_GET',
377             '_COOKIE',
378             '_SERVER',
379             '_FILES',
380             '_REQUEST'
381         );
382
383         if (ini_get('register_long_arrays') == '1') {
384             $this->superGlobalArrays = array_merge(
385                 $this->superGlobalArrays,
386                 array(
387                     'HTTP_ENV_VARS',
388                     'HTTP_POST_VARS',
389                     'HTTP_GET_VARS',
390                     'HTTP_COOKIE_VARS',
391                     'HTTP_SERVER_VARS',
392                     'HTTP_POST_FILES'
393                 )
394             );
395         }
396     }
397
398     /**
399      * @param  mixed $variable
400      * @return bool
401      * @todo   Implement this properly
402      */
403     private function canBeSerialized($variable)
404     {
405         if (!is_object($variable)) {
406             return !is_resource($variable);
407         }
408
409         if ($variable instanceof \stdClass) {
410             return true;
411         }
412
413         $class = new ReflectionClass($variable);
414
415         do {
416             if ($class->isInternal()) {
417                 return $variable instanceof Serializable;
418             }
419         } while ($class = $class->getParentClass());
420
421         return true;
422     }
423 }