/** * @dataProvider providePaths */ public function testWfRemoveDotSegments($inputPath, $outputPath) { $this->assertEquals($outputPath, wfRemoveDotSegments($inputPath), "Testing {$inputPath} expands to {$outputPath}"); }
/** * Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer * is correct. * * The meaning of the PROTO_* constants is as follows: * PROTO_HTTP: Output a URL starting with http:// * PROTO_HTTPS: Output a URL starting with https:// * PROTO_RELATIVE: Output a URL starting with // (protocol-relative URL) * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending on which protocol was used for the current incoming request * PROTO_CANONICAL: For URLs without a domain, like /w/index.php , use $wgCanonicalServer. For protocol-relative URLs, use the protocol of $wgCanonicalServer * PROTO_INTERNAL: Like PROTO_CANONICAL, but uses $wgInternalServer instead of $wgCanonicalServer * * @todo this won't work with current-path-relative URLs * like "subdir/foo.html", etc. * * @param $url String: either fully-qualified or a local path + query * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the * protocol to use if $url or $wgServer is * protocol-relative * @return string Fully-qualified URL, current-path-relative URL or false if * no valid URL can be constructed */ function wfExpandUrl($url, $defaultProto = PROTO_CURRENT) { global $wgServer, $wgCanonicalServer, $wgInternalServer; $serverUrl = $wgServer; if ($defaultProto === PROTO_CANONICAL) { $serverUrl = $wgCanonicalServer; } // Make $wgInternalServer fall back to $wgServer if not set if ($defaultProto === PROTO_INTERNAL && $wgInternalServer !== false) { $serverUrl = $wgInternalServer; } if ($defaultProto === PROTO_CURRENT) { $defaultProto = WebRequest::detectProtocol() . '://'; } // Analyze $serverUrl to obtain its protocol $bits = wfParseUrl($serverUrl); $serverHasProto = $bits && $bits['scheme'] != ''; if ($defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL) { if ($serverHasProto) { $defaultProto = $bits['scheme'] . '://'; } else { // $wgCanonicalServer or $wgInternalServer doesn't have a protocol. This really isn't supposed to happen // Fall back to HTTP in this ridiculous case $defaultProto = PROTO_HTTP; } } $defaultProtoWithoutSlashes = substr($defaultProto, 0, -2); if (substr($url, 0, 2) == '//') { $url = $defaultProtoWithoutSlashes . $url; } elseif (substr($url, 0, 1) == '/') { // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone $url = ($serverHasProto ? '' : $defaultProtoWithoutSlashes) . $serverUrl . $url; } $bits = wfParseUrl($url); if ($bits && isset($bits['path'])) { $bits['path'] = wfRemoveDotSegments($bits['path']); return wfAssembleUrl($bits); } elseif ($bits) { # No path to expand return $url; } elseif (substr($url, 0, 1) != '/') { # URL is a relative path return wfRemoveDotSegments($url); } # Expanded URL is not valid. return false; }
/** * Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer * is correct. * * The meaning of the PROTO_* constants is as follows: * PROTO_HTTP: Output a URL starting with http:// * PROTO_HTTPS: Output a URL starting with https:// * PROTO_RELATIVE: Output a URL starting with // (protocol-relative URL) * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending * on which protocol was used for the current incoming request * PROTO_CANONICAL: For URLs without a domain, like /w/index.php , use $wgCanonicalServer. * For protocol-relative URLs, use the protocol of $wgCanonicalServer * PROTO_INTERNAL: Like PROTO_CANONICAL, but uses $wgInternalServer instead of $wgCanonicalServer * * @todo this won't work with current-path-relative URLs * like "subdir/foo.html", etc. * * @param string $url Either fully-qualified or a local path + query * @param string $defaultProto One of the PROTO_* constants. Determines the * protocol to use if $url or $wgServer is protocol-relative * @return string Fully-qualified URL, current-path-relative URL or false if * no valid URL can be constructed */ function wfExpandUrl($url, $defaultProto = PROTO_CURRENT) { global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest, $wgHttpsPort; if ($defaultProto === PROTO_CANONICAL) { $serverUrl = $wgCanonicalServer; } elseif ($defaultProto === PROTO_INTERNAL && $wgInternalServer !== false) { // Make $wgInternalServer fall back to $wgServer if not set $serverUrl = $wgInternalServer; } else { $serverUrl = $wgServer; if ($defaultProto === PROTO_CURRENT) { $defaultProto = $wgRequest->getProtocol() . '://'; } } // Analyze $serverUrl to obtain its protocol $bits = wfParseUrl($serverUrl); $serverHasProto = $bits && $bits['scheme'] != ''; if ($defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL) { if ($serverHasProto) { $defaultProto = $bits['scheme'] . '://'; } else { // $wgCanonicalServer or $wgInternalServer doesn't have a protocol. // This really isn't supposed to happen. Fall back to HTTP in this // ridiculous case. $defaultProto = PROTO_HTTP; } } $defaultProtoWithoutSlashes = substr($defaultProto, 0, -2); if (substr($url, 0, 2) == '//') { $url = $defaultProtoWithoutSlashes . $url; } elseif (substr($url, 0, 1) == '/') { // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes, // otherwise leave it alone. $url = ($serverHasProto ? '' : $defaultProtoWithoutSlashes) . $serverUrl . $url; } $bits = wfParseUrl($url); // ensure proper port for HTTPS arrives in URL // https://bugzilla.wikimedia.org/show_bug.cgi?id=65184 if ($defaultProto === PROTO_HTTPS && $wgHttpsPort != 443) { $bits['port'] = $wgHttpsPort; } if ($bits && isset($bits['path'])) { $bits['path'] = wfRemoveDotSegments($bits['path']); return wfAssembleUrl($bits); } elseif ($bits) { # No path to expand return $url; } elseif (substr($url, 0, 1) != '/') { # URL is a relative path return wfRemoveDotSegments($url); } # Expanded URL is not valid. return false; }
/** * Remap or embed a CSS URL path. * * @param string $file URL to remap/embed * @param string $query * @param string $local File path where the source was read from * @param string $remote URL path to the file * @param bool $embed Whether to do any data URI embedding * @return string Remapped/embedded URL data */ public static function remapOne($file, $query, $local, $remote, $embed) { // The full URL possibly with query, as passed to the 'url()' value in CSS $url = $file . $query; // Expand local URLs with absolute paths like /w/index.php to possibly protocol-relative URL, if // wfExpandUrl() is available. (This will not be the case if we're running outside of MW.) if (self::isLocalUrl($url) && function_exists('wfExpandUrl')) { return wfExpandUrl($url, PROTO_RELATIVE); } // Pass thru fully-qualified and protocol-relative URLs and data URIs, as well as local URLs if // we can't expand them. if (self::isRemoteUrl($url) || self::isLocalUrl($url)) { return $url; } if ($local === false) { // Assume that all paths are relative to $remote, and make them absolute $url = $remote . '/' . $url; } else { // We drop the query part here and instead make the path relative to $remote $url = "{$remote}/{$file}"; // Path to the actual file on the filesystem $localFile = "{$local}/{$file}"; if (file_exists($localFile)) { // Add version parameter as the first five hex digits // of the MD5 hash of the file's contents. $url .= '?' . substr(md5_file($localFile), 0, 5); if ($embed) { $data = self::encodeImageAsDataURI($localFile); if ($data !== false) { return $data; } } } // If any of these conditions failed (file missing, we don't want to embed it // or it's not embeddable), return the URL (possibly with ?timestamp part) } if (function_exists('wfRemoveDotSegments')) { $url = wfRemoveDotSegments($url); } return $url; }