This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | class TimberLoader { |
||
4 | |||
5 | const CACHEGROUP = 'timberloader'; |
||
6 | |||
7 | const TRANS_KEY_LEN = 50; |
||
8 | |||
9 | const CACHE_NONE = 'none'; |
||
10 | const CACHE_OBJECT = 'cache'; |
||
11 | const CACHE_TRANSIENT = 'transient'; |
||
12 | const CACHE_SITE_TRANSIENT = 'site-transient'; |
||
13 | const CACHE_USE_DEFAULT = 'default'; |
||
14 | |||
15 | public static $cache_modes = array( |
||
16 | self::CACHE_NONE, |
||
17 | self::CACHE_OBJECT, |
||
18 | self::CACHE_TRANSIENT, |
||
19 | self::CACHE_SITE_TRANSIENT |
||
20 | ); |
||
21 | |||
22 | protected $cache_mode = self::CACHE_TRANSIENT; |
||
23 | |||
24 | public $locations; |
||
25 | |||
26 | /** |
||
27 | * @param bool|string $caller the calling directory or false |
||
28 | */ |
||
29 | function __construct($caller = false) { |
||
30 | $this->locations = $this->get_locations($caller); |
||
31 | $this->cache_mode = apply_filters('timber_cache_mode', $this->cache_mode); |
||
32 | $this->cache_mode = apply_filters('timber/cache/mode', $this->cache_mode); |
||
33 | } |
||
34 | |||
35 | /** |
||
36 | * @param string $file |
||
37 | * @param array $data |
||
38 | * @param bool $expires |
||
39 | * @param string $cache_mode |
||
40 | * @return bool|string |
||
41 | */ |
||
42 | function render($file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
43 | // Different $expires if user is anonymous or logged in |
||
44 | if (is_array($expires)) { |
||
45 | if (is_user_logged_in() && isset($expires[1])) { |
||
46 | $expires = $expires[1]; |
||
47 | } else { |
||
48 | $expires = $expires[0]; |
||
49 | } |
||
50 | } |
||
51 | |||
52 | $key = null; |
||
53 | $output = false; |
||
54 | if (false !== $expires) { |
||
55 | ksort($data); |
||
56 | $key = md5($file . json_encode($data)); |
||
57 | $output = $this->get_cache($key, self::CACHEGROUP, $cache_mode); |
||
58 | } |
||
59 | |||
60 | if (false === $output || null === $output) { |
||
61 | $twig = $this->get_twig(); |
||
62 | if (strlen($file)) { |
||
63 | $loader = $this->get_loader(); |
||
64 | $result = $loader->getCacheKey($file); |
||
65 | do_action('timber_loader_render_file', $result); |
||
66 | } |
||
67 | $data = apply_filters('timber_loader_render_data', $data); |
||
68 | $data = apply_filters('timber/loader/render_data', $data); |
||
69 | $output = $twig->render($file, $data); |
||
70 | } |
||
71 | |||
72 | if (false !== $output && false !== $expires && null !== $key) { |
||
73 | $this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode); |
||
74 | } |
||
75 | $output = apply_filters('timber_output', $output); |
||
76 | return apply_filters('timber/output', $output); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * @param array $filenames |
||
81 | * @return bool |
||
82 | */ |
||
83 | public function choose_template($filenames) { |
||
84 | if (is_array($filenames)) { |
||
85 | /* its an array so we have to figure out which one the dev wants */ |
||
86 | foreach ($filenames as $filename) { |
||
87 | if (self::template_exists($filename)) { |
||
88 | return $filename; |
||
89 | } |
||
90 | } |
||
91 | return $filenames[0]; |
||
92 | } |
||
93 | return $filenames; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * @param string $file |
||
98 | * @return bool |
||
99 | */ |
||
100 | protected function template_exists($file) { |
||
101 | foreach ($this->locations as $dir) { |
||
102 | $look_for = trailingslashit($dir) . $file; |
||
103 | if (file_exists($look_for)) { |
||
104 | return true; |
||
105 | } |
||
106 | } |
||
107 | return false; |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * @return array |
||
112 | */ |
||
113 | function get_locations_theme() { |
||
114 | $theme_locs = array(); |
||
115 | $child_loc = get_stylesheet_directory(); |
||
116 | $parent_loc = get_template_directory(); |
||
117 | if (DIRECTORY_SEPARATOR == '\\') { |
||
118 | $child_loc = str_replace('/', '\\', $child_loc); |
||
119 | $parent_loc = str_replace('/', '\\', $parent_loc); |
||
120 | } |
||
121 | $theme_locs[] = $child_loc; |
||
122 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
123 | $theme_locs[] = trailingslashit($child_loc) . trailingslashit($dirname); |
||
124 | } |
||
125 | if ($child_loc != $parent_loc) { |
||
126 | $theme_locs[] = $parent_loc; |
||
127 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
128 | $theme_locs[] = trailingslashit($parent_loc) . trailingslashit($dirname); |
||
129 | } |
||
130 | } |
||
131 | //now make sure theres a trailing slash on everything |
||
132 | $theme_locs = array_map('trailingslashit', $theme_locs); |
||
133 | return $theme_locs; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * returns an array of the directory inside themes that holds twig files |
||
138 | * @return string[] the names of directores, ie: array('templats', 'views'); |
||
139 | */ |
||
140 | private function get_locations_theme_dir() { |
||
141 | if (is_string(Timber::$dirname)) { |
||
142 | return array(Timber::$dirname); |
||
143 | } |
||
144 | return Timber::$dirname; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * @return array |
||
149 | */ |
||
150 | function get_locations_user() { |
||
151 | $locs = array(); |
||
152 | if (isset(Timber::$locations)) { |
||
153 | if (is_string(Timber::$locations)) { |
||
154 | Timber::$locations = array(Timber::$locations); |
||
155 | } |
||
156 | foreach (Timber::$locations as $tloc) { |
||
157 | $tloc = realpath($tloc); |
||
158 | if (is_dir($tloc)) { |
||
159 | $locs[] = $tloc; |
||
160 | } |
||
161 | } |
||
162 | } |
||
163 | return $locs; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @param bool|string $caller the calling directory |
||
168 | * @return array |
||
169 | */ |
||
170 | function get_locations_caller($caller = false) { |
||
171 | $locs = array(); |
||
172 | if ($caller && is_string($caller)) { |
||
173 | $caller = trailingslashit($caller); |
||
174 | if (is_dir($caller)) { |
||
175 | $locs[] = $caller; |
||
176 | } |
||
177 | foreach ($this->get_locations_theme_dir() as $dirname) { |
||
178 | $caller_sub = $caller . trailingslashit($dirname); |
||
179 | if (is_dir($caller_sub)) { |
||
180 | $locs[] = $caller_sub; |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | return $locs; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * @param bool|string $caller the calling directory (or false) |
||
189 | * @return array |
||
190 | */ |
||
191 | function get_locations($caller = false) { |
||
192 | //prioirty: user locations, caller (but not theme), child theme, parent theme, caller |
||
193 | $locs = array(); |
||
194 | $locs = array_merge($locs, $this->get_locations_user()); |
||
195 | $locs = array_merge($locs, $this->get_locations_caller($caller)); |
||
196 | //remove themes from caller |
||
197 | $locs = array_diff($locs, $this->get_locations_theme()); |
||
198 | $locs = array_merge($locs, $this->get_locations_theme()); |
||
199 | $locs = array_merge($locs, $this->get_locations_caller($caller)); |
||
200 | $locs = array_unique($locs); |
||
201 | $locs = apply_filters('timber_locations', $locs); |
||
202 | $locs = apply_filters('timber/locations', $locs); |
||
203 | return $locs; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @return Twig_Loader_Filesystem |
||
208 | */ |
||
209 | function get_loader() { |
||
210 | $paths = array(); |
||
211 | foreach ($this->locations as $loc) { |
||
212 | $loc = realpath($loc); |
||
213 | if (is_dir($loc)) { |
||
214 | $loc = realpath($loc); |
||
215 | $paths[] = $loc; |
||
216 | } else { |
||
217 | //error_log($loc.' is not a directory'); |
||
218 | } |
||
219 | } |
||
220 | if (!ini_get('open_basedir')) { |
||
221 | $paths[] = '/'; |
||
222 | } else { |
||
223 | $paths[] = ABSPATH; |
||
224 | } |
||
225 | $paths = apply_filters('timber/loader/paths', $paths); |
||
226 | $loader = new Twig_Loader_Filesystem($paths); |
||
227 | return $loader; |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * @return Twig_Environment |
||
232 | */ |
||
233 | function get_twig() { |
||
234 | $loader = $this->get_loader(); |
||
235 | $params = array('debug' => WP_DEBUG, 'autoescape' => false); |
||
236 | if (isset(Timber::$autoescape)) { |
||
237 | $params['autoescape'] = Timber::$autoescape; |
||
238 | } |
||
239 | if (Timber::$cache === true) { |
||
240 | Timber::$twig_cache = true; |
||
241 | } |
||
242 | if (Timber::$twig_cache) { |
||
243 | $twig_cache_loc = apply_filters( 'timber/cache/location', TIMBER_LOC . '/cache/twig' ); |
||
244 | if (!file_exists($twig_cache_loc)) { |
||
245 | mkdir($twig_cache_loc, 0777, true); |
||
246 | } |
||
247 | $params['cache'] = $twig_cache_loc; |
||
248 | } |
||
249 | $twig = new Twig_Environment($loader, $params); |
||
250 | if ( WP_DEBUG ) { |
||
251 | $twig->addExtension(new Twig_Extension_Debug()); |
||
252 | } |
||
253 | $twig->addExtension($this->_get_cache_extension()); |
||
254 | |||
255 | $twig = apply_filters('twig_apply_filters', $twig); |
||
256 | $twig = apply_filters('timber/twig/filters', $twig); |
||
257 | $twig = apply_filters('timber/loader/twig', $twig); |
||
258 | return $twig; |
||
259 | } |
||
260 | |||
261 | public function clear_cache_timber($cache_mode = self::CACHE_USE_DEFAULT){ |
||
262 | //_transient_timberloader |
||
263 | $object_cache = false; |
||
264 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
265 | $object_cache = true; |
||
266 | } |
||
267 | $cache_mode = $this->_get_cache_mode($cache_mode); |
||
268 | if (self::CACHE_TRANSIENT === $cache_mode) { |
||
269 | global $wpdb; |
||
270 | $query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%'); |
||
271 | $wpdb->query( $query ); |
||
272 | return true; |
||
273 | } else if (self::CACHE_SITE_TRANSIENT === $cache_mode) { |
||
274 | global $wpdb; |
||
275 | $query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%'); |
||
276 | $wpdb->query( $query ); |
||
277 | return true; |
||
278 | } else if (self::CACHE_OBJECT === $cache_mode && $object_cache) { |
||
279 | global $wp_object_cache; |
||
280 | if (isset($wp_object_cache->cache[self::CACHEGROUP])){ |
||
281 | unset($wp_object_cache->cache[self::CACHEGROUP]); |
||
282 | return true; |
||
283 | } |
||
284 | } |
||
285 | return false; |
||
286 | } |
||
287 | |||
288 | public function clear_cache_twig() { |
||
289 | $twig = $this->get_twig(); |
||
290 | $twig->clearCacheFiles(); |
||
291 | $cache = $twig->getCache(); |
||
292 | if ($cache){ |
||
293 | self::rrmdir($twig->getCache()); |
||
0 ignored issues
–
show
|
|||
294 | return true; |
||
295 | } |
||
296 | return false; |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * @param string|false $dirPath |
||
301 | */ |
||
302 | public static function rrmdir($dirPath) { |
||
303 | if (! is_dir($dirPath)) { |
||
304 | throw new InvalidArgumentException("$dirPath must be a directory"); |
||
305 | } |
||
306 | if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') { |
||
307 | $dirPath .= '/'; |
||
308 | } |
||
309 | $files = glob($dirPath . '*', GLOB_MARK); |
||
310 | foreach ($files as $file) { |
||
311 | if (is_dir($file)) { |
||
312 | self::rrmdir($file); |
||
313 | } else { |
||
314 | unlink($file); |
||
315 | } |
||
316 | } |
||
317 | rmdir($dirPath); |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @return \Asm89\Twig\CacheExtension\Extension |
||
322 | */ |
||
323 | private function _get_cache_extension() { |
||
324 | |||
325 | $key_generator = new \Timber\Cache\KeyGenerator(); |
||
326 | $cache_provider = new \Timber\Cache\WPObjectCacheAdapter( $this ); |
||
327 | $cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy( $cache_provider, $key_generator ); |
||
328 | $cache_extension = new \Asm89\Twig\CacheExtension\Extension( $cache_strategy ); |
||
329 | |||
330 | return $cache_extension; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * @param string $key |
||
335 | * @param string $group |
||
336 | * @param string $cache_mode |
||
337 | * @return bool |
||
338 | */ |
||
339 | public function get_cache($key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
340 | $object_cache = false; |
||
341 | |||
342 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
343 | $object_cache = true; |
||
344 | } |
||
345 | |||
346 | $cache_mode = $this->_get_cache_mode($cache_mode); |
||
347 | |||
348 | $value = false; |
||
349 | |||
350 | $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN); |
||
351 | if (self::CACHE_TRANSIENT === $cache_mode) |
||
352 | $value = get_transient($trans_key); |
||
353 | |||
354 | elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) |
||
355 | $value = get_site_transient($trans_key); |
||
356 | |||
357 | elseif (self::CACHE_OBJECT === $cache_mode && $object_cache) |
||
358 | $value = wp_cache_get($key, $group); |
||
359 | |||
360 | return $value; |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * @param string $key |
||
365 | * @param string|boolean $value |
||
366 | * @param string $group |
||
367 | * @param int $expires |
||
368 | * @param string $cache_mode |
||
369 | * @return string|boolean |
||
370 | */ |
||
371 | public function set_cache($key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT) { |
||
372 | $object_cache = false; |
||
373 | |||
374 | if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) { |
||
375 | $object_cache = true; |
||
376 | } |
||
377 | |||
378 | if ((int)$expires < 1) |
||
379 | $expires = 0; |
||
380 | |||
381 | $cache_mode = self::_get_cache_mode($cache_mode); |
||
382 | $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN); |
||
383 | |||
384 | if (self::CACHE_TRANSIENT === $cache_mode) |
||
385 | set_transient($trans_key, $value, $expires); |
||
386 | |||
387 | elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) |
||
388 | set_site_transient($trans_key, $value, $expires); |
||
389 | |||
390 | elseif (self::CACHE_OBJECT === $cache_mode && $object_cache) |
||
391 | wp_cache_set($key, $value, $group, $expires); |
||
392 | |||
393 | return $value; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * @param string $cache_mode |
||
398 | * @return string |
||
399 | */ |
||
400 | private function _get_cache_mode($cache_mode) { |
||
401 | if (empty($cache_mode) || self::CACHE_USE_DEFAULT === $cache_mode) { |
||
402 | $cache_mode = $this->cache_mode; |
||
403 | } |
||
404 | |||
405 | // Fallback if self::$cache_mode did not get a valid value |
||
406 | if (!in_array($cache_mode, self::$cache_modes)) { |
||
407 | $cache_mode = self::CACHE_OBJECT; |
||
408 | } |
||
409 | |||
410 | return $cache_mode; |
||
411 | } |
||
412 | |||
413 | } |
||
414 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.