Files
EasySoft-ZenTaoPMS/framework/helper.class.php
2016-03-08 11:32:48 +08:00

1307 lines
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* ZenTaoPHP的helper类。
* The helper class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
/**
* 该类实现了一些常用的方法
* The helper class, contains the tool functions.
*
* @package framework
*/
class helper
{
/**
* 设置一个对象的成员变量
* Set the member's value of one object.
* <code>
* <?php
* $lang->db->user = 'wwccss';
* helper::setMember('lang', 'db.user', 'chunsheng.wang');
* ?>
* </code>
* @param string $objName the var name of the object.
* @param string $key the key of the member, can be parent.child.
* @param mixed $value the value to be set.
* @static
* @access public
* @return bool
*/
static public function setMember($objName, $key, $value)
{
global $$objName;
if(!is_object($$objName) or empty($key)) return false;
$key = str_replace('.', '->', $key);
$value = serialize($value);
$code = ("\$${objName}->{$key}=unserialize(<<<EOT\n$value\nEOT\n);");
eval($code);
return true;
}
/**
* 创建一个模块方法的链接
* control类的createLink实际上调用的是这个方法
*
* Create a link to a module's method.
* This method also mapped in control class to call conveniently.
*
* <code>
* <?php
* helper::createLink('hello', 'index', 'var1=value1&var2=value2');
* helper::createLink('hello', 'index', array('var1' => 'value1', 'var2' => 'value2');
* ?>
* </code>
* @param string $moduleName module name
* @param string $methodName method name
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2
* @param string $viewType the view type
* @param bool $onlybody whether onlybody
* @static
* @access public
* @return string the link string.
*/
static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlybody = false)
{
global $app, $config;
$appName = $app->getAppName();
$appName = empty($appName) ? '' : $appName . '/';
if(strpos($moduleName, '.') !== false) list($appName, $moduleName) = explode('.', $moduleName);
$link = $config->requestType == 'PATH_INFO' ? $config->webRoot . $appName : $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']);
if($config->requestType == 'PATH_INFO2') $link .= '/';
/* 设置视图类型和变量。 */
/* Set the view type and vars. */
if(empty($viewType)) $viewType = $app->getViewType();
if(!is_array($vars)) parse_str($vars, $vars);
/* PATH_INFO方式。 */
/* The PATH_INFO and PATH_INFO2 type. */
if($config->requestType != 'GET')
{
/* 如果方法名与默认方法相等,并且参数是空的,转换为友好的链接地址。 */
/* If the method equal the default method defined in the config file and the vars is empty, convert the link. */
if($methodName == $config->default->method and empty($vars))
{
/* 如果模块名与默认模块名相等转换为index.html。*/
/* If the module also equal the default module, change index-index to index.html. */
if($moduleName == $config->default->module)
{
$link .= 'index.' . $viewType;
}
elseif($viewType == $app->getViewType())
{
$link .= $moduleName . '/';
}
else
{
$link .= $moduleName . '.' . $viewType;
}
}
else
{
$link .= "$moduleName{$config->requestFix}$methodName";
foreach($vars as $value) $link .= "{$config->requestFix}$value";
$link .= '.' . $viewType;
}
}
else
{
$link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName";
if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType;
foreach($vars as $key => $value) $link .= "&$key=$value";
}
/* if page has onlybody param then add this param in all link. the param hide header and footer. */
if($onlybody or isonlybody())
{
$onlybody = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes";
$link .= $onlybody;
}
return $link;
}
/**
* 引用一个文件替换内置的include及require方法
* Import a file instend of include or require.
*
* @param string $file the file to be imported.
* @static
* @access public
* @return bool
*/
static public function import($file)
{
if(!is_file($file)) return false;
static $includedFiles = array();
if(!isset($includedFiles[$file]))
{
include $file;
$includedFiles[$file] = true;
return true;
}
return true;
}
/**
* 设置一个模块的model文件如果存在model扩展一起合并
* Set the model file of one module. If there's an extension file, merge it with the main model file.
*
* @param string $moduleName the module name
* @param string $appName the app name
* @static
* @access public
* @return string the model file
*/
static public function setModelFile($moduleName, $appName = '')
{
global $app;
if($appName == '') $appName = $app->getAppName();
/* 设置主model文件扩展文件和路径。 */
/* Set the main model file, extension path and files. */
$mainModelFile = $app->getModulePath($appName, $moduleName) . 'model.php';
$modelExtPaths = $app->getModuleExtPath($appName, $moduleName, 'model');
$hookFiles = array();
$extFiles = array();
foreach($modelExtPaths as $modelExtPath)
{
if(empty($modelExtPath)) continue;
$hookFiles = array_merge($hookFiles, helper::ls($modelExtPath . 'hook/', '.php'));
$extFiles = array_merge($extFiles, helper::ls($modelExtPath, '.php'));
}
/* Get ext's app name from realname. */
if($appName) $extAppName = basename(dirname(dirname(dirname($modelExtPath))));
/* 如果没有扩展文件,返回主文件目录。 */
/* If no extension file, return the main file directly. */
if(empty($extFiles) and empty($hookFiles)) return $mainModelFile;
/* 通过对比合并后的缓存文件和扩展文件的修改时间,确定是否要重新生成缓存 */
/* Else, judge whether needed update or not .*/
$extModelPrefix = empty($app->siteCode) ? '' : $app->siteCode{0} . DS . $app->siteCode;
$mergedModelDir = $app->getTmpRoot() . 'model' . DS . $extModelPrefix . DS;
$mergedModelFile = $mergedModelDir . (empty($app->siteCode) ? '' : $app->siteCode . '.') . $moduleName . '.php';
$needUpdate = false;
$lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0;
if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true);
while(!$needUpdate)
{
foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) break 2;
foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) break 2;
$modelExtPath = $modelExtPaths['common'];
$modelHookPath = $modelExtPaths['common'] . 'hook/';
if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) break;
if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) break;
if($modelExtPaths['site'])
{
$modelExtPath = $modelExtPaths['site'];
$modelHookPath = $modelExtPaths['site'] . 'hook/';
if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) break;
if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) break;
}
if(filemtime($mainModelFile) > $lastTime) break;
return $mergedModelFile;
}
/* If loaded zend opcache module, turn off cache when create tmp model file to avoid the conflics. */
if(extension_loaded('Zend OPcache')) ini_set('opcache.enable', 0);
/* Update the cache file. */
$modelClass = $moduleName . 'Model';
$extModelClass = 'ext' . $modelClass;
$extTmpModelClass = 'tmpExt' . $modelClass;
$modelLines = "<?php\n";
$modelLines .= "helper::import('$mainModelFile');\n";
$modelLines .= "class $extTmpModelClass extends $modelClass \n{\n";
/* Cycle all the extension files. */
foreach($extFiles as $extFile)
{
$extLines = self::removeTagsOfPHP($extFile);
$modelLines .= $extLines . "\n";
}
/* Create the merged model file and import it. */
$replaceMark = '//**//'; // This mark is for replacing code using.
$modelLines .= "$replaceMark\n}";
/* Unset conflic function for model. */
preg_match_all('/.* function\s+(\w+)\s*\(.*\)[^\{]*\{/Ui', $modelLines, $functions);
$functions = $functions[1];
$conflics = array_count_values($functions);
foreach($conflics as $functionName => $count)
{
if($count <= 1) unset($conflics[$functionName]);
}
if($conflics)
{
$modelLines = explode("\n", $modelLines);
$startDel = false;
foreach($modelLines as $line => $code)
{
if($startDel and preg_match('/.* function\s+(\w+)\s*\(.*\)/Ui', $code)) $startDel = false;
if($startDel)
{
unset($modelLines[$line]);
}
else
{
foreach($conflics as $functionName => $count)
{
if($count <= 1) continue;
if(preg_match('/.* function\s+' . $functionName . '\s*\(.*\)/Ui', $code))
{
$conflics[$functionName] = $count - 1;
$startDel = true;
unset($modelLines[$line]);
}
}
}
}
$modelLines = join("\n", $modelLines);
}
$tmpMergedModelFile = $mergedModelDir . 'tmp.' . (empty($app->siteCode) ? '' : $app->siteCode . '.') . $moduleName . '.php';
if(!@file_put_contents($tmpMergedModelFile, $modelLines))
{
die("ERROR: $tmpMergedModelFile not writable, please make sure the " . dirname($tmpMergedModelFile) . ' directory exists and writable');
}
if(!class_exists($extTmpModelClass)) include $tmpMergedModelFile;
/* Get hook codes need to merge. */
$hookCodes = array();
foreach($hookFiles as $hookFile)
{
$fileName = baseName($hookFile);
list($method) = explode('.', $fileName);
$hookCodes[$method][] = self::removeTagsOfPHP($hookFile);
}
/* Cycle the hook methods and merge hook codes. */
$hookedMethods = array_keys($hookCodes);
$mainModelCodes = file($mainModelFile);
$mergedModelCodes = file($tmpMergedModelFile);
foreach($hookedMethods as $method)
{
/* Reflection the hooked method to get it's defined position. */
$methodRelfection = new reflectionMethod($extTmpModelClass, $method);
$definedFile = $methodRelfection->getFileName();
$startLine = $methodRelfection->getStartLine() . ' ';
$endLine = $methodRelfection->getEndLine() . ' ';
/* Merge hook codes. */
$oldCodes = $definedFile == $tmpMergedModelFile ? $mergedModelCodes : $mainModelCodes;
$oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1));
$openBrace = strpos($oldCodes, '{');
$newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1);
/* Replace it. */
if($definedFile == $tmpMergedModelFile)
{
$modelLines = str_replace($oldCodes, $newCodes, $modelLines);
}
else
{
$modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines);
}
}
unlink($tmpMergedModelFile);
/* Save it. */
$modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines);
file_put_contents($mergedModelFile, $modelLines);
return $mergedModelFile;
}
/**
* Remove tags of PHP
*
* @param string $fileName
* @static
* @access public
* @return string
*/
static public function removeTagsOfPHP($fileName)
{
$code = trim(file_get_contents($fileName));
if(strpos($code, '<?php') === 0) $code = ltrim($code, '<?php');
if(strrpos($code, '?>') !== false) $code = rtrim($code, '?>');
return trim($code);
}
/**
* 将数组转化成 IN( 'a', 'b') 的形式,用于数据库字符串拼接
* Create the in('a', 'b') string.
*
* @param string|array $ids the id lists, can be a array or a string with ids joined with comma.
* @static
* @access public
* @return string the string like IN('a', 'b').
*/
static public function dbIN($ids)
{
if(is_array($ids))
{
if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc())
{
foreach ($ids as $key=>$value) $ids[$key] = addslashes($value);
}
return "IN ('" . join("','", $ids) . "')";
}
if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) $ids = addslashes($ids);
return "IN ('" . str_replace(',', "','", str_replace(' ', '', $ids)) . "')";
}
/**
* base64编码框架对'/'字符比较敏感,转换为'.'
* Create safe base64 encoded string for the framework.
*
* @param string $string the string to encode.
* @static
* @access public
* @return string encoded string.
*/
static public function safe64Encode($string)
{
return strtr(base64_encode($string), '/', '.');
}
/**
* 解码base64先将之前的'.' 转换回'/'
* Decode the string encoded by safe64Encode.
*
* @param string $string the string to decode
* @static
* @access public
* @return string decoded string.
*/
static public function safe64Decode($string)
{
return base64_decode(strtr($string, '.', '/'));
}
/**
* Json encode and addslashe if magic_quotes_gpc is on.
*
* @param mixed $data the object to encode
* @static
* @access public
* @return string decoded string.
*/
static public function jsonEncode($data)
{
return (version_compare(phpversion(), '5.4', '<') and function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc()) ? addslashes(json_encode($data)) : json_encode($data);
}
/**
* 判断是否是utf8编码
* Judge a string is utf-8 or not.
*
* @param string $string
* @author hmdker@gmail.com
* @see http://php.net/manual/en/function.mb-detect-encoding.php
* @static
* @access public
* @return bool
*/
static public function isUTF8($string)
{
$c = 0;
$b = 0;
$bits = 0;
$len = strlen($string);
for($i=0; $i<$len; $i++)
{
$c = ord($string[$i]);
if($c > 128)
{
if(($c >= 254)) return false;
elseif($c >= 252) $bits=6;
elseif($c >= 248) $bits=5;
elseif($c >= 240) $bits=4;
elseif($c >= 224) $bits=3;
elseif($c >= 192) $bits=2;
else return false;
if(($i+$bits) > $len) return false;
while($bits > 1)
{
$i++;
$b=ord($string[$i]);
if($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}
/**
* 计算两个日期相差的天数,取整
* Compute the diff days of two date.
*
* @param string $date1 the first date.
* @param string $date2 the sencode date.
* @access public
* @return int the diff of the two days.
*/
static public function diffDate($date1, $date2)
{
return round((strtotime($date1) - strtotime($date2)) / 86400, 0);
}
/**
* 获取当前时间使用common语言文件定义的DT_DATETIME1常量
* Get now time use the DT_DATETIME1 constant defined in the lang file.
*
* @access public
* @return datetime now
*/
static public function now()
{
return date(DT_DATETIME1);
}
/**
* 获取当前日期使用common语言文件定义的DT_DATE1常量
* Get today according to the DT_DATE1 constant defined in the lang file.
*
* @access public
* @return date today
*/
static public function today()
{
return date(DT_DATE1);
}
/**
* 获取当前日期使用common语言文件定义的DT_DATE1常量
* Get now time use the DT_TIME1 constant defined in the lang file.
*
* @access public
* @return date today
*/
static public function time()
{
return date(DT_TIME1);
}
/**
* 判断日期是不是零
* Judge a date is zero or not.
*
* @access public
* @return bool
*/
static public function isZeroDate($date)
{
return substr($date, 0, 4) == '0000';
}
/**
* 列出目录中符合该正则表达式的文件
* Get files match the pattern under one directory.
*
* @access public
* @return array the files match the pattern
*/
static public function ls($dir, $pattern = '')
{
if(empty($dir)) return array();
$files = array();
$dir = realpath($dir);
if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern);
return empty($files) ? array() : $files;
}
/**
* 切换目录
* Change directory.
*
* @param string $path
* @static
* @access public
* @return void
*/
static function cd($path = '')
{
static $cwd = '';
if($path) $cwd = getcwd();
!empty($path) ? chdir($path) : chdir($cwd);
}
/**
* 去掉UTF8 Bom头
* Remove UTF8 Bom
*
* @param string $string
* @access public
* @return string
*/
public static function removeUTF8Bom($string)
{
if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3);
return $string;
}
/**
* 通过域名获取站点代号。
* Get siteCode from domain.
* @param string $domain
* @return string $siteCode
**/
public static function getSiteCode($domain)
{
global $config;
if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':')); // Remove port from domain.
$domain = strtolower($domain);
if(isset($config->siteCode[$domain])) return $config->siteCode[$domain];
if($domain == 'localhost') return $domain;
if(!preg_match('/^([a-z0-9\-_]+\.)+[a-z0-9\-]+$/', $domain)) die('domain denied');
$domain = str_replace('-', '_', $domain); // Replace '-' by '_'.
$items = explode('.', $domain);
$postfix = str_replace($items[0] . '.', '', $domain);
if(isset($config->chanzhi->node->domain) and $postfix == $config->chanzhi->node->domain) return $items[0];
if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0];
$postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain);
if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[1];
return null;
}
/**
* 增强substr方法支持多字节语言比如中文。
* Enhanced substr version: support multibyte languages like Chinese.
*
* @param string $string
* @param int $length
* @param string $append
* @return string
**/
public static function substr($string, $length, $append = '')
{
if (strlen($string) <= $length ) $append = '';
if(function_exists('mb_substr')) return mb_substr($string, 0, $length, 'utf-8') . $append;
preg_match_all("/./su", $string, $data);
return join("", array_slice($data[0], 0, $length)) . $append;
}
/**
* 检查是否是SEO模式
* Check in seo mode or not.
*
* return bool
*/
public static function inSeoMode()
{
global $config;
return (!empty($config->seoMode) and ($config->requestType != 'GET'));
}
/**
* 检查是否是AJAX请求
* Check is ajax request.
*
* @static
* @access public
* @return bool
*/
public static function isAjaxRequest()
{
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
}
/**
* 301跳转
* Header 301 Moved Permanently.
*
* @param string $locate
* @access public
* @return void
*/
public static function header301($locate)
{
header('HTTP/1.1 301 Moved Permanently');
die(header('Location:' . $locate));
}
/**
* 获取浏览器类型。
* Get browser.
*
* @access public
* @return string
*/
public static function getBrowser()
{
if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow';
$agent = $_SERVER["HTTP_USER_AGENT"];
if(strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0'))
{
return "ie";
}
else if(strpos($agent, 'Firefox') !== false)
{
return "firefox";
}
else if(strpos($agent, 'Chrome') !== false)
{
return "chrome";
}
else if(strpos($agent, 'Opera') !== false)
{
return 'opera';
}
else if((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false)
{
return 'safari';
}
else
{
return 'unknown';
}
}
/**
* 获取浏览器版本
* Get browser version.
*
* @access public
* @return string
*/
public static function getBrowserVersion()
{
if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow';
$agent = $_SERVER['HTTP_USER_AGENT'];
if(preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs))
{
return $regs[1];
}
else if(preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs))
{
return $regs[1];
}
else if(preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs))
{
return $regs[1];
}
else if(preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs))
{
return $regs[1];
}
else if((strpos($agent,'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs))
{
return $regs[1];
}
else if(preg_match('/rv:(\d+)\..*/i', $agent, $regs))
{
return $regs[1];
}
else
{
return 'unknow';
}
}
/**
* 获取客户端操作系统
* Get client os from agent info.
*
* @static
* @access public
* @return string
*/
public static function getOS()
{
if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow';
$osList = array(
'/windows nt 10/i' => 'Windows 10',
'/windows nt 6.3/i' => 'Windows 8.1',
'/windows nt 6.2/i' => 'Windows 8',
'/windows nt 6.1/i' => 'Windows 7',
'/windows nt 6.0/i' => 'Windows Vista',
'/windows nt 5.2/i' => 'Windows Server 2003/XP x64',
'/windows nt 5.1/i' => 'Windows XP',
'/windows xp/i' => 'Windows XP',
'/windows nt 5.0/i' => 'Windows 2000',
'/windows me/i' => 'Windows ME',
'/win98/i' => 'Windows 98',
'/win95/i' => 'Windows 95',
'/win16/i' => 'Windows 3.11',
'/macintosh|mac os x/i' => 'Mac OS X',
'/mac_powerpc/i' => 'Mac OS 9',
'/linux/i' => 'Linux',
'/ubuntu/i' => 'Ubuntu',
'/iphone/i' => 'iPhone',
'/ipod/i' => 'iPod',
'/ipad/i' => 'iPad',
'/android/i' => 'Android',
'/blackberry/i' => 'BlackBerry',
'/webos/i' => 'Mobile'
);
foreach ($osList as $regex => $value)
{
if(preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) return $value;
}
return 'unknown';
}
/**
* 设置$viewTypehtml还是mhtml或其他。
* Set viewType.
*
* @static
* @access public
* @return void
*/
public static function setViewType()
{
global $config, $app;
if($config->requestType != 'GET')
{
$pathInfo = $app->getPathInfo();
if(!empty($pathInfo))
{
$dotPos = strrpos($pathInfo, '.');
if($dotPos)
{
$viewType = substr($pathInfo, $dotPos + 1);
}
else
{
$config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view;
}
}
}
elseif($config->requestType == 'GET')
{
if(isset($_GET[$config->viewVar]))
{
$viewType = $_GET[$config->viewVar];
}
else
{
/* Set default view when url has not module name. such as only domain. */
$config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view;
}
}
if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view;
$app->viewType = isset($viewType) ? $viewType : $config->default->view;
}
/**
* 数据配置合并到主配置
* Merge config items in database and config files.
*
* @param array $dbConfig
* @param string $moduleName
* @static
* @access public
* @return void
*/
public static function mergeConfig($dbConfig, $moduleName = 'common')
{
global $config;
$config2Merge = $config;
if($moduleName != 'common') $config2Merge = $config->$moduleName;
foreach($dbConfig as $item)
{
foreach($item as $record)
{
if(!is_object($record))
{
if($item->section and !isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass();
$configItem = $item->section ? $config2Merge->{$item->section} : $config2Merge;
if($item->key) $configItem->{$item->key} = $item->value;
break;
}
if($record->section and !isset($config2Merge->{$record->section})) $config2Merge->{$record->section} = new stdclass();
$configItem = $record->section ? $config2Merge->{$record->section} : $config2Merge;
if($record->key) $configItem->{$record->key} = $record->value;
}
}
}
/**
* 将字符串中的字符统一到标准字符。
* Unify string to standard chars.
*
* @param string $string
* @param string $to
* @static
* @access public
* @return string
*/
public static function unify($string, $to = ',')
{
$labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', '', '。');
$string = str_replace($labels, $to, $string);
return preg_replace("/[{$to}]+/", $to, trim($string, $to));
}
/**
* 获取远程IP。
* Get remote ip.
*
* @access public
* @return string
*/
public static function getRemoteIp()
{
$ip = '';
if(!empty($_SERVER['HTTP_CLIENT_IP']))
{
$ip = $_SERVER['HTTP_CLIENT_IP'];
}
else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else if(!empty($_SERVER["REMOTE_ADDR"]))
{
$ip = $_SERVER["REMOTE_ADDR"];
}
return $ip;
}
/**
* 检查IP是否在给定的IP范围内。
* check ip is in network.
*
* @param string $ip
* @param string $network
* @access public
* @return void
*/
public static function checkIpScope($ip, $network)
{
if(strpos($network, '/') === false) return $ip == $network;
$ip = (double) (sprintf("%u", ip2long($ip)));
$s = explode('/', $network);
$networkStart = (double) (sprintf("%u", ip2long($s[0])));
$networkLen = pow(2, 32 - $s[1]);
$networkEnd = $networkStart + $networkLen - 1;
if ($ip >= $networkStart && $ip <= $networkEnd)
{
return true;
}
return false;
}
/**
* 检查IP是否合法。
* Check ip avaliable.
*
* @param string $ip
* @access public
* @return bool
*/
public static function checkIP($ip)
{
$ip = trim($ip);
if(strpos($ip, '/') !== false)
{
$s = explode('/', $ip);
preg_match('/^(((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3})$/', $s[0], $matches);
if(!empty($matches) and $s[1] > 0 and $s[1] < 36) return true;
}
else
{
preg_match('/^(((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3})$/', $ip, $matches);
if(!empty($matches)) return true;
}
return false;
}
/**
* 创建随机的字符串。
* Create random string.
*
* @param int $length
* @param string $skip A-Z|a-z|0-9
* @static
* @access public
* @return void
*/
public static function createRandomStr($length, $skip = '')
{
$str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$skip = str_replace('A-Z', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', $skip);
$skip = str_replace('a-z', 'abcdefghijklmnopqrstuvwxyz', $skip);
$skip = str_replace('0-9', '0123456789', $skip);
for($i = 0; $i < strlen($skip); $i++)
{
$str = str_replace($skip[$i], '', $str);
}
$strlen = strlen($str);
while($length > strlen($str)) $str .= $str;
$str = str_shuffle($str);
return substr($str,0,$length);
}
/**
* 获取设备类型。
* Get device.
*
* @access public
* @return void
*/
public static function getDevice()
{
global $app, $config;
$viewType = $app->getViewType();
if($viewType == 'mhtml') return 'mobile';
if(isset($_COOKIE['visualDevice'])) return $_COOKIE['visualDevice'];
/* Detect mobile. */
$mobile = $app->loadClass('mobile');
if($mobile->isMobile())
{
if(!isset($config->template->mobile)) return 'desktop';
if(isset($config->site->mobileTemplate) and $config->site->mobileTemplate == 'close') return 'desktop';
return 'mobile';
}
return 'desktop';
}
}
/**
* helper::createLink()的别名,方便创建本模块的链接
* The short alias of helper::createLink() method.
*
* @param string $methodName the method name
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2)
* @param string $viewType
* @return string the link string.
*/
function inLink($methodName = 'index', $vars = '', $viewType = '')
{
global $app;
return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType);
}
/**
* 通过一个静态游标,可以遍历数组
* Static cycle a array
*
* @param array $items the array to be cycled.
* @return mixed
*/
function cycle($items)
{
static $i = 0;
if(!is_array($items)) $items = explode(',', $items);
if(!isset($items[$i])) $i = 0;
return $items[$i++];
}
/**
* 获取当前时间的Unix时间戳精确到微妙
* Get current microtime.
*
* @access protected
* @return float current time.
*/
function getTime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
/**
* 打印变量的信息
* dump a var.
*
* @param mixed $var
* @access public
* @return void
*/
function a($var)
{
echo "<xmp class='a-left'>";
print_r($var);
echo "</xmp>";
}
/**
* 判断是否内外IP。
* Judge the server ip is local or not.
*
* @access public
* @return void
*/
function isLocalIP()
{
$serverIP = $_SERVER['SERVER_ADDR'];
if($serverIP == '127.0.0.1') return true;
if(strpos($serverIP, '10.60') !== false) return false;
return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
}
/**
* 获取webRoot。
* Get web root.
*
* @access public
* @return string
*/
function getWebRoot()
{
$path = $_SERVER['SCRIPT_NAME'];
if(PHP_SAPI == 'cli')
{
$url = parse_url($_SERVER['argv'][1]);
$path = empty($url['path']) ? '/' : rtrim($url['path'], '/');
$path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path);
}
return substr($path, 0, (strrpos($path, '/') + 1));
}
/**
* 检查是否是onlybody模式。
* Check exist onlybody param.
*
* @access public
* @return void
*/
function isonlybody()
{
return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes');
}
/**
* 格式化钱。
* Format money.
*
* @param float $money
* @access public
* @return string
*/
function formatMoney($money)
{
return trim(preg_replace('/\.0*$/', '', number_format($money, 2)));
}
/**
* 格式化时间
* Format time.
*
* @param int $time
* @param string $format
* @access public
* @return void
*/
function formatTime($time, $format = '')
{
$time = str_replace('0000-00-00', '', $time);
$time = str_replace('00:00:00', '', $time);
if(trim($time) == '') return ;
if($format) return date($format, strtotime($time));
return trim($time);
}
/**
* 检查可用curl ssl。
* Check curl ssl enabled.
*
* @access public
* @return void
*/
function checkCurlSSL()
{
$version = curl_version();
return ($version['features'] & CURL_VERSION_SSL);
}
/**
* 当数组/对象变量$var存在$key项时返回存在的对应值或设定值否则返回$key或不存在的设定值。
* When the $var has the $key, return it, esle result one default value.
*
* @param array|object $var
* @param string|int $key
* @param mixed $valueWhenNone value when the key not exits.
* @param mixed $valueWhenExists value when the key exits.
* @access public
* @return string
*/
function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false)
{
if(!is_array($var) and !is_object($var)) return false;
$type = is_array($var) ? 'array' : 'object';
$checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key);
if($checkExists)
{
if($valueWhenExists !== false) return $valueWhenExists;
return $type == 'array' ? $var[$key] : $var->$key;
}
if($valueWhenNone !== false) return $valueWhenNone;
return $key;
}
/**
* 301跳转。
* Header lcoation 301.
*
* @param string $url
* @access public
* @return void
*/
function header301($url)
{
header('HTTP/1.1 301 Moved Permanently');
die(header('Location:' . $url));
}
/**
* 处理恶意参数.
* Process evil params.
*
* @param string $value
* @access public
* @return void
*/
function processEvil($value)
{
global $config;
if(strpos(htmlspecialchars_decode($value), '<?') !== false)
{
$value = (string) $value;
$evils = array('eval', 'exec', 'passthru', 'proc_open', 'shell_exec', 'system', '$$', 'include', 'require', 'assert');
$gibbedEvils = array('e v a l', 'e x e c', ' p a s s t h r u', ' p r o c _ o p e n', 's h e l l _ e x e c', 's y s t e m', '$ $', 'i n c l u d e', 'r e q u i r e', 'a s s e r t');
$value = str_ireplace($evils, $gibbedEvils, $value);
}
if(isset($config->framework->stripXSS) and $config->framework->stripXSS)
{
if(stripos($value, '<script') !== false)
{
$value = (string) $value;
$evils = array('appendchild(', 'createElement(', 'xss.re', 'onfocus', 'onclick', 'innerHTML', 'replaceChild(', 'html(', 'append(', 'appendTo(', 'prepend(', 'prependTo(', 'after(', 'before(', 'replaceWith(');
$gibbedEvils = array('a p p e n d c h i l d (', 'c r e a t e E l e m e n t (', 'x s s . r e', 'o n f o c u s', 'o n c l i c k', 'i n n e r H T M L', 'r e p l a c e C h i l d (', 'h t m l (', 'a p p e n d (', 'a p p e n d T o (', 'p r e p e n d (', 'p r e p e n d T o (', 'a f t e r (', 'b e f o r e (', 'r e p l a c e W i t h (');
$value = str_ireplace($evils, $gibbedEvils, $value);
}
/* Process like 'javascript:' */
$value = preg_replace('/j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t\s*:/Ui', 'j a v a s c r i p t :', $value);
}
return $value;
}
/**
* 批量处理恶意参数.
* Process array evils.
*
* @param array $params
* @access public
* @return array
*/
function processArrayEvils($params)
{
$params = (array) $params;
foreach($params as $item => $values)
{
if(!is_array($values))
{
$params[$item] = processEvil($values);
if(processEvil($item) != $item) unset($params[$item]);
}
else
{
foreach($values as $key => $value)
{
if(is_array($value)) continue;
$params[$item][$key] = processEvil($value);
if(processEvil($key) != $key) unset($params[$item][$key]);
}
}
}
return $params;
}
/**
* 获取主机地址。
* Get host URL.
*
* @access public
* @return bool
*/
function getHostURL()
{
return ((isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) != 'off') ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'];
}
/**
* 判断requestType是否是GET类型。
* Check current request is GET.
*
* @access public
* @return void
*/
function isGetUrl()
{
$webRoot = getWebRoot();
if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}?") === 0) return true;
if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}index.php?") === 0) return true;
if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}index.php/?") === 0) return true;
return false;
}
/**
* 获取文件mime。
* Get file mime type.
*
* @param int $file
* @access public
* @return void
*/
function getFileMimeType($file)
{
if(function_exists('mime_content_type')) return mime_content_type($file);
if(function_exists('finfo_open'))
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
return finfo_file($finfo, $file);
}
return false;
}