/** * Получить абсолютный URL * @param string $href * @param string $referrer * @return string * @throws nc_search_exception */ protected function resolve_link($href, $referrer = null) { $referrer_parts = $this->parse_utf8_url($referrer); // Абсолютная ссылка без указания протокола — неправильно обрабатывается // функцией parse_url() до PHP 5.4.7 if (substr($href, 0, 2) == "//") { $scheme = isset($referrer_parts['scheme']) ? $referrer_parts['scheme'] : 'http'; $href = "{$scheme}:{$href}"; } $href_parts = $this->parse_utf8_url($href); if (!is_array($href_parts)) { $href_parts = array(); } // $href == "#" $result_parts = $href_parts; if (!isset($href_parts["host"])) { // path with no host name if ($referrer == 'http:///') { return false; } if ($referrer == 'http://') { return false; } if (!$referrer_parts || !isset($referrer_parts["host"])) { throw new nc_search_exception("Cannot resolve full URL: '{$href}' (no referrer)"); } foreach (array("scheme", "host", "port", "path") as $p) { if (isset($referrer_parts[$p]) && !isset($href_parts[$p])) { $result_parts[$p] = $referrer_parts[$p]; } } if ($result_parts["path"][0] != "/") { // relative path $referrer_dir = substr($referrer_parts["path"], -1) == '/' ? $referrer_parts["path"] : dirname($referrer_parts["path"]) . "/"; $result_parts["path"] = $referrer_dir . $result_parts["path"]; } } // end of "path with no host name" // "http://mysite.org" → "http://mysite.org/" if (!isset($result_parts["path"])) { $result_parts["path"] = "/"; } // get rid of "./", "../" if (strpos($result_parts["path"], "./") !== false) { $path_fragments = array(); foreach (explode("/", $result_parts["path"]) as $part) { if ($part == '.' || $part == '') { continue; } if ($part == '..') { array_pop($path_fragments); } else { $path_fragments[] = $part; } } $path = join("/", $path_fragments); if (substr($href_parts["path"], -1) == '/') { $path .= "/"; } if ($path[0] != '/') { $path = "/{$path}"; } $result_parts["path"] = $path; } // Производится сортировка параметров для того, чтобы не запрашивать страницу // дважды, если в ссылках на неё параметры перечислены в разном порядке, например: // /sub/?tag=22&curPos=10 и /sub/?curPos=10&tag=22 будут считаться одной страницей // Параметр модуля: IndexerNormalizeLinks if (isset($result_parts["query"]) && strpos($result_parts["query"], "&") && nc_search::should('IndexerNormalizeLinks')) { $params = explode("&", $result_parts["query"]); sort($params); $result_parts["query"] = join("&", $params); } // IDN & non-latin paths $result_parts["host"] = nc_search_util::encode_host($result_parts["host"]); $result_parts["path"] = nc_search_util::encode_path($result_parts["path"]); // MySite.ORG == mysite.org $result_parts["host"] = strtolower($result_parts["host"]); $full_url = strtolower($result_parts["scheme"]) . "://" . $result_parts["host"] . (isset($result_parts["port"]) ? ":{$result_parts['port']}" : "") . $result_parts["path"] . (isset($result_parts["query"]) ? "?{$result_parts['query']}" : ""); return $full_url; }