/** * Attempt to use mod_rewrite to improve this URL. * * @param ID_TEXT The name of the zone for this * @param array A map of variables to include in our URL * @param boolean Force inclusion of the index.php name into a short URL, so something may tack on extra parameters to the result here * @return ?URLPATH The improved URL (NULL: couldn't do anything) */ function _url_rewrite_params($zone_name, $vars, $force_index_php = false) { global $URL_REMAPPINGS; if ($URL_REMAPPINGS === NULL) { $old_style = get_option('htm_short_urls') != '1'; require_code('url_remappings'); $URL_REMAPPINGS = get_remappings($old_style); } // Find mapping foreach ($URL_REMAPPINGS as $_remapping) { list($remapping, $target, $require_full_coverage) = $_remapping; // if (count($remapping)!=$num_vars) continue; $good = true; $last_key_num = count($remapping); $loop_cnt = 0; foreach ($remapping as $key => $val) { $loop_cnt++; $last = $loop_cnt == $last_key_num; if (!is_string($val) && $val !== NULL) { $val = strval($val); } if (array_key_exists($key, $vars) && is_integer($vars[$key])) { $vars[$key] = strval($vars[$key]); } if (!((isset($vars[$key]) || $val === NULL && $key == 'type' && array_key_exists('id', $vars)) && ($key != 'page' || $vars[$key] != '' || $val === '') && (!array_key_exists($key, $vars) || $vars[$key] != '' || !$last) && ($val === NULL || $vars[$key] == $val))) { $good = false; break; } } if ($require_full_coverage) { foreach ($_GET as $key => $val) { if (!is_string($val)) { continue; } if (substr($key, 0, 5) == 'keep_' && !skippable_keep($key, $val)) { $good = false; } } foreach ($vars as $key => $val) { if (!array_key_exists($key, $remapping) && $val !== NULL && ($key != 'page' || $vars[$key] != '')) { $good = false; } } } if ($good) { // We've found one, now let's sort out the target $makeup = $target; if ($GLOBALS['DEBUG_MODE']) { foreach ($vars as $key => $val) { if (is_integer($val)) { $vars[$key] = strval($val); } } } $extra_vars = array(); foreach (array_keys($remapping) as $key) { if (!isset($vars[$key])) { continue; } $val = $vars[$key]; unset($vars[$key]); $makeup = str_replace(strtoupper($key), ocp_url_encode_mini($val, true), $makeup); } if (!$require_full_coverage) { $extra_vars += $vars; } $makeup = str_replace('TYPE', 'misc', $makeup); if ($makeup == '') { $makeup .= get_zone_default_page($zone_name) . '.htm'; } if ($extra_vars != array() || $force_index_php) { if (get_option('htm_short_urls') != '1') { $makeup .= '/index.php'; } $first = true; foreach ($extra_vars as $key => $val) { if ($val === NULL) { continue; } if (is_integer($key)) { $key = strval($key); } if ($val === SELF_REDIRECT) { $val = get_self_url(true, true); } $makeup .= ($first ? '?' : '&') . $key . '=' . ocp_url_encode($val, true); $first = false; } } return $makeup; } } return NULL; }
/** * Convert a local URL to a page-link. * * @param URLPATH The URL to convert. Note it may not be a short URL, and it must be based on the local base URL (else failure WILL occur). * @param boolean Whether to only convert absolute URLs. Turn this on if you're not sure what you're passing is a URL not and you want to be extra safe. * @param boolean Whether to only allow perfect conversions. * @return string The page link (blank: could not convert). */ function _url_to_pagelink($url, $abs_only = false, $perfect_only = true) { if ($abs_only && substr($url, 0, 7) != 'http://' && substr($url, 0, 8) != 'https://') { return ''; } // Try and strip any variants of the base URL from our $url variable, to make it relative $non_www_base_url = str_replace('http://www.', 'http://', get_base_url()); $www_base_url = str_replace('http://', 'http://www.', get_base_url()); $url = preg_replace('#^' . str_replace('#', '\\#', preg_quote(get_base_url() . '/')) . '#', '', $url); $url = preg_replace('#^' . str_replace('#', '\\#', preg_quote($non_www_base_url . '/')) . '#', '', $url); $url = preg_replace('#^' . str_replace('#', '\\#', preg_quote($www_base_url . '/')) . '#', '', $url); if (substr($url, 0, 7) == 'http://') { return ''; } if (substr($url, 0, 8) == 'https://') { return ''; } if (substr($url, 0, 1) != '/') { $url = '/' . $url; } // Parse the URL if (strpos($url, '&') !== false && strpos($url, '?') === false) { $url = preg_replace('#&#', '?', $url, 1); } // Old-style short URLs workl like this (no first ?, just &) $parsed_url = @parse_url($url); if ($parsed_url === false) { require_code('site'); attach_message(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL', escape_html($url)), 'warn'); return ''; } // Work out the zone $slash_pos = strpos($parsed_url['path'], '/', 1); $zone = $slash_pos !== false ? substr($parsed_url['path'], 1, $slash_pos - 1) : ''; if (!in_array($zone, find_all_zones())) { $zone = ''; $slash_pos = false; } $parsed_url['path'] = $slash_pos === false ? substr($parsed_url['path'], 1) : substr($parsed_url['path'], $slash_pos + 1); // everything AFTER the zone $parsed_url['path'] = preg_replace('#/index\\.php$#', '', $parsed_url['path']); $attributes = array(); $attributes['page'] = ''; // hopefully will get overwritten with a real one // Convert short URL path info into extra implied attribute data require_code('url_remappings'); foreach (array(false, true) as $method) { $mappings = get_remappings($method); foreach ($mappings as $mapping) { if (is_null($mapping)) { continue; } list($params, $match_string, ) = $mapping; $match_string_pattern = preg_replace('#[A-Z]+#', '[^\\&\\?]+', preg_quote($match_string)); $zones = find_all_zones(); if (preg_match('#^' . $match_string_pattern . '$#', $parsed_url['path']) != 0) { $attributes = array_merge($attributes, $params); $bits_pattern = explode('/', preg_replace('#\\.htm$#', '', $match_string)); $bits_real = explode('/', preg_replace('#\\.htm$#', '', $parsed_url['path']), count($bits_pattern)); foreach ($bits_pattern as $i => $bit) { if (array_key_exists(strtolower($bit), $params) && strtoupper($bit) == $bit && is_null($params[strtolower($bit)])) { $attributes[strtolower($bit)] = $bits_real[$i]; } } break; } } } if ($attributes == array('page' => '') && $parsed_url['path'] != '') { if (strpos($parsed_url['path'], '/pg/') === false && strpos($parsed_url['path'], '.htm') === false && $parsed_url['path'] != 'index.php') { return ''; } } // Parse query string component into the waiting (and partly-filled-already) attribute data array if (array_key_exists('query', $parsed_url)) { $bits = explode('&', $parsed_url['query']); foreach ($bits as $bit) { $_bit = explode('=', $bit, 2); if (count($_bit) == 2) { $attributes[$_bit[0]] = $_bit[1]; if (strpos($attributes[$_bit[0]], ':') !== false) { if ($perfect_only) { return ''; } // Could not convert this URL to a page-link, because it contains a colon unset($attributes[$_bit[0]]); } } } } // Put it together $page_link = $zone . ':' . $attributes['page']; if (array_key_exists('type', $attributes)) { $page_link .= ':' . $attributes['type']; } elseif (array_key_exists('id', $attributes)) { $page_link .= ':'; } if (array_key_exists('id', $attributes)) { $page_link .= ':' . urldecode($attributes['id']); } foreach ($attributes as $key => $val) { if (!is_string($val)) { $val = strval($val); } if ($key != 'page' && $key != 'type' && $key != 'id') { $page_link .= ':' . $key . '=' . urldecode($val); } } // Hash bit? if (array_key_exists('fragment', $parsed_url)) { $page_link .= '#' . $parsed_url['fragment']; } return $page_link; }