Files
server/usr/share/psa-pear/pear/php/Horde/Url.php
2026-01-07 20:52:11 +01:00

414 lines
11 KiB
PHP

<?php
/**
* This file contains the Horde_Url class for manipulating URLs.
*
* Copyright 2009-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Jan Schneider <jan@horde.org>
* @author Michael Slusarz <slusarz@horde.org>
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @category Horde
* @package Url
*/
/**
* The Horde_Url class represents a single URL and provides methods for
* manipulating URLs.
*
* @author Jan Schneider <jan@horde.org>
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @package Url
*/
class Horde_Url
{
/**
* The anchor string (a/k/a fragment).
*
* @var string
*/
public $anchor = '';
/**
* Any PATH_INFO to be added to the URL.
*
* @var string
*/
public $pathInfo;
/**
* The query parameters.
*
* The keys are paramter names, the values parameter values. Array values
* will be added to the URL using name[]=value notation.
*
* @var array
*/
public $parameters = array();
/**
* Whether to output the URL in the raw URL format or HTML-encoded.
*
* @var boolean
*/
public $raw;
/**
* A callback function to use when converting to a string.
*
* @var callback
*/
public $toStringCallback;
/**
* The basic URL, without query parameters.
*
* @var string
*/
public $url;
/**
* Cached parameter list for use in toString().
*
* @var array
*/
protected $_cache;
/**
* Constructor.
*
* @param string|Horde_Url $url The basic URL, with or without query
* parameters.
* @param boolean $raw Whether to output the URL in the raw URL
* format or HTML-encoded.
*/
public function __construct($url = '', $raw = null)
{
if ($url instanceof Horde_Url) {
foreach (get_object_vars($url) as $k => $v) {
$this->$k = $v;
}
if (!is_null($raw)) {
$this->raw = $raw;
}
return;
}
if (($pos = strrpos($url, '#')) !== false) {
$this->anchor = urldecode(substr($url, $pos + 1));
$url = substr($url, 0, $pos);
}
if (($pos = strrpos($url, '?')) !== false) {
$query = substr($url, $pos + 1);
$url = substr($url, 0, $pos);
/* Check if the argument separator has been already
* htmlentities-ized in the URL. */
if (strpos($query, '&amp;') !== false) {
$query = html_entity_decode($query);
if (is_null($raw)) {
$raw = false;
}
} elseif (strpos($query, '&') !== false) {
if (is_null($raw)) {
$raw = true;
}
}
$pairs = explode('&', $query);
foreach ($pairs as $pair) {
$result = explode('=', urldecode($pair), 2);
$this->add($result[0], isset($result[1]) ? $result[1] : null);
}
}
$this->url = $url;
$this->raw = $raw;
}
/**
* Returns a clone of this object. Useful for chaining.
*
* @return Horde_Url A clone of this object.
*/
public function copy()
{
$url = clone $this;
return $url;
}
/**
* Adds one or more query parameters.
*
* @param mixed $parameters Either the name value or an array of
* name/value pairs.
* @param string $value If specified, the value part ($parameters is
* then assumed to just be the parameter name).
*
* @return Horde_Url This (modified) object, to allow chaining.
*/
public function add($parameters, $value = null)
{
if (!is_array($parameters)) {
$parameters = array($parameters => $value);
}
foreach ($parameters as $parameter => $value) {
if (substr($parameter, -2) == '[]') {
$parameter = substr($parameter, 0, -2);
if (!isset($this->parameters[$parameter])) {
$this->parameters[$parameter] = array();
}
$this->parameters[$parameter][] = $value;
} else {
$this->parameters[$parameter] = $value;
}
}
unset($this->_cache);
return $this;
}
/**
* Removes one ore more parameters.
*
* @param mixed $remove Either a single parameter to remove or an array
* of parameters to remove.
*
* @return Horde_Url This (modified) object, to allow chaining.
*/
public function remove($parameters)
{
if (!is_array($parameters)) {
$parameters = array($parameters);
}
foreach ($parameters as $parameter) {
unset($this->parameters[$parameter]);
}
unset($this->_cache);
return $this;
}
/**
* Sets the URL anchor.
*
* @param string $anchor An anchor to add.
*
* @return Horde_Url This (modified) object, to allow chaining.
*/
public function setAnchor($anchor)
{
$this->anchor = $anchor;
return $this;
}
/**
* Sets the $raw value. This call can be chained.
*
* @param boolean $raw Whether to output the URL in the raw URL format or
* HTML-encoded.
*
* @return Horde_Url This object, to allow chaining.
*/
public function setRaw($raw)
{
$this->raw = $raw;
return $this;
}
/**
* Sets the URL scheme.
*
* @param string $scheme The URL scheme.
* @param boolean $replace Force using $scheme, even if it already
* exists?
*
* @return Horde_Url This object, to allow chaining.
*/
public function setScheme($scheme = 'http', $replace = false)
{
$pos = stripos($this->url, '://');
if ($pos === false) {
$this->url = $scheme . '://' . $this->url;
} elseif ($replace) {
$this->url = substr_replace($this->url, $scheme . '://', 0, $pos);
}
return $this;
}
/**
* Creates the full URL string.
*
* @param boolean $raw Whether to output the URL in the raw URL format
* or HTML-encoded.
* @param boolean $full Output the full URL?
*
* @return string The string representation of this object.
*/
public function toString($raw = false, $full = true)
{
if ($this->toStringCallback) {
$callback = $this->toStringCallback;
$this->toStringCallback = null;
$ret = call_user_func($callback, $this);
$this->toStringCallback = $callback;
return $ret;
}
$url = $full
? $this->url
: parse_url($this->url, PHP_URL_PATH);
if (strlen($this->pathInfo)) {
$url = rtrim($url, '/') . '/';
if ($raw) {
$url .= $this->pathInfo;
} else {
$url .= implode('/', array_map('rawurlencode', explode('/', $this->pathInfo)));
}
}
if ($params = $this->_getParameters()) {
$url .= '?' . implode($raw ? '&' : '&amp;', $params);
}
if ($this->anchor) {
$url .= '#' . ($raw ? $this->anchor : rawurlencode($this->anchor));
}
return strval($url);
}
/**
* Return a formatted list of URL parameters.
*
* @return array Parameter list.
*/
protected function _getParameters()
{
if (!isset($this->_cache)) {
$params = array();
foreach ($this->parameters as $p => $v) {
if (is_array($v)) {
foreach ($v as $val) {
$params[] = rawurlencode($p) . '[]=' . rawurlencode($val);
}
} else {
$params[] = rawurlencode($p) .
(strlen($v) ? ('=' . rawurlencode($v)) : '');
}
}
$this->_cache = $params;
}
return $this->_cache;
}
/**
* Creates the full URL string.
*
* @return string The string representation of this object.
*/
public function __toString()
{
return $this->toString($this->raw);
}
/**
* Generates a HTML link tag out of this URL.
*
* @param array $attributes A hash with any additional attributes to be
* added to the link. If the attribute name is
* suffixed with ".raw", the attribute value
* won't be HTML-encoded.
*
* @return string An <a> tag representing this URL.
*/
public function link(array $attributes = array())
{
$url = (string)$this->setRaw(false);
$link = '<a';
if (!empty($url)) {
$link .= " href=\"$url\"";
}
foreach ($attributes as $name => $value) {
if (!strlen($value)) {
continue;
}
if (substr($name, -4) == '.raw') {
$link .= ' ' . htmlspecialchars(substr($name, 0, -4))
. '="' . $value . '"';
} else {
$link .= ' ' . htmlspecialchars($name)
. '="' . htmlspecialchars($value) . '"';
}
}
return $link . '>';
}
/**
* Add a unique parameter to the URL to aid in cache-busting.
*
* @return Horde_Url This (modified) object, to allow chaining.
*/
public function unique()
{
return $this->add('u', uniqid(mt_rand()));
}
/**
* Sends a redirect request to the browser to the URL in this object.
*
* @throws Horde_Url_Exception
*/
public function redirect()
{
$url = strval($this->setRaw(true));
if (!strlen($url)) {
throw new Horde_Url_Exception('Redirect failed: URL is empty.');
}
header('Location: ' . $url);
exit;
}
/**
* URL-safe base64 encoding, with trimmed '='.
*
* @param string $string String to encode.
*
* @return string URL-safe, base64 encoded data.
*/
public static function uriB64Encode($string)
{
return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($string));
}
/**
* Decode URL-safe base64 data, dealing with missing '='.
*
* @param string $string Encoded data.
*
* @return string Decoded data.
*/
public static function uriB64Decode($string)
{
$data = str_replace(array('-', '_'), array('+', '/'), $string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
}