* * @author Ondrej Jombik * @package Platon * @version 1.0 * @access public */ /* $Platon: phpPlatonLib/Platon/Platon.php,v 1.33 2005/11/07 23:21:17 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 */ 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 */ 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 */ 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 '../') */ 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 */ 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 */ function redirect($where, $temporary = false) /* {{{ */ { $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) { header('HTTP/1.1 301 Moved Permanently'); } 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 */ 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 */ function redirect_test($file, $url) /* {{{ */ { if (! isset($_SERVER['PHP_SELF']) || ! eregi($file, $_SERVER['PHP_SELF'])) { 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"; } } header("Location: $url"); exit; } /* }}} */ /** * 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 */ 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 .= ' $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 */ function undo_htmlspecialchars($str) /* {{{ */ { $str = preg_replace('/>/i', '>', $str); $str = preg_replace('/</i', '<', $str); $str = preg_replace('/"/i', '\'', $str); $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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 * @date May/2002 */ 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 # 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; # }}} /** * Returns english grammar related number. * * @param int $number intput number * @return string output number */ 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; } /* }}} */ /** * HTML special characters substitution with replacing space for ' '. * * @param string $str string to escape * @return string HTML escaped string with spaces substitued */ function htmlspecialchars2($str) /* {{{ */ { return str_replace(' ', ' ', htmlspecialchars($str)); } /* }}} */ /* * Replaces tilde with non-breaking space * * @param string $str input string * @return string replaced string */ function tilde_replace($str) /* {{{ */ { $str = str_replace('/~', '/', $str); $str = str_replace('~', ' ', $str); $str = preg_replace('||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 */ 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 */ 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++) { $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 = '·'; $no_js_at_subst = '@'; $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 .= ''."\n"; $ret .= ''; break; default: case 'hypertext_link': is_array($attr) && $attr = join(' ', $attr); $attr != '' && $attr .= ' '; $ret = sprintf('%s', $attr, Platon::escape_email($email, 'mailto'), Platon::escape_email($email, 'html')); break; } return $ret; } /* }}} */ /** * 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 */ 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 * @date 19/Feb/2001 */ 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 */ 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 = split(',[[:space:]]*', $accept_lang); $candidates = array(); for ($i = 0; $i < count($accepted); $i++) { if (eregi('^([a-z0-9_-]+);[[:space:]]*q=([0-9\.]+)', $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 */ 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) */ 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 */ ?>