Source for file uri.php

Documentation is available at uri.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Uri
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. /**
  13.  * JUri Class
  14.  *
  15.  * This class serves two purposes. First it parses a URI and provides a common interface
  16.  * for the Joomla Platform to access and manipulate a URI.  Second it obtains the URI of
  17.  * the current executing script from the server regardless of server.
  18.  *
  19.  * @package     Joomla.Platform
  20.  * @subpackage  Uri
  21.  * @since       11.1
  22.  */
  23. class JUri
  24. {
  25.     /**
  26.      * @var    string Original URI
  27.      * @since  12.1
  28.      */
  29.     protected $uri = null;
  30.  
  31.     /**
  32.      * @var    string  Protocol
  33.      * @since  12.1
  34.      */
  35.     protected $scheme = null;
  36.  
  37.     /**
  38.      * @var    string  Host
  39.      * @since  12.1
  40.      */
  41.     protected $host = null;
  42.  
  43.     /**
  44.      * @var    integer  Port
  45.      * @since  12.1
  46.      */
  47.     protected $port = null;
  48.  
  49.     /**
  50.      * @var    string  Username
  51.      * @since  12.1
  52.      */
  53.     protected $user = null;
  54.  
  55.     /**
  56.      * @var    string  Password
  57.      * @since  12.1
  58.      */
  59.     protected $pass = null;
  60.  
  61.     /**
  62.      * @var    string  Path
  63.      * @since  12.1
  64.      */
  65.     protected $path = null;
  66.  
  67.     /**
  68.      * @var    string  Query
  69.      * @since  12.1
  70.      */
  71.     protected $query = null;
  72.  
  73.     /**
  74.      * @var    string  Anchor
  75.      * @since  12.1
  76.      */
  77.     protected $fragment = null;
  78.  
  79.     /**
  80.      * @var    array  Query variable hash
  81.      * @since  12.1
  82.      */
  83.     protected $vars = array();
  84.  
  85.     /**
  86.      * @var    array  An array of JUri instances.
  87.      * @since  11.1
  88.      */
  89.     protected static $instances array();
  90.  
  91.     /**
  92.      * @var    array  The current calculated base url segments.
  93.      * @since  11.1
  94.      */
  95.     protected static $base array();
  96.  
  97.     /**
  98.      * @var    array  The current calculated root url segments.
  99.      * @since  11.1
  100.      */
  101.     protected static $root array();
  102.  
  103.     /**
  104.      * @var    string  The current url.
  105.      * @since  11.1
  106.      */
  107.     protected static $current;
  108.  
  109.     /**
  110.      * Constructor.
  111.      * You can pass a URI string to the constructor to initialise a specific URI.
  112.      *
  113.      * @param   string  $uri  The optional URI string
  114.      *
  115.      * @since   11.1
  116.      */
  117.     public function __construct($uri null)
  118.     {
  119.         if (!is_null($uri))
  120.         {
  121.             $this->parse($uri);
  122.         }
  123.     }
  124.  
  125.     /**
  126.      * Magic method to get the string representation of the URI object.
  127.      *
  128.      * @return  string 
  129.      *
  130.      * @since   11.1
  131.      */
  132.     public function __toString()
  133.     {
  134.         return $this->toString();
  135.     }
  136.  
  137.     /**
  138.      * Returns the global JUri object, only creating it
  139.      * if it doesn't already exist.
  140.      *
  141.      * @param   string  $uri  The URI to parse.  [optional: if null uses script URI]
  142.      *
  143.      * @return  JUri  The URI object.
  144.      *
  145.      * @since   11.1
  146.      */
  147.     public static function getInstance($uri 'SERVER')
  148.     {
  149.         if (empty(self::$instances[$uri]))
  150.         {
  151.             // Are we obtaining the URI from the server?
  152.             if ($uri == 'SERVER')
  153.             {
  154.                 // Determine if the request was over SSL (HTTPS).
  155.                 if (isset($_SERVER['HTTPS']&& !empty($_SERVER['HTTPS']&& (strtolower($_SERVER['HTTPS']!= 'off'))
  156.                 {
  157.                     $https 's://';
  158.                 }
  159.                 else
  160.                 {
  161.                     $https '://';
  162.                 }
  163.  
  164.                 /*
  165.                  * Since we are assigning the URI from the server variables, we first need
  166.                  * to determine if we are running on apache or IIS.  If PHP_SELF and REQUEST_URI
  167.                  * are present, we will assume we are running on apache.
  168.                  */
  169.  
  170.                 if (!empty($_SERVER['PHP_SELF']&& !empty($_SERVER['REQUEST_URI']))
  171.                 {
  172.                     // To build the entire URI we need to prepend the protocol, and the http host
  173.                     // to the URI string.
  174.                     $theURI 'http' $https $_SERVER['HTTP_HOST'$_SERVER['REQUEST_URI'];
  175.                 }
  176.                 else
  177.                 {
  178.                     /*
  179.                      * Since we do not have REQUEST_URI to work with, we will assume we are
  180.                      * running on IIS and will therefore need to work some magic with the SCRIPT_NAME and
  181.                      * QUERY_STRING environment variables.
  182.                      *
  183.                      * IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS
  184.                      */
  185.                     $theURI 'http' $https $_SERVER['HTTP_HOST'$_SERVER['SCRIPT_NAME'];
  186.  
  187.                     // If the query string exists append it to the URI string
  188.                     if (isset($_SERVER['QUERY_STRING']&& !empty($_SERVER['QUERY_STRING']))
  189.                     {
  190.                         $theURI .= '?' $_SERVER['QUERY_STRING'];
  191.                     }
  192.                 }
  193.  
  194.                 // Extra cleanup to remove invalid chars in the URL to prevent injections through the Host header
  195.                 $theURI str_replace(array("'"'"''<''>')array("%27""%22""%3C""%3E")$theURI);
  196.             }
  197.             else
  198.             {
  199.                 // We were given a URI
  200.                 $theURI $uri;
  201.             }
  202.  
  203.             self::$instances[$urinew JUri($theURI);
  204.         }
  205.  
  206.         return self::$instances[$uri];
  207.     }
  208.  
  209.     /**
  210.      * Returns the base URI for the request.
  211.      *
  212.      * @param   boolean  $pathonly  If false, prepend the scheme, host and port information. Default is false.
  213.      *
  214.      * @return  string  The base URI string
  215.      *
  216.      * @since   11.1
  217.      */
  218.     public static function base($pathonly false)
  219.     {
  220.         // Get the base request path.
  221.         if (empty(self::$base))
  222.         {
  223.             $config JFactory::getConfig();
  224.             $live_site $config->get('live_site');
  225.  
  226.             if (trim($live_site!= '')
  227.             {
  228.                 $uri self::getInstance($live_site);
  229.                 self::$base['prefix'$uri->toString(array('scheme''host''port'));
  230.                 self::$base['path'rtrim($uri->toString(array('path'))'/\\');
  231.  
  232.                 if (defined('JPATH_BASE'&& defined('JPATH_ADMINISTRATOR'))
  233.                 {
  234.                     if (JPATH_BASE == JPATH_ADMINISTRATOR)
  235.                     {
  236.                         self::$base['path'.= '/administrator';
  237.                     }
  238.                 }
  239.             }
  240.             else
  241.             {
  242.                 $uri self::getInstance();
  243.                 self::$base['prefix'$uri->toString(array('scheme''host''port'));
  244.  
  245.                 if (strpos(php_sapi_name()'cgi'!== false && !ini_get('cgi.fix_pathinfo'&& !empty($_SERVER['REQUEST_URI']))
  246.                 {
  247.                     // PHP-CGI on Apache with "cgi.fix_pathinfo = 0"
  248.  
  249.                     // We shouldn't have user-supplied PATH_INFO in PHP_SELF in this case
  250.                     // because PHP will not work with PATH_INFO at all.
  251.                     $script_name $_SERVER['PHP_SELF'];
  252.                 }
  253.                 else
  254.                 {
  255.                     // Others
  256.                     $script_name $_SERVER['SCRIPT_NAME'];
  257.                 }
  258.  
  259.                 self::$base['path'rtrim(dirname($script_name)'/\\');
  260.             }
  261.         }
  262.  
  263.         return $pathonly === false self::$base['prefix'self::$base['path''/' self::$base['path'];
  264.     }
  265.  
  266.     /**
  267.      * Returns the root URI for the request.
  268.      *
  269.      * @param   boolean  $pathonly  If false, prepend the scheme, host and port information. Default is false.
  270.      * @param   string   $path      The path
  271.      *
  272.      * @return  string  The root URI string.
  273.      *
  274.      * @since   11.1
  275.      */
  276.     public static function root($pathonly false$path null)
  277.     {
  278.         // Get the scheme
  279.         if (empty(self::$root))
  280.         {
  281.             $uri self::getInstance(self::base());
  282.             self::$root['prefix'$uri->toString(array('scheme''host''port'));
  283.             self::$root['path'rtrim($uri->toString(array('path'))'/\\');
  284.         }
  285.  
  286.         // Get the scheme
  287.         if (isset($path))
  288.         {
  289.             self::$root['path'$path;
  290.         }
  291.  
  292.         return $pathonly === false self::$root['prefix'self::$root['path''/' self::$root['path'];
  293.     }
  294.  
  295.     /**
  296.      * Returns the URL for the request, minus the query.
  297.      *
  298.      * @return  string 
  299.      *
  300.      * @since   11.1
  301.      */
  302.     public static function current()
  303.     {
  304.         // Get the current URL.
  305.         if (empty(self::$current))
  306.         {
  307.             $uri self::getInstance();
  308.             self::$current $uri->toString(array('scheme''host''port''path'));
  309.         }
  310.  
  311.         return self::$current;
  312.     }
  313.  
  314.     /**
  315.      * Method to reset class static members for testing and other various issues.
  316.      *
  317.      * @return  void 
  318.      *
  319.      * @since   11.1
  320.      */
  321.     public static function reset()
  322.     {
  323.         self::$instances array();
  324.         self::$base array();
  325.         self::$root array();
  326.         self::$current '';
  327.     }
  328.  
  329.     /**
  330.      * Parse a given URI and populate the class fields.
  331.      *
  332.      * @param   string  $uri  The URI string to parse.
  333.      *
  334.      * @return  boolean  True on success.
  335.      *
  336.      * @since   11.1
  337.      */
  338.     public function parse($uri)
  339.     {
  340.         // Set the original URI to fall back on
  341.         $this->uri = $uri;
  342.  
  343.         /*
  344.          * Parse the URI and populate the object fields. If URI is parsed properly,
  345.          * set method return value to true.
  346.          */
  347.         $parts JString::parse_url($uri);
  348.  
  349.         $retval ($partstrue false;
  350.  
  351.         // We need to replace &amp; with & for parse_str to work right...
  352.         if (isset($parts['query']&& strpos($parts['query']'&amp;'))
  353.         {
  354.             $parts['query'str_replace('&amp;''&'$parts['query']);
  355.         }
  356.  
  357.         $this->scheme = isset($parts['scheme']$parts['scheme'null;
  358.         $this->user = isset($parts['user']$parts['user'null;
  359.         $this->pass = isset($parts['pass']$parts['pass'null;
  360.         $this->host = isset($parts['host']$parts['host'null;
  361.         $this->port = isset($parts['port']$parts['port'null;
  362.         $this->path = isset($parts['path']$parts['path'null;
  363.         $this->query = isset($parts['query']$parts['query'null;
  364.         $this->fragment = isset($parts['fragment']$parts['fragment'null;
  365.  
  366.         // Parse the query
  367.         if (isset($parts['query']))
  368.         {
  369.             parse_str($parts['query']$this->vars);
  370.         }
  371.  
  372.         return $retval;
  373.     }
  374.  
  375.     /**
  376.      * Returns full uri string.
  377.      *
  378.      * @param   array  $parts  An array specifying the parts to render.
  379.      *
  380.      * @return  string  The rendered URI string.
  381.      *
  382.      * @since   11.1
  383.      */
  384.     public function toString(array $parts array('scheme''user''pass''host''port''path''query''fragment'))
  385.     {
  386.         // Make sure the query is created
  387.         $query $this->getQuery();
  388.  
  389.         $uri '';
  390.         $uri .= in_array('scheme'$parts(!empty($this->scheme$this->scheme . '://' '''';
  391.         $uri .= in_array('user'$parts$this->user : '';
  392.         $uri .= in_array('pass'$parts(!empty($this->pass':' ''$this->pass . (!empty($this->user'@' '''';
  393.         $uri .= in_array('host'$parts$this->host : '';
  394.         $uri .= in_array('port'$parts(!empty($this->port':' ''$this->port : '';
  395.         $uri .= in_array('path'$parts$this->path : '';
  396.         $uri .= in_array('query'$parts(!empty($query'?' $query '''';
  397.         $uri .= in_array('fragment'$parts(!empty($this->fragment'#' $this->fragment : '''';
  398.  
  399.         return $uri;
  400.     }
  401.  
  402.     /**
  403.      * Adds a query variable and value, replacing the value if it
  404.      * already exists and returning the old value.
  405.      *
  406.      * @param   string  $name   Name of the query variable to set.
  407.      * @param   string  $value  Value of the query variable.
  408.      *
  409.      * @return  string  Previous value for the query variable.
  410.      *
  411.      * @since   11.1
  412.      */
  413.     public function setVar($name$value)
  414.     {
  415.         $tmp = isset($this->vars[$name]$this->vars[$namenull;
  416.  
  417.         $this->vars[$name$value;
  418.  
  419.         // Empty the query
  420.         $this->query = null;
  421.  
  422.         return $tmp;
  423.     }
  424.  
  425.     /**
  426.      * Checks if variable exists.
  427.      *
  428.      * @param   string  $name  Name of the query variable to check.
  429.      *
  430.      * @return  boolean  True if the variable exists.
  431.      *
  432.      * @since   11.1
  433.      */
  434.     public function hasVar($name)
  435.     {
  436.         return array_key_exists($name$this->vars);
  437.     }
  438.  
  439.     /**
  440.      * Returns a query variable by name.
  441.      *
  442.      * @param   string  $name     Name of the query variable to get.
  443.      * @param   string  $default  Default value to return if the variable is not set.
  444.      *
  445.      * @return  array   Query variables.
  446.      *
  447.      * @since   11.1
  448.      */
  449.     public function getVar($name$default null)
  450.     {
  451.         if (array_key_exists($name$this->vars))
  452.         {
  453.             return $this->vars[$name];
  454.         }
  455.  
  456.         return $default;
  457.     }
  458.  
  459.     /**
  460.      * Removes an item from the query string variables if it exists.
  461.      *
  462.      * @param   string  $name  Name of variable to remove.
  463.      *
  464.      * @return  void 
  465.      *
  466.      * @since   11.1
  467.      */
  468.     public function delVar($name)
  469.     {
  470.         if (array_key_exists($name$this->vars))
  471.         {
  472.             unset($this->vars[$name]);
  473.  
  474.             // Empty the query
  475.             $this->query = null;
  476.         }
  477.     }
  478.  
  479.     /**
  480.      * Sets the query to a supplied string in format:
  481.      * foo=bar&x=y
  482.      *
  483.      * @param   mixed  $query  The query string or array.
  484.      *
  485.      * @return  void 
  486.      *
  487.      * @since   11.1
  488.      */
  489.     public function setQuery($query)
  490.     {
  491.         if (is_array($query))
  492.         {
  493.             $this->vars = $query;
  494.         }
  495.         else
  496.         {
  497.             if (strpos($query'&amp;'!== false)
  498.             {
  499.                 $query str_replace('&amp;''&'$query);
  500.             }
  501.  
  502.             parse_str($query$this->vars);
  503.         }
  504.  
  505.         // Empty the query
  506.         $this->query = null;
  507.     }
  508.  
  509.     /**
  510.      * Returns flat query string.
  511.      *
  512.      * @param   boolean  $toArray  True to return the query as a key => value pair array.
  513.      *
  514.      * @return  string   Query string.
  515.      *
  516.      * @since   11.1
  517.      */
  518.     public function getQuery($toArray false)
  519.     {
  520.         if ($toArray)
  521.         {
  522.             return $this->vars;
  523.         }
  524.  
  525.         // If the query is empty build it first
  526.         if (is_null($this->query))
  527.         {
  528.             $this->query = self::buildQuery($this->vars);
  529.         }
  530.  
  531.         return $this->query;
  532.     }
  533.  
  534.     /**
  535.      * Build a query from a array (reverse of the PHP parse_str()).
  536.      *
  537.      * @param   array  $params  The array of key => value pairs to return as a query string.
  538.      *
  539.      * @return  string  The resulting query string.
  540.      *
  541.      * @see     parse_str()
  542.      * @since   11.1
  543.      */
  544.     public static function buildQuery(array $params)
  545.     {
  546.         if (count($params== 0)
  547.         {
  548.             return false;
  549.         }
  550.  
  551.         return urldecode(http_build_query($params'''&'));
  552.     }
  553.  
  554.     /**
  555.      * Get URI scheme (protocol)
  556.      * ie. http, https, ftp, etc...
  557.      *
  558.      * @return  string  The URI scheme.
  559.      *
  560.      * @since   11.1
  561.      */
  562.     public function getScheme()
  563.     {
  564.         return $this->scheme;
  565.     }
  566.  
  567.     /**
  568.      * Set URI scheme (protocol)
  569.      * ie. http, https, ftp, etc...
  570.      *
  571.      * @param   string  $scheme  The URI scheme.
  572.      *
  573.      * @return  void 
  574.      *
  575.      * @since   11.1
  576.      */
  577.     public function setScheme($scheme)
  578.     {
  579.         $this->scheme $scheme;
  580.     }
  581.  
  582.     /**
  583.      * Get URI username
  584.      * Returns the username, or null if no username was specified.
  585.      *
  586.      * @return  string  The URI username.
  587.      *
  588.      * @since   11.1
  589.      */
  590.     public function getUser()
  591.     {
  592.         return $this->user;
  593.     }
  594.  
  595.     /**
  596.      * Set URI username.
  597.      *
  598.      * @param   string  $user  The URI username.
  599.      *
  600.      * @return  void 
  601.      *
  602.      * @since   11.1
  603.      */
  604.     public function setUser($user)
  605.     {
  606.         $this->user $user;
  607.     }
  608.  
  609.     /**
  610.      * Get URI password
  611.      * Returns the password, or null if no password was specified.
  612.      *
  613.      * @return  string  The URI password.
  614.      *
  615.      * @since   11.1
  616.      */
  617.     public function getPass()
  618.     {
  619.         return $this->pass;
  620.     }
  621.  
  622.     /**
  623.      * Set URI password.
  624.      *
  625.      * @param   string  $pass  The URI password.
  626.      *
  627.      * @return  void 
  628.      *
  629.      * @since   11.1
  630.      */
  631.     public function setPass($pass)
  632.     {
  633.         $this->pass $pass;
  634.     }
  635.  
  636.     /**
  637.      * Get URI host
  638.      * Returns the hostname/ip or null if no hostname/ip was specified.
  639.      *
  640.      * @return  string  The URI host.
  641.      *
  642.      * @since   11.1
  643.      */
  644.     public function getHost()
  645.     {
  646.         return $this->host;
  647.     }
  648.  
  649.     /**
  650.      * Set URI host.
  651.      *
  652.      * @param   string  $host  The URI host.
  653.      *
  654.      * @return  void 
  655.      *
  656.      * @since   11.1
  657.      */
  658.     public function setHost($host)
  659.     {
  660.         $this->host $host;
  661.     }
  662.  
  663.     /**
  664.      * Get URI port
  665.      * Returns the port number, or null if no port was specified.
  666.      *
  667.      * @return  integer  The URI port number.
  668.      *
  669.      * @since   11.1
  670.      */
  671.     public function getPort()
  672.     {
  673.         return (isset($this->port)) $this->port null;
  674.     }
  675.  
  676.     /**
  677.      * Set URI port.
  678.      *
  679.      * @param   integer  $port  The URI port number.
  680.      *
  681.      * @return  void 
  682.      *
  683.      * @since   11.1
  684.      */
  685.     public function setPort($port)
  686.     {
  687.         $this->port $port;
  688.     }
  689.  
  690.     /**
  691.      * Gets the URI path string.
  692.      *
  693.      * @return  string  The URI path string.
  694.      *
  695.      * @since   11.1
  696.      */
  697.     public function getPath()
  698.     {
  699.         return $this->path;
  700.     }
  701.  
  702.     /**
  703.      * Set the URI path string.
  704.      *
  705.      * @param   string  $path  The URI path string.
  706.      *
  707.      * @return  void 
  708.      *
  709.      * @since   11.1
  710.      */
  711.     public function setPath($path)
  712.     {
  713.         $this->path $this->_cleanPath($path);
  714.     }
  715.  
  716.     /**
  717.      * Get the URI archor string
  718.      * Everything after the "#".
  719.      *
  720.      * @return  string  The URI anchor string.
  721.      *
  722.      * @since   11.1
  723.      */
  724.     public function getFragment()
  725.     {
  726.         return $this->fragment;
  727.     }
  728.  
  729.     /**
  730.      * Set the URI anchor string
  731.      * everything after the "#".
  732.      *
  733.      * @param   string  $anchor  The URI anchor string.
  734.      *
  735.      * @return  void 
  736.      *
  737.      * @since   11.1
  738.      */
  739.     public function setFragment($anchor)
  740.     {
  741.         $this->fragment $anchor;
  742.     }
  743.  
  744.     /**
  745.      * Checks whether the current URI is using HTTPS.
  746.      *
  747.      * @return  boolean  True if using SSL via HTTPS.
  748.      *
  749.      * @since   11.1
  750.      */
  751.     public function isSSL()
  752.     {
  753.         return $this->getScheme(== 'https' true false;
  754.     }
  755.  
  756.     /**
  757.      * Checks if the supplied URL is internal
  758.      *
  759.      * @param   string  $url  The URL to check.
  760.      *
  761.      * @return  boolean  True if Internal.
  762.      *
  763.      * @since   11.1
  764.      */
  765.     public static function isInternal($url)
  766.     {
  767.         $uri self::getInstance($url);
  768.         $base $uri->toString(array('scheme''host''port''path'));
  769.         $host $uri->toString(array('scheme''host''port'));
  770.  
  771.         if (stripos($baseself::base()) !== && !empty($host))
  772.         {
  773.             return false;
  774.         }
  775.  
  776.         return true;
  777.     }
  778.  
  779.     /**
  780.      * Resolves //, ../ and ./ from a path and returns
  781.      * the result. Eg:
  782.      *
  783.      * /foo/bar/../boo.php    => /foo/boo.php
  784.      * /foo/bar/../../boo.php => /boo.php
  785.      * /foo/bar/.././/boo.php => /foo/boo.php
  786.      *
  787.      * @param   string  $path  The URI path to clean.
  788.      *
  789.      * @return  string  Cleaned and resolved URI path.
  790.      *
  791.      * @since   11.1
  792.      */
  793.     protected function _cleanPath($path)
  794.     {
  795.         $path explode('/'preg_replace('#(/+)#''/'$path));
  796.  
  797.         for ($i 0$n count($path)$i $n$i++)
  798.         {
  799.             if ($path[$i== '.' || $path[$i== '..')
  800.             {
  801.                 if (($path[$i== '.'|| ($path[$i== '..' && $i == && $path[0== ''))
  802.                 {
  803.                     unset($path[$i]);
  804.                     $path array_values($path);
  805.                     $i--;
  806.                     $n--;
  807.                 }
  808.                 elseif ($path[$i== '..' && ($i || ($i == && $path[0!= '')))
  809.                 {
  810.                     unset($path[$i]);
  811.                     unset($path[$i 1]);
  812.                     $path array_values($path);
  813.                     $i -= 2;
  814.                     $n -= 2;
  815.                 }
  816.             }
  817.         }
  818.  
  819.         return implode('/'$path);
  820.     }
  821. }

Documentation generated on Tue, 19 Nov 2013 15:16:15 +0100 by phpDocumentor 1.4.3