// Copyright: Copyright (C) 2002-2007 Pristine Communications // Refer to RFC 1808 // Set the include path if (!defined("INCPATH_SET")) { require_once dirname(__FILE__) . "/incpath.inc.php"; } // Referenced subroutines require_once "monica/parseurl.inc.php"; require_once "monica/requri.inc.php"; // Settings define("REL2ABS_SKIP_FRAGMENT", true); define("REL2ABS_NO_HOST", true); define("REL2ABS_RDIFF_KEEP", true); define("REL2ABS_RDIFF_STRIP", false); // rel2abs: Conver a relative URL to an absolute URL // Refer to RFC 1808 function rel2abs($rel, $base = null, $skip_fragment = false, $no_host = false, $rdiff = true) { // Keep the original. We may need to bounce intact later. $rel_o = $rel; // Make the base absolute first if (!is_null($base)) { $base = rel2abs($base); // Default base to the current URL } else { $base = REQUEST_FULLURI; } // Skip the fragment if (substr($rel, 0, 1) == "#" && $skip_fragment) { return $rel; } // Return if it is completely empty (RFC 1808, 4, step 2, a) if ($rel == "") { return $base; } // Parse the URL first $rel_a = parse_url_rfc1808($rel); // Fail to parse - bounce intact if (is_null($rel_a)) { return $rel_o; } if ( !array_key_exists("net_loc", $rel_a) && array_key_exists("path", $rel_a) && substr($rel_a["path"], 0, 1) == "/" && $rdiff) { $rel_a["path"] = ROOT_DIFF . $rel_a["path"]; } $base_a = parse_url_rfc1808($base); // Fail to parse - bounce intact if (is_null($base_a)) { return $rel_o; } if (!array_key_exists("path", $base_a)) { $base_a["path"] = "/"; } if (!array_key_exists("scheme", $base_a)) { $base_a["scheme"] = "http"; } // Return if it starts with a scheme (RFC 1808, 4, step 2, b) if (array_key_exists("scheme", $rel_a)) { return $rel; } // Inherit the scheme of the base URL (RFC 1808, 4, step 2, c) $rel_a["scheme"] = $base_a["scheme"]; $skip_to_7 = false; // The net_loc is not empty (RFC 1808, 4, step 3) if (array_key_exists("net_loc", $rel_a)) { $skip_to_7 = true; // Inherit the net_loc of the base URL (if any) } else { if (array_key_exists("net_loc", $base_a)) { $rel_a["net_loc"] = $base_a["net_loc"]; } // The path is not relative (RFC 1808, 4, step 4) if ( array_key_exists("path", $rel_a) && substr($rel_a["path"], 0, 1) == "/") { $skip_to_7 = true; } else { // The path is empty (RFC 1808, 4, step 5) if (!array_key_exists("path", $rel_a)) { $rel_a["path"] = $base_a["path"]; // The params is not empty (RFC 1808, 4, step 5, a) if (array_key_exists("params", $rel_a)) { $skip_to_7 = true; } else { if (array_key_exists("params", $base_a)) { $rel_a["params"] = $base_a["params"]; } // The query is not empty (RFC 1808, 4, step 5, b) if (array_key_exists("query", $rel_a)) { $skip_to_7 = true; } else { if (array_key_exists("query", $base_a)) { $rel_a["query"] = $base_a["query"]; } $skip_to_7 = true; } } } } } // Resolve the path (RFC 1808, 4, step 6) if (!$skip_to_7) { $rel_a["path"] = preg_replace("/[^\/]+$/", "", $base_a["path"]) . $rel_a["path"]; $rel_a["path"] = stdpath($rel_a["path"]); } // Compose the URL (RFC 1808, 4, step 7) $abs = ""; if (!$no_host) { $abs .= $rel_a["scheme"] . ":"; if (array_key_exists("net_loc", $rel_a)) { $abs .= "//" . $rel_a["net_loc"]; } } $abs .= $rel_a["path"]; if (array_key_exists("params", $rel_a)) { $abs .= ";" . $rel_a["params"]; } if (array_key_exists("query", $rel_a)) { $abs .= "?" . $rel_a["query"]; } if (array_key_exists("fragment", $rel_a)) { $abs .= "#" . $rel_a["fragment"]; } return $abs; } // abs2rel: Conver an absolute URL to a relative URL function abs2rel($abs, $base = null) { // Keep the original. We may need to bounce intact later. $abs_o = $abs; // Make the base absolute first if (!is_null($base)) { $base = rel2abs($base); // Default base to the current URL } else { $base = REQUEST_FULLURI; } $abs = rel2abs($abs, $base); // Parse the URL first $abs_a = parse_url_rfc1808($abs); // Fail to parse - bounce intact if (is_null($abs_a)) { return $abs_o; } if (!array_key_exists("path", $abs_a)) { $abs_a["path"] = "/"; } $base_a = parse_url_rfc1808($base); // Fail to parse - bounce intact if (is_null($base_a)) { return $abs_o; } // Return if not the same scheme if ($abs_a["scheme"] != $base_a["scheme"]) { return $abs; } unset($abs_a["scheme"]); // Return if not the same network location (net_loc) if ( !((!array_key_exists("net_loc", $abs_a) && !array_key_exists("net_loc", $base_a)) || (array_key_exists("net_loc", $abs_a) && array_key_exists("net_loc", $base_a) && $abs_a["net_loc"] == $base_a["net_loc"]))) { return $abs; } unset($abs_a["net_loc"]); if (!array_key_exists("path", $abs_a)) { $abs_a["path"] = "/"; } // Different path -- find the path difference if ($abs_a["path"] != $base_a["path"]) { // Remove the last segment from the base URL $base_path = preg_replace("/[^\/]+$/", "", $base_a["path"]); $abs_path = $abs_a["path"]; // Remove the leading absolute slash $base_path = preg_replace("/^\//", "", $base_path); $abs_path = preg_replace("/^\//", "", $abs_path); // Check each path segment from the left while (preg_match("/^([^\/]+\/)(.*)$/", $base_path, $m)) { // Not sharing the same path segment if (substr($abs_path, 0, strlen($m[1])) != $m[1]) { break; } $base_path = $m[2]; $abs_path = substr($abs_path, strlen($m[1])); // Nothing left, but false is not what we want if ($abs_path === false) { $abs_path = ""; break; } } // Turn each remaining segment to ".." and prepend it to the path $abs_a["path"] = preg_replace("/[^\/]+/", "..", $base_path) . $abs_path; // Remove the trailing slash of the ancestor directories if ( $abs_a["path"] == "../" || preg_match("/\/\.\.\/$/", $abs_a["path"])) { $abs_a["path"] = substr($abs_a["path"], 0, -1); } // Nothing left means the current directory if ($abs_a["path"] == "") { $abs_a["path"] = "."; } // Same path } else { // Different params if ( !((!array_key_exists("params", $abs_a) && !array_key_exists("params", $base_a)) || (array_key_exists("params", $abs_a) && array_key_exists("params", $base_a) && $abs_a["params"] == $base_a["params"]))) { // No further checks // Keep the last segment of the path $abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]); if ($abs_a["path"] == "") { $abs_a["path"] = "."; } // Same params } else { // Different query if ( !((!array_key_exists("query", $abs_a) && !array_key_exists("query", $base_a)) || (array_key_exists("query", $abs_a) && array_key_exists("query", $base_a) && $abs_a["query"] == $base_a["query"]))) { // No further checks // Keep the last segment of the path $abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]); if ($abs_a["path"] == "") { $abs_a["path"] = "."; } // Same query } else { // Everything is the same (fragment not counted) // Keep only the fragment if there is a fragment if (array_key_exists("fragment", $abs_a)) { unset($abs_a["path"]); unset($abs_a["params"]); unset($abs_a["query"]); // No fragment } else { // Keep the last segment of the path $abs_a["path"] = preg_replace("/^\/(?:[^\/]+\/)*/", "", $abs_a["path"]); if ($abs_a["path"] == "") { $abs_a["path"] = "."; } } } } } // Compose the URL $rel = ""; if (array_key_exists("path", $abs_a)) { $rel .= $abs_a["path"]; } if (array_key_exists("params", $abs_a)) { $rel .= ";" . $abs_a["params"]; } if (array_key_exists("query", $abs_a)) { $rel .= "?" . $abs_a["query"]; } if (array_key_exists("fragment", $abs_a)) { $rel .= "#" . $abs_a["fragment"]; } return $rel; } // stdpath: Standardize a path name // Refer to RFC 1808, 4, step 6 function stdpath($path) { // Remove all the "./" (RFC 1808, 4, step 6, a) $path = preg_replace("/(?<=\/)\.\//", "", $path); $path = preg_replace("/^\.\//", "", $path); // Remove the trailing "." (RFC 1808, 4, step 6, b) $path = preg_replace("/(?<=\/)\.$/", "", $path); // Remove all the "/../" (RFC 1808, 4, step 6, c) while ( preg_match("/^(.*?)([^\/]+)\/\.\.\/(.*)$/", $path, $m) && $m[2] != "..") { $path = $m[1] . $m[3]; } // Remove the trailing "/.." (RFC 1808, 4, step 6, d) while ( preg_match("/^(.*?)([^\/]+)\/\.\.$/", $path, $m) && $m[2] != "..") { $path = $m[1]; } return $path; } ?>