Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

path_helper.php

Zuletzt modifiziert: 02.04.2025, 15:01 - Dateigröße: 14.41 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb;
015   
016  /**
017  * A class with various functions that are related to paths, files and the filesystem
018  */
019  class path_helper
020  {
021      /** @var \phpbb\symfony_request */
022      protected $symfony_request;
023   
024      /** @var \phpbb\filesystem\filesystem_interface */
025      protected $filesystem;
026   
027      /** @var \phpbb\request\request_interface */
028      protected $request;
029   
030      /** @var string */
031      protected $phpbb_root_path;
032   
033      /** @var string */
034      protected $adm_relative_path;
035   
036      /** @var string */
037      protected $php_ext;
038   
039      /** @var string */
040      protected $web_root_path;
041   
042      /** @var bool Flag whether we're in adm path */
043      protected $in_adm_path = false;
044   
045      /**
046      * Constructor
047      *
048      * @param \phpbb\symfony_request $symfony_request
049      * @param \phpbb\filesystem\filesystem_interface $filesystem
050      * @param \phpbb\request\request_interface $request
051      * @param string $phpbb_root_path Relative path to phpBB root
052      * @param string $php_ext PHP file extension
053      * @param mixed $adm_relative_path Relative path admin path to adm/ root
054      */
055      public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null)
056      {
057          $this->symfony_request = $symfony_request;
058          $this->filesystem = $filesystem;
059          $this->request = $request;
060          $this->phpbb_root_path = $phpbb_root_path;
061          $this->php_ext = $php_ext;
062          $this->adm_relative_path = $adm_relative_path;
063      }
064   
065      /**
066      * Get the phpBB root path
067      *
068      * @return string
069      */
070      public function get_phpbb_root_path()
071      {
072          return $this->phpbb_root_path;
073      }
074   
075      /**
076      * Get the adm root path
077      *
078      * @return string
079      */
080      public function get_adm_relative_path()
081      {
082          return $this->adm_relative_path;
083      }
084   
085      /**
086      * Get the php extension
087      *
088      * @return string
089      */
090      public function get_php_ext()
091      {
092          return $this->php_ext;
093      }
094   
095      /**
096      * Update a web path to the correct relative root path
097      *
098      * This replaces $phpbb_root_path . some_url with
099      *    get_web_root_path() . some_url
100      *
101      * @param string $path The path to be updated
102      * @return string
103      */
104      public function update_web_root_path($path)
105      {
106          $web_root_path = $this->get_web_root_path();
107   
108          // Removes the web root path if it is already present
109          if (strpos($path, $web_root_path) === 0)
110          {
111              $path = $this->phpbb_root_path . substr($path, strlen($web_root_path));
112          }
113   
114          if (strpos($path, $this->phpbb_root_path) === 0)
115          {
116              $path = substr($path, strlen($this->phpbb_root_path));
117   
118              if (substr($web_root_path, -8) === 'app.php/' && substr($path, 0, 7) === 'app.php')
119              {
120                  $path = substr($path, 8);
121              }
122   
123              $path = $this->filesystem->clean_path($web_root_path . $path);
124   
125              // Further clean path if we're in adm
126              if ($this->in_adm_path && strpos($path, $this->phpbb_root_path . $this->adm_relative_path) === 0)
127              {
128                  $path = substr($path, strlen($this->phpbb_root_path . $this->adm_relative_path));
129              }
130          }
131   
132          return $path;
133      }
134   
135      /**
136      * Strips away the web root path and prepends the normal root path
137      *
138      * This replaces get_web_root_path() . some_url with
139      *    $phpbb_root_path . some_url
140      *
141      * @param string $path The path to be updated
142      * @return string
143      */
144      public function remove_web_root_path($path)
145      {
146          if (strpos($path, $this->get_web_root_path()) === 0)
147          {
148              $path = substr($path, strlen($this->get_web_root_path()));
149   
150              return $this->phpbb_root_path . $path;
151          }
152   
153          return $path;
154      }
155   
156      /**
157      * Get a relative root path from the current URL
158      *
159      * @return string
160      */
161      public function get_web_root_path()
162      {
163          if (null !== $this->web_root_path)
164          {
165              return $this->web_root_path;
166          }
167   
168          if (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH)
169          {
170              return $this->web_root_path = generate_board_url() . '/';
171          }
172   
173          // We do not need to escape $path_info, $request_uri and $script_name because we can not find their content in the result.
174          // Path info (e.g. /foo/bar)
175          $path_info = $this->filesystem->clean_path($this->symfony_request->getPathInfo());
176   
177          // Full request URI (e.g. phpBB/app.php/foo/bar)
178          $request_uri = $this->symfony_request->getRequestUri();
179   
180          // Script name URI (e.g. phpBB/app.php)
181          $script_name = $this->symfony_request->getScriptName();
182   
183          /*
184          * If the path info is empty but we're using app.php, then we
185          *    might be using an empty route like app.php/ which is
186          *    supported by symfony's routing
187          */
188          if ($path_info === '/' && preg_match('/app\.' . $this->php_ext . '\/$/', $request_uri))
189          {
190              return $this->web_root_path = $this->filesystem->clean_path('./../' . $this->phpbb_root_path);
191          }
192   
193          if ($path_info === '/' && defined('ADMIN_START') && preg_match('/\/' . preg_quote($this->adm_relative_path, '/') . 'index\.' . $this->php_ext . '$/', $script_name))
194          {
195              $this->in_adm_path = true;
196          }
197   
198          /*
199          * If the path info is empty (single /), then we're not using
200          *    a route like app.php/foo/bar
201          */
202          if ($path_info === '/')
203          {
204              return $this->web_root_path = $this->phpbb_root_path;
205          }
206   
207          /*
208          * Check AJAX request:
209          * If the current request is a AJAX we need to fix the paths.
210          * We need to get the root path based on the Referer, so we can use
211          * the generated URLs in the template of the Referer. If we do not
212          * generate the relative path based on the Referer, but based on the
213          * currently requested URL, the generated URLs will not point to the
214          * intended locations:
215          *    Referer                desired URL            desired relative root path
216          *    memberlist.php        faq.php                ./
217          *    memberlist.php        app.php/foo/bar        ./
218          *    app.php/foo            memberlist.php        ../
219          *    app.php/foo            app.php/fox            ../
220          *    app.php/foo/bar        memberlist.php        ../../
221          *    ../page.php            memberlist.php        ./phpBB/
222          *    ../sub/page.php        memberlist.php        ./../phpBB/
223          *
224          * The referer must be specified as a parameter in the query.
225          */
226          if ($this->request->is_ajax() && $this->request->header('Referer'))
227          {
228              // We need to escape $absolute_board_url because it can be partially concatenated to the result.
229              $absolute_board_url = $this->request->escape($this->symfony_request->getSchemeAndHttpHost() . $this->symfony_request->getBasePath(), true);
230   
231              $referer_web_root_path = $this->get_web_root_path_from_ajax_referer(
232                  $this->request->header('Referer'),
233                  $absolute_board_url
234              );
235              return $this->web_root_path = $referer_web_root_path;
236          }
237   
238          // How many corrections might we need?
239          $corrections = substr_count($path_info, '/');
240   
241          /*
242          * If the script name (e.g. phpBB/app.php) does not exists in the
243          * requestUri (e.g. phpBB/app.php/foo/template), then we are rewriting
244          * the URL. So we must reduce the slash count by 1.
245          */
246          if (strpos($request_uri, $script_name) !== 0)
247          {
248              $corrections--;
249          }
250   
251          // Prepend ../ to the phpbb_root_path as many times as / exists in path_info
252          $this->web_root_path = $this->filesystem->clean_path(
253              './' . str_repeat('../', max(0, $corrections)) . $this->phpbb_root_path
254          );
255          return $this->web_root_path;
256      }
257   
258      /**
259      * Get the web root path of the referer form an ajax request
260      *
261      * @param string $absolute_referer_url
262      * @param string $absolute_board_url
263      * @return string
264      */
265      public function get_web_root_path_from_ajax_referer($absolute_referer_url, $absolute_board_url)
266      {
267          // If the board URL is in the beginning of the referer, this means
268          // we the referer is in the board URL or a subdirectory of it.
269          // So we just need to count the / (slashes) in the left over part of
270          // the referer and prepend ../ the the current root_path, to get the
271          // web root path of the referer.
272          if (strpos($absolute_referer_url, $absolute_board_url) === 0)
273          {
274              $relative_referer_path = substr($absolute_referer_url, strlen($absolute_board_url));
275              $has_params = strpos($relative_referer_path, '?');
276              if ($has_params !== false)
277              {
278                  $relative_referer_path = substr($relative_referer_path, 0, $has_params);
279              }
280              $corrections = substr_count($relative_referer_path, '/');
281              return $this->phpbb_root_path . str_repeat('../', max(0, $corrections - 1));
282          }
283   
284          // If not, it's a bit more complicated. We go to the parent directory
285          // of the referer until we find the remaining referer in the board URL.
286          // Foreach directory we need to add a ../ to the fixed root_path.
287          // When we finally found it, we need to remove the remaining referer
288          // from the board URL, to get the boards root path.
289          // If the then append these two strings, we get our fixed web root path.
290          $fixed_root_path = '';
291          $referer_dir = $absolute_referer_url;
292          $has_params = strpos($referer_dir, '?');
293          if ($has_params !== false)
294          {
295              $referer_dir = substr($referer_dir, 0, $has_params);
296          }
297   
298          // If we do not find a slash at the end of the referer, we come
299          // from a file. So the first dirname() does not need a traversal
300          // path correction.
301          if (substr($referer_dir, -1) !== '/')
302          {
303              $referer_dir = dirname($referer_dir);
304          }
305   
306          while (($dir_position = strpos($absolute_board_url, $referer_dir)) !== 0)
307          {
308              $fixed_root_path .= '../';
309              $referer_dir = dirname($referer_dir);
310   
311              // Just return phpbb_root_path if we reach the top directory
312              if ($referer_dir === '.')
313              {
314                  return $this->phpbb_root_path;
315              }
316          }
317   
318          $fixed_root_path .= substr($absolute_board_url, strlen($referer_dir) + 1);
319          // Add trailing slash
320          return $this->phpbb_root_path . $fixed_root_path . '/';
321      }
322   
323      /**
324      * Eliminates useless . and .. components from specified URL
325      *
326      * @param string $url URL to clean
327      *
328      * @return string Cleaned URL
329      */
330      public function clean_url($url)
331      {
332          $delimiter_position = strpos($url, '://');
333          // URL should contain :// but it shouldn't start with it.
334          // Do not clean URLs that do not fit these constraints.
335          if (empty($delimiter_position))
336          {
337              return $url;
338          }
339          $scheme = substr($url, 0, $delimiter_position) . '://';
340          // Add length of URL delimiter to position
341          $path = substr($url, $delimiter_position + 3);
342   
343          return $scheme . $this->filesystem->clean_path($path);
344      }
345   
346      /**
347      * Glue URL parameters together
348      *
349      * @param array $params URL parameters in the form of array(name => value)
350      * @return string Returns the glued string, e.g. name1=value1&amp;name2&amp;name3=value3
351      */
352      public function glue_url_params($params)
353      {
354          $_params = array();
355   
356          foreach ($params as $key => $value)
357          {
358              // some parameters do not have value
359              if ($value !== null)
360              {
361                  $_params[] = $key . '=' . $value;
362              }
363              else
364              {
365                  $_params[] = $key;
366              }
367          }
368          return implode('&amp;', $_params);
369      }
370   
371      /**
372      * Get the base and parameters of a URL
373      *
374      * @param string $url URL to break apart
375      * @param bool $is_amp Is the parameter separator &amp;. Defaults to true.
376      * @return array Returns the base and parameters in the form of array('base' => string, 'params' => array(name => value))
377      */
378      public function get_url_parts($url, $is_amp = true)
379      {
380          $separator = ($is_amp) ? '&amp;' : '&';
381          $params = array();
382   
383          if (strpos($url, '?') !== false)
384          {
385              $base = substr($url, 0, strpos($url, '?'));
386              $args = substr($url, strlen($base) + 1);
387              $args = ($args) ? explode($separator, $args) : array();
388   
389              foreach ($args as $argument)
390              {
391                  if (empty($argument))
392                  {
393                      continue;
394                  }
395   
396                  // some parameters don't have value
397                  if (strpos($argument, '=') !== false)
398                  {
399                      list($key, $value) = explode('=', $argument, 2);
400                  }
401                  else
402                  {
403                      $key = $argument;
404                      $value = null;
405                  }
406   
407                  if ($key === '')
408                  {
409                      continue;
410                  }
411   
412                  $params[$key] = $value;
413              }
414          }
415          else
416          {
417              $base = $url;
418          }
419   
420          return array(
421              'base'        => $base,
422              'params'    => $params,
423          );
424      }
425   
426      /**
427      * Strip parameters from an already built URL.
428      *
429      * @param string $url URL to strip parameters from
430      * @param array|string $strip Parameters to strip.
431      * @param bool $is_amp Is the parameter separator &amp;. Defaults to true.
432      * @return string Returns the new URL.
433      */
434      public function strip_url_params($url, $strip, $is_amp = true)
435      {
436          $url_parts = $this->get_url_parts($url, $is_amp);
437          $params = $url_parts['params'];
438   
439          if (!is_array($strip))
440          {
441              $strip = array($strip);
442          }
443   
444          if (!empty($params))
445          {
446              // Strip the parameters off
447              foreach ($strip as $param)
448              {
449                  unset($params[$param]);
450              }
451          }
452   
453          return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : '');
454      }
455   
456      /**
457      * Append parameters to an already built URL.
458      *
459      * @param string $url URL to append parameters to
460      * @param array $new_params Parameters to add in the form of array(name => value)
461      * @param bool $is_amp Is the parameter separator &amp;. Defaults to true.
462      * @return string Returns the new URL.
463      */
464      public function append_url_params($url, $new_params, $is_amp = true)
465      {
466          $url_parts = $this->get_url_parts($url, $is_amp);
467          $params = array_merge($url_parts['params'], $new_params);
468   
469          // Move the sid to the end if it's set
470          if (isset($params['sid']))
471          {
472              $sid = $params['sid'];
473              unset($params['sid']);
474              $params['sid'] = $sid;
475          }
476   
477          return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : '');
478      }
479   
480      /**
481       * Get a valid page
482       *
483       * @param string $page The page to verify
484       * @param bool $mod_rewrite Whether mod_rewrite is enabled, default: false
485       *
486       * @return string A valid page based on given page and mod_rewrite
487       */
488      public function get_valid_page($page, $mod_rewrite = false)
489      {
490          // We need to be cautious here.
491          // On some situations, the redirect path is an absolute URL, sometimes a relative path
492          // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
493          // else we use the URL directly.
494          $url_parts = parse_url($page);
495   
496          // URL
497          if ($url_parts === false || empty($url_parts['scheme']) || empty($url_parts['host']))
498          {
499              // Remove 'app.php/' from the page, when rewrite is enabled.
500              // Treat app.php as a reserved file name and remove on mod rewrite
501              // even if it might not be in the phpBB root.
502              if ($mod_rewrite && ($app_position = strpos($page, 'app.' . $this->php_ext . '/')) !== false)
503              {
504                  $page = substr($page, 0, $app_position) . substr($page, $app_position + strlen('app.' . $this->php_ext . '/'));
505              }
506   
507              // Remove preceding slashes from page name and prepend root path
508              $page = $this->get_phpbb_root_path() . ltrim($page, '/\\');
509          }
510   
511          return $page;
512      }
513   
514      /**
515       * Tells if the router is currently in use (if the current page is a route or not)
516       *
517       * @return bool
518       */
519      public function is_router_used()
520      {
521          // Script name URI (e.g. phpBB/app.php)
522          $script_name = $this->symfony_request->getScriptName();
523   
524          return basename($script_name) === 'app.' . $this->php_ext;
525      }
526  }
527