[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/ -> path_helper.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb;
  15  
  16  /**
  17  * A class with various functions that are related to paths, files and the filesystem
  18  */
  19  class path_helper
  20  {
  21      /** @var \phpbb\symfony_request */
  22      protected $symfony_request;
  23  
  24      /** @var \phpbb\filesystem\filesystem_interface */
  25      protected $filesystem;
  26  
  27      /** @var \phpbb\request\request_interface */
  28      protected $request;
  29  
  30      /** @var string */
  31      protected $phpbb_root_path;
  32  
  33      /** @var string */
  34      protected $adm_relative_path;
  35  
  36      /** @var string */
  37      protected $php_ext;
  38  
  39      /** @var string */
  40      protected $web_root_path;
  41  
  42      /** @var bool Flag whether we're in adm path */
  43      protected $in_adm_path = false;
  44  
  45      /**
  46      * Constructor
  47      *
  48      * @param \phpbb\symfony_request $symfony_request
  49      * @param \phpbb\filesystem\filesystem_interface $filesystem
  50      * @param \phpbb\request\request_interface $request
  51      * @param string $phpbb_root_path Relative path to phpBB root
  52      * @param string $php_ext PHP file extension
  53      * @param mixed $adm_relative_path Relative path admin path to adm/ root
  54      */
  55  	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)
  56      {
  57          $this->symfony_request = $symfony_request;
  58          $this->filesystem = $filesystem;
  59          $this->request = $request;
  60          $this->phpbb_root_path = $phpbb_root_path;
  61          $this->php_ext = $php_ext;
  62          $this->adm_relative_path = $adm_relative_path;
  63      }
  64  
  65      /**
  66      * Get the phpBB root path
  67      *
  68      * @return string
  69      */
  70  	public function get_phpbb_root_path()
  71      {
  72          return $this->phpbb_root_path;
  73      }
  74  
  75      /**
  76      * Get the adm root path
  77      *
  78      * @return string
  79      */
  80  	public function get_adm_relative_path()
  81      {
  82          return $this->adm_relative_path;
  83      }
  84  
  85      /**
  86      * Get the php extension
  87      *
  88      * @return string
  89      */
  90  	public function get_php_ext()
  91      {
  92          return $this->php_ext;
  93      }
  94  
  95      /**
  96      * Update a web path to the correct relative root path
  97      *
  98      * This replaces $phpbb_root_path . some_url with
  99      *    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  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1