FLEA.php

浏览该文件的文档。
00001 <?php
00003 // FleaPHP Framework
00004 //
00005 // Copyright (c) 2005 - 2008 QeeYuan China Inc. (http://www.qeeyuan.com)
00006 //
00007 // 许可协议,请查看源代码中附带的 LICENSE.txt 文件,
00008 // 或者访问 http://www.fleaphp.org/ 获得详细信息。
00010 
00027 global $___fleaphp_loaded_time;
00028 $___fleaphp_loaded_time = microtime();
00029 
00034 // 定义 FleaPHP 版本号常量
00035 define('FLEA_VERSION', '1.0.70.1030');
00036 
00037 // 定义指示 PHP4 或 PHP5 的常量
00038 if (substr(PHP_VERSION, 0, 1) == '5') {
00039     define('PHP5', true);
00040     define('PHP4', false);
00041 } else {
00042     define('PHP5', false);
00043     define('PHP4', true);
00044 }
00045 
00046 // 简写的 DIRECTORY_SEPARATOR
00047 define('DS', DIRECTORY_SEPARATOR);
00048 
00049 // 标准 URL 模式
00050 define('URL_STANDARD',  'URL_STANDARD');
00051 
00052 // PATHINFO 模式
00053 define('URL_PATHINFO',  'URL_PATHINFO');
00054 
00055 // URL 重写模式
00056 define('URL_REWRITE',   'URL_REWRITE');
00057 
00061 // RBAC_EVERYONE 表示任何用户(不管该用户是否具有角色信息)
00062 define('RBAC_EVERYONE',     'RBAC_EVERYONE');
00063 
00064 // RBAC_HAS_ROLE 表示具有任何角色的用户
00065 define('RBAC_HAS_ROLE',     'RBAC_HAS_ROLE');
00066 
00067 // RBAC_NO_ROLE 表示不具有任何角色的用户
00068 define('RBAC_NO_ROLE',      'RBAC_NO_ROLE');
00069 
00070 // RBAC_NULL 表示该设置没有值
00071 define('RBAC_NULL',         'RBAC_NULL');
00072 
00073 // ACTION_ALL 表示控制器中的所有动作
00074 define('ACTION_ALL',        'ACTION_ALL');
00080 define('G_FLEA_VAR', '__FLEA_CORE__');
00081 $GLOBALS[G_FLEA_VAR] = array(
00082     'APP_INF'               => array(),
00083     'OBJECTS'               => array(),
00084     'DBO'                   => array(),
00085     'CLASS_PATH'            => array(),
00086     'FLEA_EXCEPTION_STACK'  => array(),
00087     'FLEA_EXCEPTION_HANDLER'=> null,
00088 );
00089 
00090 // 定义 FleaPHP 文件所在位置,以及初始的 CLASS_PATH
00091 $GLOBALS[G_FLEA_VAR]['CLASS_PATH'][] = dirname(__FILE__);
00092 define('FLEA_DIR', $GLOBALS[G_FLEA_VAR]['CLASS_PATH'][0] . DS . 'FLEA');
00093 define('FLEA_3RD_DIR', $GLOBALS[G_FLEA_VAR]['CLASS_PATH'][0] . DS . '3rd');
00094 
00095 // 载入与早期 FleaPHP 保持兼容性的文件
00096 if (!defined('NO_LEGACY_FLEAPHP') || NO_LEGACY_FLEAPHP == false) {
00097     require(FLEA_DIR . '/Compatibility.php');
00098 }
00099 
00105 if (!defined('DEPLOY_MODE') || DEPLOY_MODE != true) {
00106     $GLOBALS[G_FLEA_VAR]['APP_INF'] = require(FLEA_DIR . '/Config/DEBUG_MODE_CONFIG.php');
00107     define('DEBUG_MODE', true);
00108     if (!defined('DEPLOY_MODE')) { define('DEPLOY_MODE', false); }
00109 } else {
00110     $GLOBALS[G_FLEA_VAR]['APP_INF'] = require(FLEA_DIR . '/Config/DEPLOY_MODE_CONFIG.php');
00111     define('DEBUG_MODE', false);
00112     if (!defined('DEPLOY_MODE')) { define('DEPLOY_MODE', true); }
00113 }
00114 
00115 // 消除在 PHP5 中运行时产生的警告信息
00116 if (!defined('E_STRICT')) {
00117     define('E_STRICT', 2048);
00118 }
00119 if (DEBUG_MODE) {
00120     error_reporting(error_reporting(0) & ~E_STRICT);
00121 } else {
00122     error_reporting(0);
00123 }
00124 
00125 // 设置异常处理例程
00126 __SET_EXCEPTION_HANDLER('__FLEA_EXCEPTION_HANDLER');
00127 
00137 class FLEA
00138 {
00149     function loadAppInf($__flea_internal_config = null)
00150     {
00151         if (!is_array($__flea_internal_config) && is_string($__flea_internal_config)) {
00152             if (!is_readable($__flea_internal_config)) {
00153                 FLEA::loadClass('FLEA_Exception_ExpectedFile');
00154                 return __THROW(new FLEA_Exception_ExpectedFile($__flea_internal_config));
00155             }
00156             $__flea_internal_config = require($__flea_internal_config);
00157         }
00158         if (is_array($__flea_internal_config)) {
00159             $GLOBALS[G_FLEA_VAR]['APP_INF'] = array_merge($GLOBALS[G_FLEA_VAR]['APP_INF'], $__flea_internal_config);
00160         }
00161         return null;
00162     }
00163 
00179     function getAppInf($option, $default = null)
00180     {
00181         return isset($GLOBALS[G_FLEA_VAR]['APP_INF'][$option]) ? $GLOBALS[G_FLEA_VAR]['APP_INF'][$option] : $default;
00182     }
00183 
00201     function getAppInfValue($option, $keyname, $default = null)
00202     {
00203         if (!isset($GLOBALS[G_FLEA_VAR]['APP_INF'][$option])) {
00204             $GLOBALS[G_FLEA_VAR]['APP_INF'][$option] = array();
00205         }
00206         if (array_key_exists($keyname, $GLOBALS[G_FLEA_VAR]['APP_INF'][$option])) {
00207             return $GLOBALS[G_FLEA_VAR]['APP_INF'][$option][$keyname];
00208         } else {
00209             $GLOBALS[G_FLEA_VAR]['APP_INF'][$option][$keyname] = $default;
00210             return $default;
00211         }
00212     }
00213 
00221     function setAppInfValue($option, $keyname, $value)
00222     {
00223         if (!isset($GLOBALS[G_FLEA_VAR]['APP_INF'][$option])) {
00224             $GLOBALS[G_FLEA_VAR]['APP_INF'][$option] = array();
00225         }
00226         $GLOBALS[G_FLEA_VAR]['APP_INF'][$option][$keyname] = $value;
00227     }
00228 
00235     function setAppInf($option, $data = null)
00236     {
00237         if (is_array($option)) {
00238             $GLOBALS[G_FLEA_VAR]['APP_INF'] = array_merge($GLOBALS[G_FLEA_VAR]['APP_INF'], $option);
00239         } else {
00240             $GLOBALS[G_FLEA_VAR]['APP_INF'][$option] = $data;
00241         }
00242     }
00243 
00261     function import($dir)
00262     {
00263         if (array_search($dir, $GLOBALS[G_FLEA_VAR]['CLASS_PATH'], true)) { return; }
00264         if (DIRECTORY_SEPARATOR == '/') {
00265             $dir = str_replace('\\', DIRECTORY_SEPARATOR, $dir);
00266         } else {
00267             $dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
00268         }
00269         $GLOBALS[G_FLEA_VAR]['CLASS_PATH'][] = $dir;
00270     }
00271 
00288     function loadFile($filename, $loadOnce = false)
00289     {
00290         static $is_loaded = array();
00291 
00292         $path = FLEA::getFilePath($filename);
00293         if ($path != '') {
00294             if (isset($is_loaded[$path]) && $loadOnce) { return true; }
00295             $is_loaded[$path] = true;
00296             if ($loadOnce) {
00297                 return require_once($path);
00298             } else {
00299                 return require($path);
00300             }
00301         }
00302 
00303         FLEA::loadClass('FLEA_Exception_ExpectedFile');
00304         __THROW(new FLEA_Exception_ExpectedFile($filename));
00305         return false;
00306     }
00307 
00325     function loadClass($className, $noException = false)
00326     {
00327         if (PHP5) {
00328             if (class_exists($className, false) || interface_exists($className, false)) { return true; }
00329         } else {
00330             if (class_exists($className)) { return true; }
00331         }
00332 
00333         if (preg_match('/[^a-z0-9\-_.]/i', $className) === 0) {
00334             $filename = FLEA::getFilePath($className . '.php');
00335             if ($filename) {
00336                 require($filename);
00337                 if (PHP5) {
00338                     if (class_exists($className, false) || interface_exists($className, false)) { return true; }
00339                 } else {
00340                     if (class_exists($className)) { return true; }
00341                 }
00342             }
00343         }
00344 
00345         if ($noException) { return false; }
00346 
00347         $filename = FLEA::getFilePath($className . '.php', true);
00348         require_once(FLEA_DIR . '/Exception/ExpectedClass.php');
00349         __THROW(new FLEA_Exception_ExpectedClass($className, $filename, file_exists($filename)));
00350         return false;
00351     }
00352 
00363     function getFilePath($filename, $return = false)
00364     {
00365         $filename = str_replace('_', DIRECTORY_SEPARATOR, $filename);
00366         if (DIRECTORY_SEPARATOR == '/') {
00367             $filename = str_replace('\\', DIRECTORY_SEPARATOR, $filename);
00368         } else {
00369             $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
00370         }
00371 
00372         if (strtolower(substr($filename, -4)) != '.php') {
00373             $filename .= '.php';
00374         }
00375 
00376         // 首先搜索当前目录
00377         if (is_file($filename)) { return $filename; }
00378 
00379         foreach ($GLOBALS[G_FLEA_VAR]['CLASS_PATH'] as $classdir) {
00380             $path = $classdir . DIRECTORY_SEPARATOR . $filename;
00381             if (is_file($path)) { return $path; }
00382         }
00383 
00384         if ($return) { return $filename; }
00385         return false;
00386     }
00387 
00404     function & getSingleton($className)
00405     {
00406         static $instances = array();
00407         if (FLEA::isRegistered($className)) {
00408             // 返回已经存在的对象实例
00409             return FLEA::registry($className);
00410         }
00411         if (PHP5) {
00412             $classExists = class_exists($className, false);
00413         } else {
00414             $classExists = class_exists($className);
00415         }
00416         if (!$classExists) {
00417             if (!FLEA::loadClass($className)) {
00418                 $return = false;
00419                 return $return;
00420             }
00421         }
00422 
00423         $instances[$className] =& new $className();
00424         FLEA::register($instances[$className], $className);
00425         return $instances[$className];
00426     }
00427 
00448     function & register(& $obj, $name = null)
00449     {
00450         if (!is_object($obj)) {
00451             FLEA::loadClass('FLEA_Exception_TypeMismatch');
00452             return __THROW(new FLEA_Exception_TypeMismatch($obj, 'object', gettype($obj)));
00453         }
00454 
00455         if (is_null($name)) {
00456             $name = get_class($obj);
00457         }
00458 
00459         if (isset($GLOBALS[G_FLEA_VAR]['OBJECTS'][$name])) {
00460             FLEA::loadClass('FLEA_Exception_ExistsKeyName');
00461             return __THROW(new FLEA_Exception_ExistsKeyName($name));
00462         } else {
00463             $GLOBALS[G_FLEA_VAR]['OBJECTS'][$name] =& $obj;
00464             return $obj;
00465         }
00466     }
00467 
00477     function & registry($name = null)
00478     {
00479         if (is_null($name)) {
00480             return $GLOBALS[G_FLEA_VAR]['OBJECTS'];
00481         }
00482         if (isset($GLOBALS[G_FLEA_VAR]['OBJECTS'][$name]) && is_object($GLOBALS[G_FLEA_VAR]['OBJECTS'][$name])) {
00483             return $GLOBALS[G_FLEA_VAR]['OBJECTS'][$name];
00484         }
00485         FLEA::loadClass('FLEA_Exception_NotExistsKeyName');
00486         return __THROW(new FLEA_Exception_NotExistsKeyName($name));
00487     }
00488 
00505     function isRegistered($name)
00506     {
00507         return isset($GLOBALS[G_FLEA_VAR]['OBJECTS'][$name]);
00508     }
00509 
00510 
00538     function getCache($cacheId, $time = 900, $timeIsLifetime = true, $cacheIdIsFilename = false)
00539     {
00540         $cacheDir = FLEA::getAppInf('internalCacheDir');
00541         if (is_null($cacheDir)) {
00542             FLEA::loadClass('FLEA_Exception_CacheDisabled');
00543             __THROW(new FLEA_Exception_CacheDisabled($cacheDir));
00544             return false;
00545         }
00546 
00547         if ($cacheIdIsFilename) {
00548             $cacheFile = $cacheDir . DS . preg_replace('/[^a-z0-9\-_]/i', '_', $cacheId) . '.php';
00549         } else {
00550             $cacheFile = $cacheDir . DS . md5($cacheId) . '.php';
00551         }
00552         if (!file_exists($cacheFile)) { return false; }
00553 
00554         if ($timeIsLifetime && $time == -1) {
00555             $data = safe_file_get_contents($cacheFile);
00556             $hash = substr($data, 16, 32);
00557             $data = substr($data, 48);
00558             if (crc32($data) != $hash || strlen($hash) != 32) {
00559                 return false;
00560             }
00561             return $data !== false ? unserialize($data) : false;
00562         }
00563 
00564         $filetime = filemtime($cacheFile);
00565         if ($timeIsLifetime) {
00566             if (time() >= $filetime + $time) { return false; }
00567         } else {
00568             if ($time >= $filetime) { return false; }
00569         }
00570         $data = safe_file_get_contents($cacheFile);
00571         $hash = substr($data, 16, 32);
00572         $data = substr($data, 48);
00573         if (crc32($data) != $hash || strlen($hash) != 32) {
00574             return false;
00575         }
00576         return $data !== false ? unserialize($data) : false;
00577     }
00578 
00596     function writeCache($cacheId, $data, $cacheIdIsFilename = false)
00597     {
00598         $cacheDir = FLEA::getAppInf('internalCacheDir');
00599         if (is_null($cacheDir)) {
00600             FLEA::loadClass('FLEA_Exception_CacheDisabled');
00601             __THROW(new FLEA_Exception_CacheDisabled($cacheDir));
00602             return false;
00603         }
00604 
00605         if ($cacheIdIsFilename) {
00606             $cacheFile = $cacheDir . DS . preg_replace('/[^a-z0-9\-_]/i', '_', $cacheId) . '.php';
00607         } else {
00608             $cacheFile = $cacheDir . DS . md5($cacheId) . '.php';
00609         }
00610 
00611         $data = serialize($data);
00612         $prefix = '<?php die(); ?> ';
00613         $hash = sprintf('% 32d', crc32($data));
00614         $data = $prefix . $hash . $data;
00615 
00616         if (!safe_file_put_contents($cacheFile, $data)) {
00617             FLEA::loadClass('FLEA_Exception_CacheDisabled');
00618             __THROW(new FLEA_Exception_CacheDisabled($cacheDir));
00619             return false;
00620         } else {
00621             return true;
00622         }
00623     }
00624 
00633     function purgeCache($cacheId, $cacheIdIsFilename = false)
00634     {
00635         $cacheDir = FLEA::getAppInf('internalCacheDir');
00636         if (is_null($cacheDir)) {
00637             FLEA::loadClass('FLEA_Exception_CacheDisabled');
00638             __THROW(new FLEA_Exception_CacheDisabled($cacheDir));
00639             return false;
00640         }
00641 
00642         if ($cacheIdIsFilename) {
00643             $cacheFile = $cacheDir . DS . preg_replace('/[^a-z0-9\-_]/i', '_', $cacheId);
00644         } else {
00645             $cacheFile = $cacheDir . DS . md5($cacheId);
00646         }
00647 
00648         if (file_exists($cacheFile)) {
00649             return unlink($cacheFile);
00650         }
00651         return true;
00652     }
00653 
00654 
00662     function & initWebControls()
00663     {
00664         return FLEA::getSingleton(FLEA::getAppInf('webControlsClassName'));
00665     }
00666 
00674     function & initAjax()
00675     {
00676         return FLEA::getSingleton(FLEA::getAppInf('ajaxClassName'));
00677     }
00678 
00687     function loadHelper($helperName)
00688     {
00689         $settingName = 'helper.' . strtolower($helperName);
00690         $setting = FLEA::getAppInf($settingName);
00691         if ($setting) {
00692             return FLEA::loadFile($setting, true);
00693         } else {
00694             FLEA::loadClass('FLEA_Exception_NotExistsKeyName');
00695             return __THROW(new FLEA_Exception_NotExistsKeyName('helper.' . $helperName));
00696         }
00697     }
00698 
00727     function & getDBO($dsn = 0)
00728     {
00729         if ($dsn == 0) {
00730             $dsn = FLEA::getAppInf('dbDSN');
00731         }
00732         $dsn = FLEA::parseDSN($dsn);
00733 
00734         if (!is_array($dsn) || !isset($dsn['driver'])) {
00735             FLEA::loadClass('FLEA_Db_Exception_InvalidDSN');
00736             return __THROW(new FLEA_Db_Exception_InvalidDSN($dsn));
00737         }
00738 
00739         $dsnid = $dsn['id'];
00740         if (isset($GLOBALS[G_FLEA_VAR]['DBO'][$dsnid])) {
00741             return $GLOBALS[G_FLEA_VAR]['DBO'][$dsnid];
00742         }
00743 
00744         $driver = ucfirst(strtolower($dsn['driver']));
00745         $className = 'FLEA_Db_Driver_' . $driver;
00746         if ($driver == 'Mysql' || $driver == 'Mysqlt') {
00747             require_once(FLEA_DIR . '/Db/Driver/Mysql.php');
00748         } else {
00749             FLEA::loadClass($className);
00750         }
00751         $dbo =& new $className($dsn);
00752         /* @var $dbo FLEA_Db_Driver_Abstract */
00753         $dbo->connect();
00754 
00755         $GLOBALS[G_FLEA_VAR]['DBO'][$dsnid] =& $dbo;
00756         return $GLOBALS[G_FLEA_VAR]['DBO'][$dsnid];
00757     }
00758 
00766     function parseDSN($dsn)
00767     {
00768         if (is_array($dsn)) {
00769             $dsn['host'] = isset($dsn['host']) ? $dsn['host'] : '';
00770             $dsn['port'] = isset($dsn['port']) ? $dsn['port'] : '';
00771             $dsn['login'] = isset($dsn['login']) ? $dsn['login'] : '';
00772             $dsn['password'] = isset($dsn['password']) ? $dsn['password'] : '';
00773             $dsn['database'] = isset($dsn['database']) ? $dsn['database'] : '';
00774             $dsn['options'] = isset($dsn['options']) ? $dsn['options'] : '';
00775             $dsn['prefix'] = isset($dsn['prefix']) ? $dsn['prefix'] : FLEA::getAppInf('dbTablePrefix');
00776             $dsn['schema'] = isset($dsn['schema']) ? $dsn['schema'] : '';
00777         } else {
00778             $dsn = str_replace('@/', '@localhost/', $dsn);
00779             $parse = parse_url($dsn);
00780             if (empty($parse['scheme'])) { return false; }
00781 
00782             $dsn = array();
00783             $dsn['host']     = isset($parse['host']) ? $parse['host'] : 'localhost';
00784             $dsn['port']     = isset($parse['port']) ? $parse['port'] : '';
00785             $dsn['login']    = isset($parse['user']) ? $parse['user'] : '';
00786             $dsn['password'] = isset($parse['pass']) ? $parse['pass'] : '';
00787             $dsn['driver']   = isset($parse['scheme']) ? strtolower($parse['scheme']) : '';
00788             $dsn['database'] = isset($parse['path']) ? substr($parse['path'], 1) : '';
00789             $dsn['options']  = isset($parse['query']) ? $parse['query'] : '';
00790             $dsn['prefix'] = FLEA::getAppInf('dbTablePrefix');
00791             $dsn['schema']   = '';
00792         }
00793         $dsnid = "{$dsn['driver']}://{$dsn['login']}:{$dsn['password']}@{$dsn['host']}_{$dsn['prefix']}/{$dsn['database']}/{$dsn['schema']}/{$dsn['options']}";
00794         $dsn['id'] = $dsnid;
00795         return $dsn;
00796     }
00797 
00803     function runMVC()
00804     {
00805         $MVCPackageFilename = FLEA::getAppInf('MVCPackageFilename');
00806         if ($MVCPackageFilename != '') {
00807             require_once($MVCPackageFilename);
00808         }
00809         FLEA::init();
00810 
00811         // 载入调度器并转发请求到控制器
00812         $dispatcherClass = FLEA::getAppInf('dispatcher');
00813         FLEA::loadClass($dispatcherClass);
00814 
00815         $dispatcher =& new $dispatcherClass($_GET);
00816         FLEA::register($dispatcher, $dispatcherClass);
00817         $dispatcher->dispatching();
00818     }
00819 
00825     function init($loadMVC = false)
00826     {
00827         static $firstTime = true;
00828 
00829         // 避免重复调用 FLEA::init()
00830         if (!$firstTime) { return; }
00831         $firstTime = false;
00832 
00836         __SET_EXCEPTION_HANDLER(FLEA::getAppInf('exceptionHandler'));
00837         if (PHP5) {
00838             set_exception_handler(FLEA::getAppInf('exceptionHandler'));
00839         }
00840 
00844         if (FLEA::getAppInf('logEnabled') && FLEA::getAppInf('logProvider')) {
00845             FLEA::loadClass(FLEA::getAppInf('logProvider'));
00846         }
00847         if (!function_exists('log_message')) {
00848             // 如果没有指定日志服务提供程序,就定义一个空的 log_message() 函数
00849             function log_message() {};
00850         }
00851 
00855         $cachedir = FLEA::getAppInf('internalCacheDir');
00856         if (empty($cachedir)) {
00857             FLEA::setAppInf('internalCacheDir', dirname(__FILE__) . DS . '_Cache');
00858         }
00859 
00860         // 过滤 magic_quotes
00861         if (get_magic_quotes_gpc()) {
00862             $in = array(& $_GET, & $_POST, & $_COOKIE, & $_REQUEST);
00863             while (list($k,$v) = each($in)) {
00864                 foreach ($v as $key => $val) {
00865                     if (!is_array($val)) {
00866                         $in[$k][$key] = stripslashes($val);
00867                         continue;
00868                     }
00869                     $in[] =& $in[$k][$key];
00870                 }
00871             }
00872             unset($in);
00873         }
00874         set_magic_quotes_runtime(0);
00875 
00876         // 根据 URL 模式设置,决定是否要载入 URL 分析过滤器
00877         if (FLEA::getAppInf('urlMode') != URL_STANDARD) {
00878             require(FLEA_DIR . '/Filter/Uri.php');
00879         }
00880 
00881         // 处理 requestFilters
00882         foreach ((array)FLEA::getAppInf('requestFilters') as $file) {
00883             FLEA::loadFile($file);
00884         }
00885 
00886         // 处理 $loadMVC
00887         if ($loadMVC) {
00888             $MVCPackageFilename = FLEA::getAppInf('MVCPackageFilename');
00889             if ($MVCPackageFilename != '') {
00890                 require_once($MVCPackageFilename);
00891             }
00892         }
00893 
00894         // 处理 autoLoad
00895         foreach ((array)FLEA::getAppInf('autoLoad') as $file) {
00896             FLEA::loadFile($file);
00897         }
00898 
00899         // 载入指定的 session 服务提供程序
00900         if (FLEA::getAppInf('sessionProvider')) {
00901             FLEA::getSingleton(FLEA::getAppInf('sessionProvider'));
00902         }
00903         // 自动起用 session 会话
00904         if (FLEA::getAppInf('autoSessionStart')) {
00905             session_start();
00906         }
00907 
00908         // 定义 I18N 相关的常量
00909         define('RESPONSE_CHARSET', FLEA::getAppInf('responseCharset'));
00910         define('DATABASE_CHARSET', FLEA::getAppInf('databaseCharset'));
00911 
00912         // 检查是否启用多语言支持
00913         if (FLEA::getAppInf('multiLanguageSupport')) {
00914             FLEA::loadClass(FLEA::getAppInf('languageSupportProvider'));
00915         }
00916         if (!function_exists('_T')) {
00917             function _T() {};
00918         }
00919 
00920         // 自动输出内容头信息
00921         if (FLEA::getAppInf('autoResponseHeader')) {
00922             header('Content-Type: text/html; charset=' . FLEA::getAppInf('responseCharset'));
00923         }
00924     }
00925 }
00926 
00940 function redirect($url, $delay = 0, $js = false, $jsWrapped = true, $return = false)
00941 {
00942     $delay = (int)$delay;
00943     if (!$js) {
00944         if (headers_sent() || $delay > 0) {
00945             echo <<<EOT
00946     <html>
00947     <head>
00948     <meta http-equiv="refresh" content="{$delay};URL={$url}" />
00949     </head>
00950     </html>
00951 EOT;
00952             exit;
00953         } else {
00954             header("Location: {$url}");
00955             exit;
00956         }
00957     }
00958 
00959     $out = '';
00960     if ($jsWrapped) {
00961         $out .= '<script language="JavaScript" type="text/javascript">';
00962     }
00963     if ($delay > 0) {
00964         $out .= "window.setTimeout(function () { document.location='{$url}'; }, {$delay});";
00965     } else {
00966         $out .= "document.location='{$url}';";
00967     }
00968     if ($jsWrapped) {
00969         $out .= '</script>';
00970     }
00971 
00972     if ($return) {
00973         return $out;
00974     }
00975 
00976     echo $out;
00977     exit;
00978 }
00979 
01019 function url($controllerName = null, $actionName = null, $params = null, $anchor = null, $options = null)
01020 {
01021     static $baseurl = null, $currentBootstrap = null;
01022 
01023     $callback = FLEA::getAppInf('urlCallback');
01024     if (!empty($callback)) {
01025         call_user_func_array($callback, array(& $controllerName, & $actionName, & $params, & $anchor, & $options));
01026     }
01027 
01028     // 确定当前的 URL 基础地址和入口文件名
01029     if (is_null($baseurl)) {
01030         $baseurl = detect_uri_base();
01031         $p = strrpos($baseurl, '/');
01032         $currentBootstrap = substr($baseurl, $p + 1);
01033         $baseurl = substr($baseurl, 0, $p);
01034     }
01035 
01036     // 确定生成 url 要使用的 bootstrap
01037     $options = (array)$options;
01038     if (isset($options['bootstrap'])) {
01039         $bootstrap = $options['bootstrap'];
01040     } else if ($currentBootstrap == '') {
01041         $bootstrap = FLEA::getAppInf('urlBootstrap');
01042     } else {
01043         $bootstrap = $currentBootstrap;
01044     }
01045 
01046     // 确定控制器和动作的名字
01047     $defaultController = FLEA::getAppInf('defaultController');
01048     $defaultAction = FLEA::getAppInf('defaultAction');
01049     $lowerChar = isset($options['lowerChar']) ? $options['lowerChar'] : FLEA::getAppInf('urlLowerChar');
01050     if ($lowerChar) {
01051         $defaultController = strtolower($defaultController);
01052         $defaultAction = strtolower($defaultAction);
01053     }
01054 
01055     if ($bootstrap != $currentBootstrap && $currentBootstrap != '') {
01056         $controllerName = !empty($controllerName) ? $controllerName : null;
01057         $actionName = !empty($actionName) ? $actionName : null;
01058     } else {
01059         $controllerName = !empty($controllerName) ? $controllerName : $defaultController;
01060         $actionName = !empty($actionName) ? $actionName : $defaultAction;
01061     }
01062     if ($lowerChar) {
01063         $controllerName = strtolower($controllerName);
01064         $actionName = strtolower($actionName);
01065     }
01066 
01067     $url = '';
01068     $mode = isset($options['mode']) ? $options['mode'] : FLEA::getAppInf('urlMode');
01069 
01070     // PATHINFO 和 REWRITE 模式
01071     if ($mode == URL_PATHINFO || $mode == URL_REWRITE) {
01072         $url = $baseurl;
01073         if ($mode == URL_PATHINFO) {
01074             $url .= '/' . $bootstrap;
01075         }
01076         if ($controllerName != '' && $actionName != '') {
01077             $pps = isset($options['parameterPairStyle']) ? $options['parameterPairStyle'] : FLEA::getAppInf('urlParameterPairStyle');
01078             $url .= '/' . rawurlencode($controllerName);
01079             if (is_array($params) && !empty($params)) {
01080                 $url .= '/' . rawurlencode($actionName);
01081                 $url .= '/' . encode_url_args($params, $mode, $pps);
01082             } else {
01083                 if (FLEA::getAppInf('urlAlwaysUseAccessor') || $actionName != $defaultAction) {
01084                     $url .= '/' . rawurlencode($actionName);
01085                 }
01086             }
01087         }
01088         if ($anchor) { $url .= '#' . $anchor; }
01089         return $url;
01090     }
01091 
01092     // 标准模式
01093     $alwaysUseBootstrap = isset($options['alwaysUseBootstrap']) ? $options['alwaysUseBootstrap'] : FLEA::getAppInf('urlAlwaysUseBootstrap');
01094     $url = $baseurl . '/';
01095 
01096     if ($alwaysUseBootstrap || $bootstrap != FLEA::getAppInf('urlBootstrap')) {
01097         $url .= $bootstrap;
01098     }
01099 
01100     $parajoin = '?';
01101     if (FLEA::getAppInf('urlAlwaysUseAccessor')) {
01102         $defaultController = '';
01103         $defaultAction = '';
01104     }
01105     if ($controllerName != $defaultController && !is_null($controllerName)) {
01106         $url .= $parajoin . FLEA::getAppInf('controllerAccessor'). '=' . $controllerName;
01107         $parajoin = '&';
01108     }
01109     if ($actionName != $defaultAction && !is_null($actionName)) {
01110         $url .= $parajoin . FLEA::getAppInf('actionAccessor') . '=' . $actionName;
01111         $parajoin = '&';
01112     }
01113 
01114     if (is_array($params) && !empty($params)) {
01115         $url .= $parajoin . encode_url_args($params, $mode);
01116     }
01117     if ($anchor) { $url .= '#' . $anchor; }
01118 
01119     return $url;
01120 }
01121 
01131 function detect_uri_base($queryMode = false)
01132 {
01133     $aURL = array();
01134 
01135     // Try to get the request URL
01136     if (!empty($_SERVER['SCRIPT_NAME'])) {
01137         $arr = parse_url($_SERVER['SCRIPT_NAME']);
01138         $aURL['path'] = $arr['path'];
01139     } elseif (!empty($_SERVER['REQUEST_URI'])) {
01140         $_SERVER['REQUEST_URI'] = str_replace(array('"',"'",'<','>'), array('%22','%27','%3C','%3E'), $_SERVER['REQUEST_URI']);
01141         $p = strpos($_SERVER['REQUEST_URI'], ':');
01142         if ($p > 0 && substr($_SERVER['REQUEST_URI'], $p + 1, 2) != '//') {
01143             $aURL = array('path' => $_SERVER['REQUEST_URI']);
01144         } else {
01145             $aURL = parse_url($_SERVER['REQUEST_URI']);
01146         }
01147         if (isset($aURL['path']) && isset($_SERVER['PATH_INFO'])) {
01148             $aURL['path'] = substr(urldecode($aURL['path']), 0, - strlen($_SERVER['PATH_INFO']));
01149         }
01150     }
01151 
01152     // Fill in the empty values
01153     if (empty($aURL['scheme'])) {
01154         if (!empty($_SERVER['HTTP_SCHEME'])) {
01155             $aURL['scheme'] = $_SERVER['HTTP_SCHEME'];
01156         } else {
01157             $aURL['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http';
01158         }
01159     }
01160 
01161     if (empty($aURL['host'])) {
01162         if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
01163             $p = strpos($_SERVER['HTTP_X_FORWARDED_HOST'], ':');
01164             if ($p > 0) {
01165                 $aURL['host'] = substr($_SERVER['HTTP_X_FORWARDED_HOST'], 0, $p);
01166                 $aURL['port'] = substr($_SERVER['HTTP_X_FORWARDED_HOST'], $p + 1);
01167             } else {
01168                 $aURL['host'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
01169             }
01170         } else if (!empty($_SERVER['HTTP_HOST'])) {
01171             $p = strpos($_SERVER['HTTP_HOST'], ':');
01172             if ($p > 0) {
01173                 $aURL['host'] = substr($_SERVER['HTTP_HOST'], 0, $p);
01174                 $aURL['port'] = substr($_SERVER['HTTP_HOST'], $p + 1);
01175             } else {
01176                 $aURL['host'] = $_SERVER['HTTP_HOST'];
01177             }
01178         } else if (!empty($_SERVER['SERVER_NAME'])) {
01179             $aURL['host'] = $_SERVER['SERVER_NAME'];
01180         }
01181     }
01182 
01183     if (empty($aURL['port']) && !empty($_SERVER['SERVER_PORT'])) {
01184         $aURL['port'] = $_SERVER['SERVER_PORT'];
01185     }
01186 
01187     if (empty($aURL['path'])) {
01188         if (!empty($_SERVER['PATH_INFO'])) {
01189             $sPath = parse_url($_SERVER['PATH_INFO']);
01190         } else {
01191             $sPath = parse_url($_SERVER['PHP_SELF']);
01192         }
01193         $aURL['path'] = str_replace(array('"',"'",'<','>'), array('%22','%27','%3C','%3E'), $sPath['path']);
01194         unset($sPath);
01195     }
01196 
01197     // Build the URL: Start with scheme, user and pass
01198     $sURL = $aURL['scheme'].'://';
01199     if (!empty($aURL['user'])) {
01200         $sURL .= $aURL['user'];
01201         if (!empty($aURL['pass'])) {
01202             $sURL .= ':'.$aURL['pass'];
01203         }
01204         $sURL .= '@';
01205     }
01206 
01207     // Add the host
01208     $sURL .= $aURL['host'];
01209 
01210     // Add the port if needed
01211     if (!empty($aURL['port']) && (($aURL['scheme'] == 'http' && $aURL['port'] != 80) || ($aURL['scheme'] == 'https' && $aURL['port'] != 443))) {
01212         $sURL .= ':'.$aURL['port'];
01213     }
01214 
01215     $sURL .= $aURL['path'];
01216 
01217     // Add the path and the query string
01218     if ($queryMode && isset($aURL['query'])) {
01219         $sURL .= $aURL['query'];
01220     }
01221 
01222     unset($aURL);
01223     return $sURL;
01224 }
01225 
01241 function encode_url_args($args, $urlMode = URL_STANDARD, $parameterPairStyle = null)
01242 {
01243     $str = '';
01244     switch ($urlMode) {
01245     case URL_STANDARD:
01246         if (is_null($parameterPairStyle)) {
01247             $parameterPairStyle = '=';
01248         }
01249         $sc = '&';
01250         break;
01251     case URL_PATHINFO:
01252     case URL_REWRITE:
01253         if (is_null($parameterPairStyle)) {
01254             $parameterPairStyle = FLEA::getAppInf('urlParameterPairStyle');
01255         }
01256         $sc = '/';
01257         break;
01258     }
01259 
01260     foreach ($args as $key => $value) {
01261         if (is_null($value) || $value === '') { continue; }
01262         if (is_array($value)) {
01263             $append = encode_url_args($value, $urlMode);
01264         } else {
01265             $append = rawurlencode($key) . $parameterPairStyle . rawurlencode($value);
01266         }
01267         if (substr($str, -1) != $sc) {
01268             $str .= $sc;
01269         }
01270         $str .= $append;
01271     }
01272     return substr($str, 1);
01273 }
01274 
01282 function h($text)
01283 {
01284     return htmlspecialchars($text);
01285 }
01286 
01296 function t($text)
01297 {
01298     return nl2br(str_replace(' ', '&nbsp;', htmlspecialchars($text)));
01299 }
01300 
01315 function js_alert($message = '', $after_action = '', $url = '')
01316 {
01317     $out = "<script language=\"javascript\" type=\"text/javascript\">\n";
01318     if (!empty($message)) {
01319         $out .= "alert(\"";
01320         $out .= str_replace("\\\\n", "\\n", t2js(addslashes($message)));
01321         $out .= "\");\n";
01322     }
01323     if (!empty($after_action)) {
01324         $out .= $after_action . "\n";
01325     }
01326     if (!empty($url)) {
01327         $out .= "document.location.href=\"";
01328         $out .= $url;
01329         $out .= "\";\n";
01330     }
01331     $out .= "</script>";
01332     echo $out;
01333     exit;
01334 }
01335 
01343 function t2js($content)
01344 {
01345     return str_replace(array("\r", "\n"), array('', '\n'), addslashes($content));
01346 }
01347 
01357 function safe_file_put_contents($filename, & $content)
01358 {
01359     $fp = fopen($filename, 'wb');
01360     if ($fp) {
01361         flock($fp, LOCK_EX);
01362         fwrite($fp, $content);
01363         flock($fp, LOCK_UN);
01364         fclose($fp);
01365         return true;
01366     } else {
01367         return false;
01368     }
01369 }
01370 
01378 function safe_file_get_contents($filename)
01379 {
01380     $fp = fopen($filename, 'rb');
01381     if ($fp) {
01382         flock($fp, LOCK_SH);
01383         clearstatcache();
01384         $filesize = filesize($filename);
01385         if ($filesize > 0) {
01386             $data = fread($fp, $filesize);
01387         }
01388         flock($fp, LOCK_UN);
01389         fclose($fp);
01390         return $data;
01391     } else {
01392         return false;
01393     }
01394 }
01395 
01396 if (!function_exists('file_put_contents'))
01397 {
01398     function file_put_contents($filename, & $content)
01399     {
01400         return safe_file_put_contents($filename, $content);
01401     }
01402 }
01403 
01489 function __THROW($exception)
01490 {
01491     // 写入日志
01492     if (function_exists('log_message')) {
01493         log_message(get_class($exception) . ': ' . $exception->getMessage(), 'exception');
01494     }
01495 
01496     // 确定是否将异常保存在栈中
01497     if (isset($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']) && is_array($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']))
01498     {
01499         $point = array_pop($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']);
01500         if ($point != null) {
01501             array_push($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK'], $exception);
01502             $ret = false;
01503             return $ret;
01504         }
01505     }
01506 
01507     if (isset($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_HANDLER'])) {
01508         call_user_func_array($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_HANDLER'], array(& $exception));
01509     } else {
01510         __FLEA_EXCEPTION_HANDLER($exception);
01511     }
01512     exit;
01513 }
01514 
01520 function __TRY()
01521 {
01522     static $point = 0;
01523     if (!isset($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']) ||
01524         !is_array($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']))
01525     {
01526         $GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK'] = array();
01527     }
01528 
01529     $point++;
01530     array_push($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK'], $point);
01531 }
01532 
01540 function __CATCH()
01541 {
01542     if (!is_array($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK'])) {
01543         return false;
01544     }
01545     $exception = array_pop($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']);
01546     if (!is_object($exception)) {
01547         $exception = false;
01548     }
01549     return $exception;
01550 }
01551 
01557 function __CANCEL_TRY()
01558 {
01559     if (is_array($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK'])) {
01560         array_pop($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_STACK']);
01561     }
01562 }
01563 
01574 function __IS_EXCEPTION($exception, $type = null)
01575 {
01576     if (!is_object($exception) || !is_a($exception, 'FLEA_Exception')) {
01577         return false;
01578     }
01579     if (is_null($type)) {
01580         return true;
01581     } else {
01582         return strtoupper($type) == strtoupper(get_class($exception));
01583     }
01584 }
01585 
01622 function __SET_EXCEPTION_HANDLER($callback)
01623 {
01624     if (isset($GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_HANDLER'])) {
01625         $current = $GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_HANDLER'];
01626     } else {
01627         $current = null;
01628     }
01629     $GLOBALS[G_FLEA_VAR]['FLEA_EXCEPTION_HANDLER'] = $callback;
01630     return $current;
01631 }
01632 
01640 function __FLEA_EXCEPTION_HANDLER($ex)
01641 {
01642     if (!FLEA::getAppInf('displayErrors')) { exit; }
01643     if (FLEA::getAppInf('friendlyErrorsMessage')) {
01644         $language = FLEA::getAppInf('defaultLanguage');
01645         $language = preg_replace('/[^a-z0-9\-_]+/i', '', $language);
01646 
01647         $exclass = strtoupper(get_class($ex));
01648         $template = FLEA_DIR . "/_Errors/{$language}/{$exclass}.php";
01649         if (!file_exists($template)) {
01650             $template = FLEA_DIR . "/_Errors/{$language}/FLEA_EXCEPTION.php";
01651             if (!file_exists($template)) {
01652                 $template = FLEA_DIR . "/_Errors/default/FLEA_EXCEPTION.php";
01653             }
01654         }
01655         include($template);
01656     } else {
01657         print_ex($ex);
01658     }
01659     exit;
01660 }
01661 
01670 function print_ex($ex, $return = false)
01671 {
01672     $out = "exception '" . get_class($ex) . "'";
01673     if ($ex->getMessage() != '') {
01674         $out .= " with message '" . $ex->getMessage() . "'";
01675     }
01676     if (defined('DEPLOY_MODE') && DEPLOY_MODE != false) {
01677         $out .= ' in ' . basename($ex->getFile()) . ':' . $ex->getLine() . "\n\n";
01678     } else {
01679         $out .= ' in ' . $ex->getFile() . ':' . $ex->getLine() . "\n\n";
01680         $out .= $ex->getTraceAsString();
01681     }
01682 
01683     if ($return) { return $out; }
01684 
01685     if (ini_get('html_errors')) {
01686         echo nl2br(htmlspecialchars($out));
01687     } else {
01688         echo $out;
01689     }
01690 
01691     return '';
01692 }
01693 
01703 function dump($vars, $label = '', $return = false)
01704 {
01705     if (ini_get('html_errors')) {
01706         $content = "<pre>\n";
01707         if ($label != '') {
01708             $content .= "<strong>{$label} :</strong>\n";
01709         }
01710         $content .= htmlspecialchars(print_r($vars, true));
01711         $content .= "\n</pre>\n";
01712     } else {
01713         $content = $label . " :\n" . print_r($vars, true);
01714     }
01715     if ($return) { return $content; }
01716     echo $content;
01717     return null;
01718 }
01719 
01727 function dump_trace()
01728 {
01729     $debug = debug_backtrace();
01730     $lines = '';
01731     $index = 0;
01732     for ($i = 0; $i < count($debug); $i++) {
01733         if ($i == 0) { continue; }
01734         $file = $debug[$i];
01735         if ($file['file'] == '') { continue; }
01736         if (substr($file['file'], 0, strlen(FLEA_DIR)) != FLEA_DIR) {
01737             $line = "#<strong>{$index} {$file['file']}({$file['line']}): </strong>";
01738         } else {
01739             $line = "#{$index} {$file['file']}({$file['line']}): ";
01740         }
01741         if (isset($file['class'])) {
01742             $line .= "{$file['class']}{$file['type']}";
01743         }
01744         $line .= "{$file['function']}(";
01745         if (isset($file['args']) && count($file['args'])) {
01746             foreach ($file['args'] as $arg) {
01747                 $line .= gettype($arg) . ', ';
01748             }
01749             $line = substr($line, 0, -2);
01750         }
01751         $line .= ')';
01752         $lines .= $line . "\n";
01753         $index++;
01754     } // for
01755     $lines .= "#{$index} {main}\n";
01756 
01757     if (ini_get('html_errors')) {
01758         echo nl2br(str_replace(' ', '&nbsp;', $lines));
01759     } else {
01760         echo $lines;
01761     }
01762 }
01763 
01771 function microtime_float($time = null)
01772 {
01773     list($usec, $sec) = explode(' ', $time ? $time : microtime());
01774     return ((float)$usec + (float)$sec);
01775 }
01776 
01795 function _ET($errorCode, $appError = false)
01796 {
01797     static $message = array();
01798 
01799     $language = FLEA::getAppInf('defaultLanguage');
01800     $language = preg_replace('/[^a-z0-9\-_]+/i', '', $language);
01801 
01802     if (!isset($message[$language])) {
01803         if ($appError) {
01804             $filename = FLEA::getAppInf('languageFilesDir') . DS .
01805                 $language . DS . 'ErrorMessage.php';
01806         } else {
01807             // 读取 FleaPHP 自带的错误信息列表
01808             $filename = FLEA_DIR . "/_Errors/{$language}/ErrorMessage.php";
01809         }
01810         if (!is_readable($filename)) {
01811             $filename = FLEA_DIR . '/_Errors/default/ErrorMessage.php';
01812         }
01813         $message[$language] = include($filename);
01814     }
01815 
01816     return isset($message[$language][$errorCode]) ?
01817         $message[$language][$errorCode] :
01818         '';
01819 }
01820 
01824 if (PHP5) {
01825 
01826     class FLEA_Exception extends Exception
01827     {
01828         function FLEA_Exception($message = '', $code = 0)
01829         {
01830             parent::__construct($message, $code);
01831         }
01832     }
01833 
01834 } else {
01835 
01846     class FLEA_Exception
01847     {
01853         var $message = 'Unknown exception';
01854 
01858         var $code = 0;
01859 
01865         var $file;
01866 
01872         var $line;
01873 
01879         var $trac;
01880 
01889         function FLEA_Exception($message = null, $code = 0)
01890         {
01891             $this->message = $message;
01892             $this->code = $code;
01893             $this->trac = debug_backtrace();
01894 
01895             // 取得抛出异常的文件和代码行号
01896             $last = array_shift($this->trac);
01897             $this->file = $last['file'];
01898             $this->line = $last['line'];
01899         }
01900 
01906         function getMessage()
01907         {
01908             return $this->message;
01909         }
01910 
01916         function getCode()
01917         {
01918             return $this->code;
01919         }
01920 
01926         function getFile()
01927         {
01928             return $this->file;
01929         }
01930 
01936         function getLine()
01937         {
01938             return $this->line;
01939         }
01940 
01946         function getTrace()
01947         {
01948             return $this->trac;
01949         }
01950 
01954         function getTraceAsString()
01955         {
01956             $out = '';
01957             $ix = 0;
01958             foreach ($this->trac as $point) {
01959                 $out .= "#{$ix} {$point['file']}({$point['line']}): {$point['function']}(";
01960                 if (is_array($point['args']) && count($point['args']) > 0) {
01961                     foreach ($point['args'] as $arg) {
01962                         switch (gettype($arg)) {
01963                         case 'array':
01964                         case 'resource':
01965                             $out .= gettype($arg);
01966                             break;
01967                         case 'object':
01968                             $out .= get_class($arg);
01969                             break;
01970                         case 'string':
01971                             if (strlen($arg) > 30) {
01972                                 $arg = substr($arg, 0, 27) . ' ...';
01973                             }
01974                             $out .= "'{$arg}'";
01975                             break;
01976                         default:
01977                             $out .= $arg;
01978                         }
01979                         $out .= ', ';
01980                     }
01981                     $out = substr($out, 0, -2);
01982                 }
01983                 $out .= ")\n";
01984                 $ix++;
01985             }
01986             $out .= "#{$ix} {main}\n";
01987 
01988             return $out;
01989         }
01990 
01996         function __toString()
01997         {
01998             $out = "exception '" . get_class($this) . "'";
01999             if ($this->message != '') {
02000                 $out .= " with message '{$this->message}'";
02001             }
02002             $out .= " in {$this->file}:{$this->line}\n\n";
02003             $out .= $this->getTraceAsString();
02004             return $out;
02005         }
02006     }
02007 
02008 }
02009 
02019 if (!function_exists('json_encode')) {
02027     function json_encode($value)