Súbor: [Platon] / Metafox / lib / Platon.php (stiahnutie)
Revízia 1.12, Wed Nov 8 01:12:03 2017 UTC (7 years, 2 months ago) by nepto
Zmeny od 1.11: +132 -39 [lines]
Platon.php synced from phpPlatonLib
Use Platon::htmlspecialchars_encoding() at initialization
|
<?php
/**
* Platon - Platon SDG PHP framework
*
* This class provides basic Platon SDG (http://platon.sk/) PHP framework.
* At the beginning we have set of common functions we use in our PHP
* applications. After moving closer to PEAR and its coding standarts and
* realizing need of function names prefixation, we recognize to group these
* functions into base Platon class.
*
* Use class methods just like PHP core functions with "Platon::" prepended.
* See following example of use for detailed information.
*
* Usage:
* <?php
* require_once 'Platon.php';
* Platon::function_name();
* ?>
*
* @author Ondrej Jombik <nepto@platon.sk>
* @author Igor Mino <igor@platon.sk>
* @package Platon
* @version 1.1
* @access public
*/
/* $Platon: phpPlatonLib/Platon/Platon.php,v 1.43 2017/11/08 01:09:07 nepto Exp $ */
class Platon
{
/**
* Parses ID parameter from separate value in query string
* or fallback to $key_name CGI variable.
*
* @param string $key_name name of ID parameter
* @param mixed $exploded_qs exploded query string (array)
* or true to perform split method itself
* or false to skip extraction from QS
* @return parsed ID param
*/
static function parse_id_param($key_name = 'id', $exploded_qs = true) /* {{{ */
{
$ret = '';
if ($exploded_qs != false) {
if (! is_array($exploded_qs)) {
$exploded_qs = explode('&', $_SERVER['QUERY_STRING']);
}
foreach ($exploded_qs as $val) {
if (strlen($val) > 0 && strpos($val, '=') === false) {
$ret = $val;
break;
}
}
}
if ($ret == '') {
foreach ($_GET as $key => $val) {
if (! strcasecmp($key, $key_name) && (is_array($val) || strlen($val) > 0)) {
$ret = $val;
break;
}
}
}
if ($ret == '') {
foreach ($_POST as $key => $val) {
if (! strcasecmp($key, $key_name) && (is_array($val) || strlen($val) > 0)) {
$ret = $val;
break;
}
}
}
return $ret;
} /* }}} */
/**
* Returns value of CGI variable.
*
* @param string $name CGI variable name
* @param mixed $default_value what to return if variable not present
* @return stripslashed value of CGI variable
*/
static function get_cgi_var($name, $default_value = null) /* {{{ */
{
static $magic_quotes_gpc = null;
if ($magic_quotes_gpc === null) {
$magic_quotes_gpc = get_magic_quotes_gpc();
}
$var = @$_GET[$name];
if (! isset($var)) {
$var = @$_POST[$name];
}
if (isset($var)) {
if ($magic_quotes_gpc) {
if (is_array($var)) {
foreach (array_keys($var) as $key) {
$var[$key] = stripslashes($var[$key]);
}
} else {
$var = stripslashes($var);
}
}
} else {
$var = @$default_value;
}
return $var;
} /* }}} */
/**
* Changes directory back of $dir.
*
* @param string $dir directory path
* @return none
*/
static function chdir_back($dir) /* {{{ */
{
$dir_back = Platon::dir_back($dir);
if (strlen($dir_back) > 0)
return chdir($dir_back);
return false;
} /* }}} */
/**
* Creates back directory of $dir.
*
* @param string $dir directory path
* @return back directory of $dir (contains several '../')
*/
static function dir_back($dir) /* {{{ */
{
$dir_back = '';
$i = substr_count(Platon::append_slash($dir), '/');
for (; $i > 0; $i--)
$dir_back .= '../';
return $dir_back;
} /* }}} */
/**
* Returns current microtime.
*
* @param string $mtime microtime (optional)
* @return int current microtime
*/
static function get_mtime($mtime = null) /* {{{ */
{
if ($mtime === null) {
$mtime = microtime();
}
$mtime = explode(' ', $mtime);
$mtime = $mtime[1] + $mtime[0];
return $mtime;
} /* }}} */
/**
* Performs a HTTP/1.1 redirect according to RFC 2068
*
* @param string $where where to redirect (URL or local script)
* @param boolean $temporary if such redirect is only temporary one
* @todo implement HTML page redirecting if output was aleady sent
*/
static function redirect($where, $temporary = false, $status_code = 301) /* {{{ */
{
$url = '';
if (! strncmp($where, "ftp://", 6)
|| ! strncmp($where, "http://", 7)
|| ! strncmp($where, "https://", 8)) {
$url = $where;
} else {
$url = "http://";
$http_host = @$_SERVER['HTTP_HOST'];
$server_name = @$_SERVER['SERVER_NAME'];
if (isset($http_host) && strlen($http_host) > 0) {
$url .= $http_host;
} elseif (isset($server_name) && strlen($server_name) > 0) {
$url .= $server_name;
}
if ($where[0] != '/') {
$url .= Platon::get_path_without_scriptname($_SERVER['REQUEST_URI']);
}
$url .= $where;
}
header('Location: '.$url);
if (! $temporary) {
switch($status_code) {
case 303:
header('HTTP/1.1 303 See Other');
break;
case 302:
header('HTTP/1.1 302 Found');
break;
case 301:
default:
header('HTTP/1.1 301 Moved Permanently');
break;
}
}
exit;
} /* }}} */
/**
* Changes a HTTP host using permanent redirect
*
* @param string $new_http_host destination HTTP host
* @param string $old_http_host source HTTP host (string or array)
* empty string means any host
*/
static function redirect_change_host($new_http_host, $old_http_host = '') /* {{{ */
{
if (strlen($_SERVER['HTTP_HOST']) <= 0) {
return;
}
if (! strcasecmp($new_http_host, $_SERVER['HTTP_HOST'])) {
return;
}
if (is_array($old_http_host)) {
foreach ($old_http_host as $http_host) {
Platon::redirect_change_host($new_http_host, $http_host);
}
return;
}
if (strlen($old_http_host) > 0) {
if (strcasecmp($old_http_host, $_SERVER['HTTP_HOST'])) {
return;
}
}
$schema = strcasecmp($_SERVER['HTTPS'], 'on') ? 'http' : 'https';
$request_uri = $_SERVER['REQUEST_URI'];
return Platon::redirect("$schema://$new_http_host$request_uri");
} /* }}} */
/**
* Redirects if it is neccessary for particular file.
*
* @param string $file filename
* @param string $url url where to redirect
* @return allways true
*/
static function redirect_test($file, $url) /* {{{ */
{
if (is_array($file)) {
foreach ($file as $one_file) {
Platon::redirect_test($one_file, $url);
}
return true;
}
if (! isset($_SERVER['PHP_SELF'])
|| stripos($_SERVER['PHP_SELF'], $file) === false ) {
return true;
}
if (strlen($url) <= 0) {
trigger_error('empty input parameter $url'
.' in Platon::redirect_test()'.$method, E_USER_ERROR);
return;
}
$schema = '';
if (strncmp($url, "http://", 7)) {
$schema = 'http';
} elseif (strncmp($url, "https://", 8)) {
$schema = 'https';
}
if (strlen($schema) > 0) {
// TODO: create delim according to $_SERVER['SCRIPT_NAME']
$delim = $url[0] == '/' ? '' : '/';
$http_host = @$_SERVER['HTTP_HOST'];
$server_name = @$_SERVER['SERVER_NAME'];
if (isset($http_host)
&& is_string($http_host)
&& strlen($http_host) > 0) {
$url = "$schema://$http_host$delim$url";
} elseif (isset($server_name)
&& is_string($server_name)
&& strlen($server_name) > 0) {
$url = "$schema://$server_name$delim$url";
}
}
Platon::redirect($url);
} /* }}} */
/**
* Returns original variables HTML code for use in forms or links.
*
* @param mixed $origvars string or array of original variables;
* if string values should be rawurlencoded();
* if array values should not be encoded
* @param string $method type of method ("POST" or "GET")
* @param mixed $default default value of variables
* if null, empty values will be skipped
* @return get HTML code of original variables
*/
static function get_origvars_html($origvars, $method = 'POST', $default = '') /* {{{ */
{
$ret = '';
$method = strtoupper($method);
if ($method == 'POST') {
if (! is_array($origvars)) {
$new_origvars = array();
foreach (explode('&', $origvars) as $param) {
$parts = explode('=', $param, 2);
if (! isset($parts[1])) {
$parts[1] = $default;
}
if (strlen($parts[0]) <= 0) {
continue;
}
$new_origvars[$parts[0]] = $parts[1];
}
$origvars =& $new_origvars;
}
foreach ($origvars as $key => $val) {
if (strlen($val) <= 0 && $default === null) {
continue;
}
$key = rawurldecode($key);
$val = rawurldecode($val);
$ret .= '<input type="hidden" name="';
$ret .= htmlspecialchars($key).'"';
$ret .= ' value="'.htmlspecialchars($val).'"';
$ret .= " />\n";
}
} else if (! strncmp('GET', $method, 3)) {
if (! is_array($origvars)) {
$ret .= $origvars;
} else {
foreach ($origvars as $key => $val) {
if (strlen($val) <= 0 && $default === null) {
continue;
}
$ret == '' || $ret .= '&';
$ret .= htmlspecialchars(rawurlencode($key));
$ret .= '=';
$ret .= htmlspecialchars(rawurlencode($val));
}
}
if ($method[strlen($method) - 1] == '+') {
$ret = "?$ret";
}
} else {
trigger_error('Unsupported Platon::get_origvars_html() method: '
.$method, E_USER_ERROR);
}
return $ret;
} /* }}} */
/**
* Reverse of the standard htmlspecialchars() PHP function.
*
* @param string $str input string
* @return descaped string
* @author Nathan Codding
* @date 24/Aug/2000
*/
static function undo_htmlspecialchars($str) /* {{{ */
{
$str = preg_replace('/>/i', '>', $str);
$str = preg_replace('/</i', '<', $str);
$str = preg_replace('/"/i', '\'', $str);
$str = preg_replace('/&/i', '&', $str);
// do also reverse of Platon::htmlspecialchars2()
$str = preg_replace('/ /i', ' ', $str);
return $str;
} /* }}} */
/**
* Returns pronounceable random password
*
* @param array $array array of sylables or null for default
* @param int $num_letters minimum number of letters
* @param int $max_letters maximum number of letters
* @param int $uppercased if to randomize letter case
* @author Sebastien Cevey <seb@cine7.net>
*/
static function rand_pass /* {{{ */
($array = null, $num_letters = 6, $max_letters = 10, $uppercased = 0)
{
// Pronounceable pieces of words
$array = array(
'ap', 'baz', 'car', 'dus', 'tin', 'rog', 'sti',
'rev', 'pik', 'sty', 'lev', 'qot', 'rel', 'vid',
'kro', 'xo', 'pro', 'wia', 'axi', 'jer', 'foh',
'mu', 'ya', 'zol', 'gu', 'pli', 'cra', 'den',
'bi', 'sat', 'ry', 'qui', 'wip', 'fla', 'gro',
'tav', 'peh', 'gil', 'lot', 'kal', 'zan', 'noc',
'bat', 'tev', 'lun', 'pal', 'hom', 'cun', 'wos', 'vox');
// Randomize on microseconds
mt_srand ((double)microtime() * 1000000);
// Create random pass (too long for the moment)
for($i = 0; $i < $num_letters; $i++) {
$pass .= $array[mt_rand(0, (count($array) - 1))];
}
// Make sure there is not twice the same letter one after the other
for($i = 1; $i < strlen($pass); $i++) {
if(substr($pass, $i, 1) == substr($pass, $i - 1, 1))
$pass = substr($pass, 0, $i) . substr($pass, $i + 1);
}
// Randomize the pass case [for each letter]
if ($uppercased) {
for($i = 0; $i < strlen($pass); $i++) {
if(mt_rand(0, $uppercased) == 0)
$pass = substr($pass,0,$i)
. strtoupper(substr($pass, $i,1))
. substr($pass, $i + 1);
}
}
// Shorten it now
$pass = substr($pass, 0, $num_letters
+ mt_rand(0,$max_letters - $num_letters));
// Return the password
return $pass;
} /* }}} */
/**
* Returns random string of length $len consisting of A-Z and 0-9; first
* character will always be an alphabet; requires srand().
*
* @param int $len length of string
* @return string generated random string
*/
static function rand_str($len = 8) /* {{{ */
{
$s = '';
for ($i = 0; $i < $len; $i++) {
if ($i == 0) {
$r = rand() % 26;
} else {
$r = rand() % 36;
}
if ($r >= 26) {
$s .= chr($r + ord('0') - 26);
} else {
$s.= chr($r + ord('A'));
}
}
return $s;
} /* }}} */
/**
* Appends slash at the end of string if it is not empty and slash is not
* already present at the end of string.
*
* @param string $string string to search
* @param char $char character to append, slash by default
* @return changed string on success, false on failure
*/
static function append_slash($string, $char = '/') /* {{{ */
{
if (! is_string($string) || ! is_string($char)) {
return false;
}
if (strlen($string) > 0) {
if ($string[strlen($string) - 1] != $char[0])
$string .= $char[0];
}
return $string;
} /* }}} */
/**
* Returns appropriate value from array according to key compared with
* passed string or false when no key contains passed string.
*
* @param string $string string to search
* @param array $substr_ar substring arrays
* @return mixed value from $substr_ar or false
*/
static function set_value_by_substr($string, $substr_ar) /* {{{ */
{
if (! is_array($substr_ar)) {
return stristr($substr_ar, $string) != false ? $substr_ar : '';
}
foreach ($substr_ar as $key => $value) {
if ($key == '' || stristr($string, $key) != false)
return $value;
}
return false;
} /* }}} */
/**
* Replaces postfix of string.
*
* @param string $search what to replace
* @param string $replace replacement string
* @param string $subject where perform replacement
* @return string string with replaced postfix
*/
static function str_replace_postfix($search, $replace, $subject) /* {{{ */
{
$idx = strlen($subject) - strlen($search);
if ($idx < 0) {
return $subject;
}
if (! strcmp(substr($subject, $idx), $search)) {
return substr($subject, 0, $idx) . $replace;
}
return $subject;
} /* }}} */
/**
* Replaces prefix of string.
*
* @param string $search what to replace
* @param string $replace replacement string
* @param string $subject where perform replacement
* @return string string with replaced prefix
*/
static function str_replace_prefix($search, $replace, $subject) /* {{{ */
{
if (! strncmp($subject, $search, strlen($search))) {
return $replace . substr($subject, strlen($search));
}
return $subject;
} /* }}} */
/**
* Returns pretty formated substring.
*
* @param string $string string to format
* @param int $length maximum length
* @param int $slop slop
* @param int $use_hellip if use '…'
* @return pretty formatted substring
* @author Frank Schmitt <frank.schmitt@vista.com>
* @date May/2002
*/
static function pretty_substr($string, $length, $slop = 4, $use_hellip = false) /* {{{ */
{
if (strlen($string) > $length) {
$string = substr($string, 0, $length - 1);
$lastSpace = strrpos($string, ' ');
if ($lastSpace > $length - $slop) {
$string = substr($string, 0, $lastSpace);
}
$string .= $use_hellip ? '…' : '...';
}
return $string;
} /* }}} */
# pretty_substr - Oracle PL/SQL -- the same author {{{
# warning: code below contains at least one bug
# set define off; -- makes it so SQL*Plus doesn't choke on the '&'
#
# create or replace
# static function pretty_substr
# (
# str in varchar2,
# len in number,
# slop in number default 3
# )
# return varchar2 is
# result varchar2(4000);
# last_space number;
# begin
# if length(str) > len then
# result := substr(str, 0, len - 1);
#
# last_space := instr(result, ' ', (-1 * slop), 1);
#
# if last_space > 0 then
# result := substr(result, 0, last_space - 1);
# end if;
#
# result := result || '…';
# else
# result := str;
# end if;
#
# return result;
# end pretty_substr;
# }}}
/**
* Insert element into array on specific index.
*
* @param array $arr input array
* @param int $index position in array
* @param mix $element inserted element
* @return array output array
*/
static function array_insert($arr, $index, $element) /* {{{ */
{
if (!is_array($arr)) {
return false;
}
$index = intval($index);
if ($index > count($arr)-1) {
array_push($arr, $element);
return $arr;
}
$before = array_splice($arr, 0, $index);
array_push($before, $element);
return array_merge($before, $arr);
} /* }}} */
/**
* Returns english grammar related number.
*
* @param int $number intput number
* @return string output number
*/
static function get_english_num($number) /* {{{ */
{
$number = intval($number);
switch ($number % 10) {
case 1: $number .= 'st'; break;
case 2: $number .= 'nd'; break;
case 3: $number .= 'rd'; break;
default: $number .= 'th'; break;
}
return $number;
} /* }}} */
private static $_htmlspecialchars_encoding = '';
/**
* Set charset/encoding for out Platon::htmlspecialchars()
*
* @param string $encoding encoding, for more info
* see _deduct_htmlspecialchars_encoding()
* @return boolean always true
*/
static function htmlspecialchars_encoding($encoding) /* {{{ */
{
Platon::$_htmlspecialchars_encoding = $encoding;
return true;
} /* }}} */
/**
* Encode special HTML characters based on encoding and PHP version
*
* @param string $string string to encode
* @param string $encoding encoding to use (use default when empty)
* @return string HTML encoded string
*/
static function htmlspecialchars($string, $encoding = '') /* {{{ */
{
// no default encoding maps to no special transformation
static $map = array('' => '');
if (strlen($encoding) <= 0) {
$encoding = Platon::$_htmlspecialchars_encoding;
}
if (! array_key_exists($encoding, $map)) {
if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 4) {
$map[$encoding]['flags'] = ENT_COMPAT | ENT_HTML401;
$map[$encoding]['encoding'] = Platon::_deduct_htmlspecialchars_encoding($encoding);
} elseif ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6)
|| PHP_MAJOR_VERSION >= 7) {
$map[$encoding]['flags'] = ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED | ENT_SUBSTITUTE;
$map[$encoding]['encoding'] = Platon::_deduct_htmlspecialchars_encoding($encoding);
} else {
$map[$encoding] = ''; // no special htmlspecialchars()
}
}
if (is_array($map[$encoding])) {
return htmlspecialchars($string,
$map[$encoding]['flags'],
$map[$encoding]['encoding']);
}
// default
return htmlspecialchars($string);
} /* }}} */
static function _deduct_htmlspecialchars_encoding($encoding) /* {{{ */
{
// List of supported charsets http://php.net/manual/en/function.htmlspecialchars.php
$allowed = array(
'ISO-8859-1', 'ISO8859-1', // Western European, Latin-1
'ISO-8859-5', 'ISO8859-5', // Little used cyrillic charset (Latin/Cyrillic)
'ISO-8859-15', 'ISO8859-15', // Western European, Latin-9. Adds the Euro sign and others
'UTF-8', // ASCII compatible multi-byte 8-bit Unicode
'cp866', 'ibm866', '866', // DOS-specific Cyrillic charset
'cp1251', 'Windows-1251', 'win-1251', '1251', // Windows-specific Cyrillic charset
'cp1252', 'Windows-1252', '1252', // Windows specific charset for Western European
'KOI8-R', 'koi8-ru', 'koi8r', // Russian
'BIG5', '950', // Traditional Chinese, mainly used in Taiwan
'GB2312', '936', // Simplified Chinese, national standard character set
'BIG5-HKSCS', // Big5 with Hong Kong extensions, Traditional Chinese
'Shift_JIS', 'SJIS', 'SJIS-win', 'cp932', '932', // Japanese
'EUC-JP', 'EUCJP', 'eucJP-win', // Japanese
'MacRoman', // Charset that was used by Mac OS.
'' // An empty string activates detection from script encoding (Zend multibyte),
// default_charset and current locale (see nl_langinfo() and setlocale()), in this order. Not recommended.
);
if (in_array($encoding, $allowed)) {
return $encoding;
}
$encoding_upper = strtoupper($encoding);
foreach ($allowed as $allow) {
if (strtoupper($allow) == $encoding_upper) {
return $allow;
}
}
for ($len = strlen($encoding) - 1; $len > 0; $len--) {
$encoding_prefix = substr($encoding_upper, 0, $len);
foreach ($allowed as $allow) {
if (strtoupper(substr($allow, 0, min($len, strlen($allow)))) == $encoding_prefix) {
return $allow;
}
}
}
return null;
} /* }}} */
/**
* HTML special characters substitution with replacing space for ' '.
*
* @param string $str string to escape
* @return string HTML escaped string with spaces substitued
*/
static function htmlspecialchars2($str) /* {{{ */
{
return str_replace(' ', ' ', Platon::htmlspecialchars($str));
} /* }}} */
/*
* Replaces tilde with non-breaking space
*
* @param string $str input string
* @return string replaced string
*/
static function tilde_replace($str) /* {{{ */
{
$str = str_replace('/~', '/<TILDE>', $str);
$str = str_replace('~', ' ', $str);
$str = preg_replace('|<TILD[AE]?'.'>|i', '~', $str);
return $str;
} /* }}} */
/**
* Computes MD5sum of file like `md5sum' command does it.
*
* @param string $file filename
* @return string MD5sum of file or false if file not found
*/
static function md5sum($file) /* {{{ */
{
if (($fhandle = @fopen($file, 'r')) === false) {
return false;
}
$data = '';
while (($tmp_data = @fread($fhandle, 1024)) !== '') {
$data .= $tmp_data;
}
@fclose($fhandle);
return md5($data);
} /* }}} */
/**
* Escapes e-mail address.
*
* @param string $email e-mail address
* @param string $mode plain - no escaping
* url - does URL escaping
* html - does HTML escaping
* url_and_html - does URL & HTML escaping
* mailto - prepends "mailto:" and escapes
* hypertext_link - creates hypertext link
* javascript - using JS for escaping
* (JS method was inpired by Wouter Brok -- http://www.stack.nl/~wjmb)
* @param string $attr when creating hypertext link, additional
* attributes may be added
* @return string escaped e-mail added
*/
static function escape_email($email, $mode = 'hypertext_link', $attr = '')/* {{{ */
{
$ret = '';
switch ($mode) {
case 'plain':
$ret = $email;
break;
case 'url_and_html':
case 'url_html':
case 'url':
// escape every character into hex
for ($x = 0; $x < strlen($email); $x++) {
if ($email[$x] == '@') {
$ret .= '@'; // Opera browser hack
} else {
$ret .= '%' . bin2hex($email[$x]);
}
}
if ($mode == 'url') {
break;
}
$email = $ret;
$ret = '';
// ... and continue with HTML escaping
case 'html':
for ($x = 0; $x < strlen($email); $x++) {
$ret .= (ord($email[$x]) > 127
? $email[$x] : '&#x'.bin2hex($email[$x]).';');
}
break;
case 'mailto':
$ret = 'mailto:';// mailto:
$ret .= Platon::escape_email($email, 'url_and_html');
break;
case 'js':
case 'javascript':
$no_js_dot_subst = '<!-- jane@example.org -->·<!-- alice@example.com -->';
$no_js_at_subst = '<!-- peter@example.com -->@<!-- andrew@example.org -->';
$no_js_email = Platon::escape_email($email, 'html');
$no_js_email = str_replace('.', $no_js_dot_subst, $no_js_email);
$no_js_email = str_replace('@', $no_js_at_subst, $no_js_email);
$js_email = str_replace('@', '(', str_replace('.', ')', $email));
$js_email = htmlspecialchars($js_email);
$ret .= '<script language="JavaScript"><!--'."\n";
$ret .= ' var e = String("'.$js_email.'").replace(/\(/g,"@").replace(/\)/g,"."); '."\n";
$ret .= ' document.write(\'<a href="mailto:\'+e+\'">\'+e+\'</a>\');'."\n";
$ret .= '// --></script>'."\n";
$ret .= '<noscript>'.$no_js_email.'</noscript>';
break;
default:
case 'hypertext_link':
is_array($attr) && $attr = join(' ', $attr);
$attr != '' && $attr .= ' ';
$ret = sprintf('<a %shref="%s">%s</a>', $attr,
Platon::escape_email($email, 'mailto'),
Platon::escape_email($email, 'html'));
break;
}
return $ret;
} /* }}} */
/**
* Removes parameter with value from the query string
*
* @param string $query_string query string
* @param string $param parameter name
* @param char $sep separator (default: &)
* @return string modified query string
*/
static function query_string_remove_param($query_string, $param, $sep = '&') /* {{{ */
{
$regexp = $sep.$param.'=[^'.$sep.']*';
$array = preg_split("/$regexp/", $sep.$query_string);
$string = join('', $array);
$string = preg_replace('/^&*/', '',$string);
return $string;
} /* }}} */
/**
* Returns passed path without scriptname; method also accepts array
* returned from Platon::glue_url() method.
*
* @param mixed $url string URL or array from Platon::glue_url()
* @return string path without scriptname
*/
static function get_path_without_scriptname($url) /* {{{ */
{
$path = is_array($url) ? $url['path'] : $url;
$path = preg_replace('/http[s]?:\/\/[^\/]+/', '', $path);
$path = preg_replace('/\?.*/', '', $path);
$path = preg_replace('/[^\/]+\z/', '', $path);
return $path;
} /* }}} */
/**
* Creates URL string from components; components are array as it is
* returned from glue_url() function.
*
* @param array $url components array
* @return string glued url
* @author Tomas V.V.Cox <cox@idecnet.com>
* @date 19/Feb/2001
*/
static function glue_url($url) /* {{{ */
{
if (! is_array($url))
return false;
// scheme
$uri = empty($url['scheme']) ? '' : $url['scheme'] . '://';
// user and pass
if (! empty($url['user'])) {
$uri .= $url['user'].':'.$url['pass'].'@';
}
// host
$uri .= $url['host'];
// port
$port = empty($url['port']) ? '' : ':'.$url['port'];
$uri .= $port;
// path
$uri .= $url['path'];
// fragment or query
if (isset($url['fragment'])) {
$uri .= '#' . $url['fragment'];
}
elseif (isset($url['query'])) {
$uri .= '?' . $url['query'];
}
return $uri;
} /* }}} */
/**
* Parses Accept-Language HTTP header.
*
* @param string $accept_lang special Accept-Language header (if not
* present, it will be extracted from env)
* @param string $strict strict parsing (it means that in example
* "en-us" does not result into "en")
* @return string array of accepted languages according to Q
*/
static function parse_HTTP_accept_language($accept_lang = null, $strict = 0) /* {{{ */
{
$accept_lang == null && $accept_lang = (string) @$_SERVER['HTTP_ACCEPT_LANGUAGE'];
$accept_lang = strtolower($accept_lang);
$accept_lang = str_replace(array("'", '"'), '', $accept_lang);
$accepted = preg_split('/,[[:space:]]*/', $accept_lang);
$candidates = array();
for ($i = 0; $i < count($accepted); $i++) {
if (preg_match('/^([a-z0-9_-]+);[[:space:]]*q=([0-9\.]+)/i', $accepted[$i], $arr)) {
$q = (double)$arr[2];
$l = $arr[1];
} else {
$q = 42.0;
$l = $accepted[$i];
}
$l = trim($l);
if (strlen($l) <= 0) {
continue;
}
$candidates[$l] = $q;
if (! $strict && strpos($l, '-') !== false) {
$l = explode('-', $l, 2);
$l = $l[0];
isset($candidates[$l]) || $candidates[$l] = $q - 0.01;
}
}
arsort($candidates);
return array_keys($candidates);
} /* }}} */
/**
* Returns top level domain name.
*
* @param string $remote_host special remote hostname (if not present,
* it will extracted from environment)
* @return string top level domain name
*/
static function get_top_level_domain($remote_host = null) /* {{{ */
{
$remote_host == null && $remote_host = @$_SERVER['REMOTE_HOST'];
if (empty($remote_host)) {
$remote_host = @gethostbyaddr(@$_SERVER['REMOTE_ADDR']);
}
if (!empty($remote_host) && preg_match('|\.([^\.]+)$|', $remote_host, $matches)) {
$lang = strtolower($matches[1]);
return $lang;
}
return false;
} /* }}} */
/*
* Negotiate client's language.
*
* @param array $l_core_ar array of possible languages
* @param string $accept_lang special Accept-Language header;
* see Platon::parse_HTTP_accept_language()
* @param string $remote_host special remote hostname
* see Platon::get_top_level_domain()
* @return string negotiated language ($accepted array member)
*/
static function negotiate_language($l_core_ar, $accept_lang = null, $remote_host = null) /* {{{ */
{
// Sanity check
if (count($l_core_ar) < 2) {
if (count($l_core_ar) == 1) {
return $l_core_ar[0];
}
return false;
}
// Groups of similar languages. Every language can be only in one group.
// This array needs to be little bit updated in future.
static $lang_groups = array(
array('sk', 'cz', 'cs'),
array('en', 'gb', 'us', 'au')
);
$l_user_ar = Platon::parse_HTTP_accept_language($accept_lang);
$l_tld = Platon::get_top_level_domain($remote_host);
$l_tld != false && $l_user_ar += array($l_tld);
for ($i = 0; $i < count($l_user_ar); $i++) {
$lang = $l_user_ar[$i];
if (in_array($lang, $l_core_ar)) {
return $lang;
}
for ($j = 0; $j < count($lang_groups); $j++) {
if (! in_array($lang, $lang_groups[$j])) {
continue;
}
for ($k = 0; $k < count($lang_groups[$j]); $k++) {
if (in_array($lang_groups[$j][$k], $l_core_ar)) {
return $lang_groups[$j][$k];
}
}
break;
}
}
return false;
} /* }}} */
}
/* vim: set expandtab tabstop=4 shiftwidth=4:
* vim600: fdm=marker fdl=0 fdc=0
*/
?>
Platon Group <platon@platon.sk> http://platon.sk/
|