protected static function rebuildUrl(array $p)
	{
		$url = '';
		if ($p['scheme'] !== '')
		{
			$url .= $p['scheme'] . ':';
		}
		if ($p['host'] !== '')
		{
			$url .= '//';

			// Add the credentials if applicable
			if ($p['user'] !== '')
			{
				// Reencode the credentials in case there are invalid chars in them, or suspicious
				// characters such as : or @ that could confuse a browser into connecting to the
				// wrong host (or at least, to a host that is different than the one we thought)
				$url .= rawurlencode(urldecode($p['user']));

				if ($p['pass'] !== '')
				{
					$url .= ':' . rawurlencode(urldecode($p['pass']));
				}

				$url .= '@';
			}

			$url .= $p['host'];

			// Append the port number (note that as per the regexp it can only contain digits)
			if ($p['port'] !== '')
			{
				$url .= ':' . $p['port'];
			}
		}
		elseif ($p['scheme'] === 'file')
		{
			// Allow the file: scheme to not have a host and ensure it starts with slashes
			$url .= '//';
		}

		// Build the path, including the query and fragment parts
		$path = $p['path'] . $p['query'] . $p['fragment'];

		/**
		* "For consistency, URI producers and normalizers should use uppercase hexadecimal digits
		* for all percent- encodings."
		*
		* @link http://tools.ietf.org/html/rfc3986#section-2.1
		*/
		$path = preg_replace_callback(
			'/%.?[a-f]/',
			function ($m)
			{
				return strtoupper($m[0]);
			},
			$path
		);

		// Append the sanitized path to the URL
		$url .= self::sanitizeUrl($path);

		// Replace the first colon if there's no scheme and it could potentially be interpreted as
		// the scheme separator
		if (!$p['scheme'])
		{
			$url = preg_replace('#^([^/]*):#', '$1%3A', $url);
		}

		return $url;
	}