From 223760b65dfe447c81bcc7f09e85307548dfe36f Mon Sep 17 00:00:00 2001 From: thinkphp Date: Fri, 16 Jan 2015 22:42:51 +0800 Subject: [PATCH] =?UTF-8?q?TP4=E5=88=9D=E5=A7=8B=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Org/README.md | 1 + Library/Think/App.php | 255 +++ Library/Think/Auto.php | 59 + Library/Think/Behavior/ContentReplace.php | 65 + Library/Think/Behavior/LocationTemplate.php | 48 + Library/Think/Behavior/ReadHtmlCache.php | 122 ++ Library/Think/Behavior/ShowPageTrace.php | 90 ++ Library/Think/Behavior/TokenBuild.php | 61 + Library/Think/Cache.php | 38 + Library/Think/Cache/Driver/Apc.php | 101 ++ Library/Think/Cache/Driver/Db.php | 146 ++ Library/Think/Cache/Driver/Eaccelerator.php | 101 ++ Library/Think/Cache/Driver/File.php | 184 +++ Library/Think/Cache/Driver/Memcache.php | 113 ++ Library/Think/Cache/Driver/Redis.php | 116 ++ Library/Think/Cache/Driver/Secache.php | 722 +++++++++ Library/Think/Cache/Driver/Simple.php | 99 ++ Library/Think/Cache/Driver/Sqlite.php | 119 ++ Library/Think/Cache/Driver/Wincache.php | 103 ++ Library/Think/Cache/Driver/Xcache.php | 106 ++ Library/Think/Config.php | 91 ++ Library/Think/Config/Driver/Ini.php | 22 + Library/Think/Config/Driver/Xml.php | 29 + Library/Think/Controller.php | 186 +++ Library/Think/Controller/Amf.php | 29 + Library/Think/Controller/Phprpc.php | 34 + Library/Think/Controller/Rest.php | 215 +++ Library/Think/Cookie.php | 131 ++ Library/Think/Create.php | 102 ++ Library/Think/Crypt.php | 74 + Library/Think/Db.php | 97 ++ Library/Think/Db/Driver.php | 1037 +++++++++++++ Library/Think/Db/Driver/Mongo.php | 735 +++++++++ Library/Think/Db/Driver/Mysql.php | 92 ++ Library/Think/Db/Driver/Oracle.php | 153 ++ Library/Think/Db/Driver/Pgsql.php | 91 ++ Library/Think/Db/Driver/Sqlite.php | 98 ++ Library/Think/Db/Driver/Sqlsrv.php | 164 ++ Library/Think/Db/Lite.php | 449 ++++++ Library/Think/Debug.php | 112 ++ Library/Think/Error.php | 128 ++ Library/Think/Exception.php | 16 + Library/Think/Filter.php | 222 +++ Library/Think/Image.php | 61 + Library/Think/Image/Driver/Gd.php | 549 +++++++ Library/Think/Image/Driver/Gif.php | 570 +++++++ Library/Think/Image/Driver/Imagick.php | 591 +++++++ Library/Think/Input.php | 90 ++ Library/Think/Lang.php | 54 + Library/Think/Loader.php | 233 +++ Library/Think/Log.php | 84 + Library/Think/Log/Driver/File.php | 43 + Library/Think/Model.php | 1031 +++++++++++++ Library/Think/Model/ExtendModel.php | 18 + Library/Think/Model/MongoModel.php | 274 ++++ Library/Think/Model/RelationModel.php | 16 + Library/Think/Model/ViewModel.php | 16 + Library/Think/Oauth.php | 71 + Library/Think/Oauth/Driver.php | 233 +++ Library/Think/Oauth/Driver/Baidu.php | 93 ++ Library/Think/Oauth/Driver/Diandian.php | 93 ++ Library/Think/Oauth/Driver/Douban.php | 91 ++ Library/Think/Oauth/Driver/Github.php | 93 ++ Library/Think/Oauth/Driver/Google.php | 99 ++ Library/Think/Oauth/Driver/Kaixin.php | 94 ++ Library/Think/Oauth/Driver/Msn.php | 100 ++ Library/Think/Oauth/Driver/Qq.php | 102 ++ Library/Think/Oauth/Driver/Renren.php | 116 ++ Library/Think/Oauth/Driver/Sina.php | 93 ++ Library/Think/Oauth/Driver/Sohu.php | 93 ++ Library/Think/Oauth/Driver/T163.php | 95 ++ Library/Think/Oauth/Driver/Taobao.php | 97 ++ Library/Think/Oauth/Driver/Tencent.php | 98 ++ Library/Think/Oauth/Driver/X360.php | 93 ++ Library/Think/Parser.php | 32 + Library/Think/Parser/Driver/Markdown.php | 1534 +++++++++++++++++++ Library/Think/Parser/Driver/Ubb.php | 290 ++++ Library/Think/Route.php | 439 ++++++ Library/Think/Seesion/Driver.php | 22 + Library/Think/Session.php | 160 ++ Library/Think/Tag.php | 84 + Library/Think/Template.php | 733 +++++++++ Library/Think/Template/Driver/File.php | 45 + Library/Think/Template/TagLib.php | 248 +++ Library/Think/Template/TagLib/Cx.php | 614 ++++++++ Library/Think/Transform.php | 81 + Library/Think/Transform/Driver/Json.php | 22 + Library/Think/Transform/Driver/Xml.php | 119 ++ Library/Think/Upload.php | 514 +++++++ Library/Think/Url.php | 151 ++ Library/Think/Validate.php | 189 +++ Library/Think/View.php | 228 +++ Library/Think/View/Driver/Think.php | 28 + Tpl/default_index.tpl | 8 + Tpl/dispatch_jump.tpl | 44 + Tpl/page_trace.tpl | 67 + Tpl/think_exception.tpl | 53 + Traits/Think/Model/Auto.php | 363 +++++ Traits/Think/Model/Extend.php | 261 ++++ Traits/Think/Model/Query.php | 92 ++ Traits/Think/Model/Relation.php | 346 +++++ Traits/Think/Model/View.php | 239 +++ Vendor/phpRPC/bigint.php | 369 +++++ Vendor/phpRPC/compat.php | 241 +++ Vendor/phpRPC/dhparams.php | 77 + Vendor/phpRPC/dhparams/1024.dhp | 1 + Vendor/phpRPC/dhparams/128.dhp | 1 + Vendor/phpRPC/dhparams/1536.dhp | 1 + Vendor/phpRPC/dhparams/160.dhp | 1 + Vendor/phpRPC/dhparams/192.dhp | 1 + Vendor/phpRPC/dhparams/2048.dhp | 1 + Vendor/phpRPC/dhparams/256.dhp | 1 + Vendor/phpRPC/dhparams/3072.dhp | 1 + Vendor/phpRPC/dhparams/4096.dhp | 1 + Vendor/phpRPC/dhparams/512.dhp | 1 + Vendor/phpRPC/dhparams/768.dhp | 1 + Vendor/phpRPC/dhparams/96.dhp | 1 + Vendor/phpRPC/pecl/xxtea/CREDITS | 2 + Vendor/phpRPC/pecl/xxtea/INSTALL | 66 + Vendor/phpRPC/pecl/xxtea/LICENSE | 68 + Vendor/phpRPC/pecl/xxtea/README | 28 + Vendor/phpRPC/pecl/xxtea/config.m4 | 7 + Vendor/phpRPC/pecl/xxtea/config.w32 | 6 + Vendor/phpRPC/pecl/xxtea/php_xxtea.c | 193 +++ Vendor/phpRPC/pecl/xxtea/php_xxtea.dsp | 179 +++ Vendor/phpRPC/pecl/xxtea/php_xxtea.h | 49 + Vendor/phpRPC/pecl/xxtea/php_xxtea.sln | 25 + Vendor/phpRPC/pecl/xxtea/php_xxtea.vcproj | 520 +++++++ Vendor/phpRPC/pecl/xxtea/test/test.php | 8 + Vendor/phpRPC/pecl/xxtea/xxtea.c | 54 + Vendor/phpRPC/pecl/xxtea/xxtea.h | 47 + Vendor/phpRPC/phprpc_client.php | 583 +++++++ Vendor/phpRPC/phprpc_date.php | 522 +++++++ Vendor/phpRPC/phprpc_server.php | 496 ++++++ Vendor/phpRPC/xxtea.php | 134 ++ alias.php | 40 + base.php | 232 +++ convention.php | 65 + start.php | 56 + 139 files changed, 23425 insertions(+) create mode 100644 Library/Org/README.md create mode 100644 Library/Think/App.php create mode 100644 Library/Think/Auto.php create mode 100644 Library/Think/Behavior/ContentReplace.php create mode 100644 Library/Think/Behavior/LocationTemplate.php create mode 100644 Library/Think/Behavior/ReadHtmlCache.php create mode 100644 Library/Think/Behavior/ShowPageTrace.php create mode 100644 Library/Think/Behavior/TokenBuild.php create mode 100644 Library/Think/Cache.php create mode 100644 Library/Think/Cache/Driver/Apc.php create mode 100644 Library/Think/Cache/Driver/Db.php create mode 100644 Library/Think/Cache/Driver/Eaccelerator.php create mode 100644 Library/Think/Cache/Driver/File.php create mode 100644 Library/Think/Cache/Driver/Memcache.php create mode 100644 Library/Think/Cache/Driver/Redis.php create mode 100644 Library/Think/Cache/Driver/Secache.php create mode 100644 Library/Think/Cache/Driver/Simple.php create mode 100644 Library/Think/Cache/Driver/Sqlite.php create mode 100644 Library/Think/Cache/Driver/Wincache.php create mode 100644 Library/Think/Cache/Driver/Xcache.php create mode 100644 Library/Think/Config.php create mode 100644 Library/Think/Config/Driver/Ini.php create mode 100644 Library/Think/Config/Driver/Xml.php create mode 100644 Library/Think/Controller.php create mode 100644 Library/Think/Controller/Amf.php create mode 100644 Library/Think/Controller/Phprpc.php create mode 100644 Library/Think/Controller/Rest.php create mode 100644 Library/Think/Cookie.php create mode 100644 Library/Think/Create.php create mode 100644 Library/Think/Crypt.php create mode 100644 Library/Think/Db.php create mode 100644 Library/Think/Db/Driver.php create mode 100644 Library/Think/Db/Driver/Mongo.php create mode 100644 Library/Think/Db/Driver/Mysql.php create mode 100644 Library/Think/Db/Driver/Oracle.php create mode 100644 Library/Think/Db/Driver/Pgsql.php create mode 100644 Library/Think/Db/Driver/Sqlite.php create mode 100644 Library/Think/Db/Driver/Sqlsrv.php create mode 100644 Library/Think/Db/Lite.php create mode 100644 Library/Think/Debug.php create mode 100644 Library/Think/Error.php create mode 100644 Library/Think/Exception.php create mode 100644 Library/Think/Filter.php create mode 100644 Library/Think/Image.php create mode 100644 Library/Think/Image/Driver/Gd.php create mode 100644 Library/Think/Image/Driver/Gif.php create mode 100644 Library/Think/Image/Driver/Imagick.php create mode 100644 Library/Think/Input.php create mode 100644 Library/Think/Lang.php create mode 100644 Library/Think/Loader.php create mode 100644 Library/Think/Log.php create mode 100644 Library/Think/Log/Driver/File.php create mode 100644 Library/Think/Model.php create mode 100644 Library/Think/Model/ExtendModel.php create mode 100644 Library/Think/Model/MongoModel.php create mode 100644 Library/Think/Model/RelationModel.php create mode 100644 Library/Think/Model/ViewModel.php create mode 100644 Library/Think/Oauth.php create mode 100644 Library/Think/Oauth/Driver.php create mode 100644 Library/Think/Oauth/Driver/Baidu.php create mode 100644 Library/Think/Oauth/Driver/Diandian.php create mode 100644 Library/Think/Oauth/Driver/Douban.php create mode 100644 Library/Think/Oauth/Driver/Github.php create mode 100644 Library/Think/Oauth/Driver/Google.php create mode 100644 Library/Think/Oauth/Driver/Kaixin.php create mode 100644 Library/Think/Oauth/Driver/Msn.php create mode 100644 Library/Think/Oauth/Driver/Qq.php create mode 100644 Library/Think/Oauth/Driver/Renren.php create mode 100644 Library/Think/Oauth/Driver/Sina.php create mode 100644 Library/Think/Oauth/Driver/Sohu.php create mode 100644 Library/Think/Oauth/Driver/T163.php create mode 100644 Library/Think/Oauth/Driver/Taobao.php create mode 100644 Library/Think/Oauth/Driver/Tencent.php create mode 100644 Library/Think/Oauth/Driver/X360.php create mode 100644 Library/Think/Parser.php create mode 100644 Library/Think/Parser/Driver/Markdown.php create mode 100644 Library/Think/Parser/Driver/Ubb.php create mode 100644 Library/Think/Route.php create mode 100644 Library/Think/Seesion/Driver.php create mode 100644 Library/Think/Session.php create mode 100644 Library/Think/Tag.php create mode 100644 Library/Think/Template.php create mode 100644 Library/Think/Template/Driver/File.php create mode 100644 Library/Think/Template/TagLib.php create mode 100644 Library/Think/Template/TagLib/Cx.php create mode 100644 Library/Think/Transform.php create mode 100644 Library/Think/Transform/Driver/Json.php create mode 100644 Library/Think/Transform/Driver/Xml.php create mode 100644 Library/Think/Upload.php create mode 100644 Library/Think/Url.php create mode 100644 Library/Think/Validate.php create mode 100644 Library/Think/View.php create mode 100644 Library/Think/View/Driver/Think.php create mode 100644 Tpl/default_index.tpl create mode 100644 Tpl/dispatch_jump.tpl create mode 100644 Tpl/page_trace.tpl create mode 100644 Tpl/think_exception.tpl create mode 100644 Traits/Think/Model/Auto.php create mode 100644 Traits/Think/Model/Extend.php create mode 100644 Traits/Think/Model/Query.php create mode 100644 Traits/Think/Model/Relation.php create mode 100644 Traits/Think/Model/View.php create mode 100644 Vendor/phpRPC/bigint.php create mode 100644 Vendor/phpRPC/compat.php create mode 100644 Vendor/phpRPC/dhparams.php create mode 100644 Vendor/phpRPC/dhparams/1024.dhp create mode 100644 Vendor/phpRPC/dhparams/128.dhp create mode 100644 Vendor/phpRPC/dhparams/1536.dhp create mode 100644 Vendor/phpRPC/dhparams/160.dhp create mode 100644 Vendor/phpRPC/dhparams/192.dhp create mode 100644 Vendor/phpRPC/dhparams/2048.dhp create mode 100644 Vendor/phpRPC/dhparams/256.dhp create mode 100644 Vendor/phpRPC/dhparams/3072.dhp create mode 100644 Vendor/phpRPC/dhparams/4096.dhp create mode 100644 Vendor/phpRPC/dhparams/512.dhp create mode 100644 Vendor/phpRPC/dhparams/768.dhp create mode 100644 Vendor/phpRPC/dhparams/96.dhp create mode 100644 Vendor/phpRPC/pecl/xxtea/CREDITS create mode 100644 Vendor/phpRPC/pecl/xxtea/INSTALL create mode 100644 Vendor/phpRPC/pecl/xxtea/LICENSE create mode 100644 Vendor/phpRPC/pecl/xxtea/README create mode 100644 Vendor/phpRPC/pecl/xxtea/config.m4 create mode 100644 Vendor/phpRPC/pecl/xxtea/config.w32 create mode 100644 Vendor/phpRPC/pecl/xxtea/php_xxtea.c create mode 100644 Vendor/phpRPC/pecl/xxtea/php_xxtea.dsp create mode 100644 Vendor/phpRPC/pecl/xxtea/php_xxtea.h create mode 100644 Vendor/phpRPC/pecl/xxtea/php_xxtea.sln create mode 100644 Vendor/phpRPC/pecl/xxtea/php_xxtea.vcproj create mode 100644 Vendor/phpRPC/pecl/xxtea/test/test.php create mode 100644 Vendor/phpRPC/pecl/xxtea/xxtea.c create mode 100644 Vendor/phpRPC/pecl/xxtea/xxtea.h create mode 100644 Vendor/phpRPC/phprpc_client.php create mode 100644 Vendor/phpRPC/phprpc_date.php create mode 100644 Vendor/phpRPC/phprpc_server.php create mode 100644 Vendor/phpRPC/xxtea.php create mode 100644 alias.php create mode 100644 base.php create mode 100644 convention.php create mode 100644 start.php diff --git a/Library/Org/README.md b/Library/Org/README.md new file mode 100644 index 00000000..6f940733 --- /dev/null +++ b/Library/Org/README.md @@ -0,0 +1 @@ +Org命名空间目录 diff --git a/Library/Think/App.php b/Library/Think/App.php new file mode 100644 index 00000000..6b987027 --- /dev/null +++ b/Library/Think/App.php @@ -0,0 +1,255 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +/** + * App 应用管理 + * @author liu21st + */ +class App { + + /** + * 执行应用程序 + * @access public + * @return void + */ + static public function run() { + // 监听app_init + Tag::listen('app_init'); + if(Config::get('common_module')){ + define('COMMON_PATH', APP_PATH . Config::get('common_module').'/'); + // 加载全局初始化文件 + if(is_file( COMMON_PATH . 'init' . EXT )) { + include COMMON_PATH . 'init' . EXT; + }else{ + // 检测全局配置文件 + if(is_file(COMMON_PATH . 'config' . EXT)) { + Config::set(include COMMON_PATH . 'config' . EXT); + } + // 加载全局别名文件 + if(is_file(COMMON_PATH . 'alias' . EXT)) { + Loader::addMap(include COMMON_PATH . 'alias' . EXT); + } + // 加载全局公共文件 + if(is_file( COMMON_PATH . 'common' . EXT)) { + include COMMON_PATH . 'common' . EXT; + } + if(is_file(COMMON_PATH . 'tags' . EXT)) { + // 全局行为扩展文件 + Tag::import(include COMMON_PATH . 'tags' . EXT); + } + } + } + + // 应用URL调度 + self::dispatch($config); + + // 监听app_run + Tag::listen('app_run'); + + // 执行操作 + $instance = Loader::controller(CONTROLLER_NAME); + if(!$instance) { + E('[ ' . MODULE_NAME . '\\Controller\\' . parse_name(CONTROLLER_NAME, 1) . 'Controller ] not exists'); + } + + // 获取当前操作名 + $action = ACTION_NAME . $config['action_suffix']; + try{ + // 操作方法开始监听 + $call = [$instance, $action]; + Tag::listen('action_begin', $call); + if(!preg_match('/^[A-Za-z](\w)*$/', $action)){ + // 非法操作 + throw new \ReflectionException(); + } + //执行当前操作 + $method = new \ReflectionMethod($instance, $action); + if($method->isPublic()) { + // URL参数绑定检测 + if($config['url_params_bind'] && $method->getNumberOfParameters() > 0){ + switch($_SERVER['REQUEST_METHOD']) { + case 'POST': + $vars = array_merge($_GET, $_POST); + break; + case 'PUT': + parse_str(file_get_contents('php://input'), $vars); + break; + default: + $vars = $_GET; + } + $params = $method->getParameters(); + foreach ($params as $param){ + $name = $param->getName(); + if(isset($vars[$name])) { + $args[] = $vars[$name]; + }elseif($param->isDefaultValueAvailable()){ + $args[] = $param->getDefaultValue(); + }else{ + E('_PARAM_ERROR_:' . $name); + } + } + $method->invokeArgs($instance, $args); + }else{ + $method->invoke($instance); + } + // 操作方法执行完成监听 + Tag::listen('action_end', $call); + }else{ + // 操作方法不是Public 抛出异常 + throw new \ReflectionException(); + } + } catch (\ReflectionException $e) { + // 操作不存在 + if(method_exists($instance, '_empty')) { + $method = new \ReflectionMethod($instance, '_empty'); + $method->invokeArgs($instance, [$action, '']); + }else{ + E('[ ' . (new \ReflectionClass($instance))->getName() . ':' . $action . ' ] not exists ', 404); + } + } + // 监听app_end + Tag::listen('app_end'); + return ; + } + + /** + * URL调度 + * @access public + * @return void + */ + static public function dispatch($config) { + $var_m = $config['var_module']; + $var_g = $config['var_group']; + $var_c = $config['var_controller']; + $var_a = $config['var_action']; + $var_p = $config['var_pathinfo']; + if(isset($_GET[$var_p])) { // 判断URL里面是否有兼容模式参数 + $_SERVER['PATH_INFO'] = $_GET[$var_p]; + unset($_GET[$var_p]); + }elseif(IS_CLI){ // CLI模式下 index.php module/controller/action/params/... + $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; + } + + // 检测域名部署 + if(!IS_CLI) { + Route::checkDomain(); + } + + // 监听path_info + Tag::listen('path_info'); + // 分析PATHINFO信息 + if(!isset($_SERVER['PATH_INFO']) && $_SERVER['SCRIPT_NAME'] != $_SERVER['PHP_SELF']) { + $types = explode(',', $config['pathinfo_fetch']); + foreach ($types as $type){ + if(0 === strpos($type, ':')) {// 支持函数判断 + $_SERVER['PATH_INFO'] = call_user_func(substr($type,1)); + break; + }elseif(!empty($_SERVER[$type])) { + $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? + substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; + break; + } + } + } + + // 定位模块 + if(empty($_SERVER['PATH_INFO'])) { + $_SERVER['PATH_INFO'] = ''; + } + + // URL后缀 + define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'],PATHINFO_EXTENSION))); + $_SERVER['PATH_INFO'] = trim(preg_replace('/\.(' . trim($config['url_html_suffix'], '.') . ')$/i', '', $_SERVER['PATH_INFO']), '/'); + if($_SERVER['PATH_INFO']) { + if($config['url_deny_suffix'] && preg_match('/\.('.$config['url_deny_suffix'].')$/i', $_SERVER['PATH_INFO'])){ + exit; + } + $paths = explode($config['pathinfo_depr'], $_SERVER['PATH_INFO']); + // 获取URL中的模块名 + if($config['require_module'] && !isset($_GET[$var_m])) { + $_GET[$var_m] = array_shift($paths); + $_SERVER['PATH_INFO'] = implode('/', $paths); + } + } + + // 获取模块名称 + $module = strtolower(isset($_GET[$var_m]) ? $_GET[$var_m] : $config['default_module']); + if($maps = Config::get('url_module_map')) { + if(isset($maps[$module])) { + // 记录当前别名 + define('MODULE_ALIAS',$module); + // 获取实际的项目名 + $module = $maps[MODULE_ALIAS]; + }elseif(array_search($module,$maps)){ + // 禁止访问原始项目 + $module = ''; + } + } + define('MODULE_NAME', ucwords($module)); + // 模块初始化 + if(MODULE_NAME && Config::get('common_module') != MODULE_NAME && is_dir( APP_PATH . MODULE_NAME )) { + Tag::listen('app_begin'); + define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); + // 加载模块初始化文件 + if(is_file( MODULE_PATH . 'init' . EXT )) { + include MODULE_PATH . 'init' . EXT; + $config = Config::get(); + }else{ + // 检测项目(或模块)配置文件 + if(is_file(MODULE_PATH . 'config' . EXT)) { + $config = Config::set(include MODULE_PATH . 'config' . EXT); + } + if($config['app_status'] && is_file(MODULE_PATH . $config['app_status'] . EXT)) { + // 加载对应的项目配置文件 + $config = Config::set(include MODULE_PATH . $config['app_status'] . EXT); + } + // 加载别名文件 + if(is_file(MODULE_PATH . 'alias' . EXT)) { + Loader::addMap(include MODULE_PATH . 'alias' . EXT); + } + // 加载公共文件 + if(is_file( MODULE_PATH . 'common' . EXT)) { + include MODULE_PATH . 'common' . EXT; + } + if(is_file(MODULE_PATH . 'tags' . EXT)) { + // 行为扩展文件 + Tag::import(include MODULE_PATH . 'tags' . EXT); + } + } + $var_g = $config['var_group']; + $var_c = $config['var_controller']; + $var_a = $config['var_action']; + }else{ + E('module not exists :' . MODULE_NAME); + } + // 路由检测和控制器、操作解析 + Route::check($_SERVER['PATH_INFO']); + + // 获取分组名 + if(Config::get('require_group')){ + define('GROUP_NAME', strtolower(isset($_GET[$var_g]) ? $_GET[$var_g] : $config['default_group'])); + }else{ + define('GROUP_NAME', ''); + } + + // 获取控制器名 + define('CONTROLLER_NAME', strtolower(isset($_GET[$var_c]) ? $_GET[$var_c] : $config['default_controller'])); + + // 获取操作名 + define('ACTION_NAME', strtolower(isset($_GET[$var_a]) ? $_GET[$var_a] : $config['default_action'])); + + unset($_GET[$var_a], $_GET[$var_c], $_GET[$var_m]); + //保证$_REQUEST正常取值 + $_REQUEST = array_merge($_POST, $_GET); + } +} diff --git a/Library/Think/Auto.php b/Library/Think/Auto.php new file mode 100644 index 00000000..50de171a --- /dev/null +++ b/Library/Think/Auto.php @@ -0,0 +1,59 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Auto { + + protected $auto = []; + + public function rule($rule){ + $this->auto = $rule; + return $this; + } + + /** + * 自动表单处理 + * @access public + * @param array $data 创建数据 + * @return mixed + */ + public function operate($data) { + // 自动填充 + if($this->auto) { + foreach ($this->auto as $auto){ + // 填充因子定义格式 + // array('field','填充内容','附加规则',[额外参数]) + switch(trim($auto[2])) { + case 'callback': // 使用回调方法 + $args = isset($auto[3])?(array)$auto[3]:[]; + if(isset($data[$auto[0]])) { + array_unshift($args,$data[$auto[0]]); + } + $data[$auto[0]] = call_user_func_array($auto[1], $args); + break; + case 'field': // 用其它字段的值进行填充 + $data[$auto[0]] = $data[$auto[1]]; + break; + case 'ignore': // 为空忽略 + if(''===$data[$auto[0]]) + unset($data[$auto[0]]); + break; + case 'string': + default: // 默认作为字符串填充 + $data[$auto[0]] = $auto[1]; + } + if(false === $data[$auto[0]] ) unset($data[$auto[0]]); + } + } + return $data; + } +} diff --git a/Library/Think/Behavior/ContentReplace.php b/Library/Think/Behavior/ContentReplace.php new file mode 100644 index 00000000..76e3300b --- /dev/null +++ b/Library/Think/Behavior/ContentReplace.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Behavior; +use Think\Config; + +/** + * 系统行为扩展:模板内容输出替换 + * @category Think + * @package Think + * @subpackage Behavior + * @author liu21st + */ +class ContentReplace { + + // 行为扩展的执行入口必须是run + public function run(&$content){ + $content = $this->templateContentReplace($content); + } + + /** + * 模板内容替换 + * @access protected + * @param string $content 模板内容 + * @return string + */ + protected function templateContentReplace($content) { + if(IS_CGI) { + //CGI/FASTCGI模式下 + $_temp = explode('.php',$_SERVER['PHP_SELF']); + $script_name = rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'); + }else { + $script_name = rtrim($_SERVER['SCRIPT_NAME'],'/'); + } + define('ROOT_URL', rtrim(dirname(str_replace("\\","\/",$script_name)),'/')); + define('MODULE_URL', ROOT_URL.(Config::get('require_module')?'/'.(defined('MODULE_ALIAS')?MODULE_ALIAS:MODULE_NAME):'')); + define('CONTROLLER_URL', MODULE_URL.(Config::get('require_controller')?'/'.CONTROLLER_NAME:'')); + define('ACTION_URL', CONTROLLER_URL.'/'.ACTION_NAME); + + // 系统默认的特殊变量替换 + $replace = [ + '__ROOT__' => ROOT_URL, // 当前网站地址 + '__APP__' => MODULE_URL, // 当前项目地址 + '__CONTROLL__' => CONTROLLER_URL, // 当前操作地址 + '__URL__' => CONTROLLER_URL, + '__ACTION__' => ACTION_URL, // 当前操作地址 + '__SELF__' => $_SERVER['PHP_SELF'], // 当前页面地址 + '__PUBLIC__' => ROOT_URL.'/Public',// 站点公共目录 + ]; + // 允许用户自定义模板的字符串替换 + if(is_array(Config::get('tmpl_parse_string')) ) + $replace = array_merge($replace,Config::get('tmpl_parse_string')); + $content = str_replace(array_keys($replace),array_values($replace),$content); + return $content; + } + +} diff --git a/Library/Think/Behavior/LocationTemplate.php b/Library/Think/Behavior/LocationTemplate.php new file mode 100644 index 00000000..327553d5 --- /dev/null +++ b/Library/Think/Behavior/LocationTemplate.php @@ -0,0 +1,48 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Behavior; + +/** + * 系统行为扩展:定位模板文件 + * @category Think + * @package Think + * @subpackage Behavior + * @author liu21st + */ +class LocationTemplate { + // 行为扩展的执行入口必须是run + public function run(&$templateFile){ + // 自动定位模板文件 + if(!is_file($templateFile)) + $templateFile = $this->parseTemplateFile($templateFile); + } + + /** + * 自动定位模板文件 + * @access private + * @param string $templateFile 文件名 + * @return string + */ + private function parseTemplateFile($template) { + $template = str_replace(':','/',$template); + if(''==$template) { + // 如果模板文件名为空 按照默认规则定位 + $template = CONTROLLER_NAME.'/'.ACTION_NAME; + }elseif(false === strpos($template,'/')){ + $template = CONTROLLER_NAME.'/'.$template; + }elseif(false === strpos($template,'.')) { + $template = $template; + } + $templateFile = MODULE_PATH.'View/'.$template.'.html'; + return $templateFile; + } +} diff --git a/Library/Think/Behavior/ReadHtmlCache.php b/Library/Think/Behavior/ReadHtmlCache.php new file mode 100644 index 00000000..9027d447 --- /dev/null +++ b/Library/Think/Behavior/ReadHtmlCache.php @@ -0,0 +1,122 @@ + +// +---------------------------------------------------------------------- + +/** + * 系统行为扩展:静态缓存读取 + * @category Think + * @package Think + * @subpackage Behavior + * @author liu21st + */ +class ReadHtmlCacheBehavior { + protected $options = [ + 'HTML_CACHE_ON' => false, + 'HTML_CACHE_TIME' => 60, + 'HTML_CACHE_RULES' => [], + 'HTML_FILE_SUFFIX' => '.html', + ]; + + // 行为扩展的执行入口必须是run + public function run(&$params){ + // 开启静态缓存 + if(C('HTML_CACHE_ON')) { + $cacheTime = $this->requireHtmlCache(); + if( false !== $cacheTime && $this->checkHTMLCache(HTML_FILE_NAME,$cacheTime)) { //静态页面有效 + // 读取静态页面输出 + readfile(HTML_FILE_NAME); + exit(); + } + } + } + + // 判断是否需要静态缓存 + static private function requireHtmlCache() { + // 分析当前的静态规则 + $htmls = C('HTML_CACHE_RULES'); // 读取静态规则 + if(!empty($htmls)) { + $htmls = array_change_key_case($htmls); + // 静态规则文件定义格式 actionName=>array('静态规则','缓存时间','附加规则') + // 'read'=>array('{id},{name}',60,'md5') 必须保证静态规则的唯一性 和 可判断性 + // 检测静态规则 + $moduleName = strtolower(MODULE_NAME); + $actionName = strtolower(ACTION_NAME); + if(isset($htmls[$moduleName.':'.$actionName])) { + $html = $htmls[$moduleName.':'.$actionName]; // 某个模块的操作的静态规则 + }elseif(isset($htmls[$moduleName.':'])){// 某个模块的静态规则 + $html = $htmls[$moduleName.':']; + }elseif(isset($htmls[$actionName])){ + $html = $htmls[$actionName]; // 所有操作的静态规则 + }elseif(isset($htmls['*'])){ + $html = $htmls['*']; // 全局静态规则 + }elseif(isset($htmls['empty:index']) && !class_exists(MODULE_NAME.'Action')){ + $html = $htmls['empty:index']; // 空模块静态规则 + }elseif(isset($htmls[$moduleName.':_empty']) && $this->isEmptyAction(MODULE_NAME,ACTION_NAME)){ + $html = $htmls[$moduleName.':_empty']; // 空操作静态规则 + } + if(!empty($html)) { + // 解读静态规则 + $rule = $html[0]; + // 以$_开头的系统变量 + $rule = preg_replace('/{\$(_\w+)\.(\w+)\|(\w+)}/e',"\\3(\$\\1['\\2'])",$rule); + $rule = preg_replace('/{\$(_\w+)\.(\w+)}/e',"\$\\1['\\2']",$rule); + // {ID|FUN} GET变量的简写 + $rule = preg_replace('/{(\w+)\|(\w+)}/e',"\\2(\$_GET['\\1'])",$rule); + $rule = preg_replace('/{(\w+)}/e',"\$_GET['\\1']",$rule); + // 特殊系统变量 + $rule = str_ireplace( + ['{:app}','{:module}','{:action}','{:group}'], + [APP_NAME,MODULE_NAME,ACTION_NAME,defined('GROUP_NAME')?GROUP_NAME:''], + $rule); + // {|FUN} 单独使用函数 + $rule = preg_replace('/{|(\w+)}/e',"\\1()",$rule); + if(!empty($html[2])) $rule = $html[2]($rule); // 应用附加函数 + $cacheTime = isset($html[1])?$html[1]:C('HTML_CACHE_TIME'); // 缓存有效期 + // 当前缓存文件 + define('HTML_FILE_NAME',HTML_PATH . $rule.C('HTML_FILE_SUFFIX')); + return $cacheTime; + } + } + // 无需缓存 + return false; + } + + /** + * 检查静态HTML文件是否有效 + * 如果无效需要重新更新 + * @access public + * @param string $cacheFile 静态文件名 + * @param integer $cacheTime 缓存有效期 + * @return boolen + */ + static public function checkHTMLCache($cacheFile='',$cacheTime='') { + if(!is_file($cacheFile)){ + return false; + }elseif (filemtime(C('TEMPLATE_NAME')) > filemtime($cacheFile)) { + // 模板文件如果更新静态文件需要更新 + return false; + }elseif(!is_numeric($cacheTime) && function_exists($cacheTime)){ + return $cacheTime($cacheFile); + }elseif ($cacheTime != 0 && NOW_TIME > filemtime($cacheFile)+$cacheTime) { + // 文件是否在有效期 + return false; + } + //静态文件有效 + return true; + } + + //检测是否是空操作 + static private function isEmptyAction($module,$action) { + $className = $module.'Action'; + $class = new $className; + return !method_exists($class,$action); + } + +} diff --git a/Library/Think/Behavior/ShowPageTrace.php b/Library/Think/Behavior/ShowPageTrace.php new file mode 100644 index 00000000..0fff7677 --- /dev/null +++ b/Library/Think/Behavior/ShowPageTrace.php @@ -0,0 +1,90 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Behavior; +use Think\Config; +use Think\Log; +use Think\Debug; + +/** + * 系统行为扩展:页面Trace显示输出 + * @category Think + * @package Think + * @subpackage Behavior + * @author liu21st + */ +class ShowPageTrace { + + // 行为扩展的执行入口必须是run + public function run(&$params){ + if(!IS_AJAX && Config::get('show_page_trace')) { + echo $this->showTrace(); + } + } + + /** + * 显示页面Trace信息 + * @access private + */ + private function showTrace() { + // 系统默认显示信息 + $files = get_included_files(); + $info = []; + foreach ($files as $key=>$file){ + $info[] = $file.' ( '.number_format(filesize($file)/1024,2).' KB )'; + } + $trace = []; + Debug::remark('START',$GLOBALS['startTime']); + $base = [ + '请求信息' => date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']).' '.$_SERVER['SERVER_PROTOCOL'].' '.$_SERVER['REQUEST_METHOD'].' : '.$_SERVER['PHP_SELF'], + '运行时间' => Debug::getUseTime('START','END',6).'s', + '内存开销' => MEMORY_LIMIT_ON?G('START','END','m').'b':'不支持', + '查询信息' => N('db_query').' queries '.N('db_write').' writes ', + '文件加载' => count($files), + '缓存信息' => N('cache_read').' gets '.N('cache_write').' writes ', + '配置加载' => count(Config::get()), + ]; + // 读取项目定义的Trace文件 + $traceFile = MODULE_PATH.'trace.php'; + if(is_file($traceFile)) { + $base = array_merge($base,include $traceFile); + } + $debug = Log::getLog(); + $tabs = Config::get('trace_page_tabs'); + foreach ($tabs as $name=>$title){ + switch(strtoupper($name)) { + case 'BASE':// 基本信息 + $trace[$title] = $base; + break; + case 'FILE': // 文件信息 + $trace[$title] = $info; + break; + default:// 调试信息 + $name = strtoupper($name); + if(strpos($name,'|')) {// 多组信息 + $array = explode('|',$name); + $result = []; + foreach($array as $name){ + $result += isset($debug[$name])?$debug[$name]:[]; + } + $trace[$title] = $result; + }else{ + $trace[$title] = isset($debug[$name])?$debug[$name]:''; + } + } + } + unset($files,$info,$base,$debug); + // 调用Trace页面模板 + ob_start(); + include Config::has('tmpl_trace_file')?Config::get('tmpl_trace_file'):THINK_PATH.'tpl/page_trace.tpl'; + return ob_get_clean(); + } +} diff --git a/Library/Think/Behavior/TokenBuild.php b/Library/Think/Behavior/TokenBuild.php new file mode 100644 index 00000000..11e71993 --- /dev/null +++ b/Library/Think/Behavior/TokenBuild.php @@ -0,0 +1,61 @@ + +// +---------------------------------------------------------------------- + +defined('THINK_PATH') or exit(); +/** + * 系统行为扩展:表单令牌生成 + * @category Think + * @package Think + * @subpackage Behavior + * @author liu21st + */ +class TokenBuildBehavior extends Behavior { + // 行为参数定义 + protected $options = [ + 'TOKEN_ON' => false, // 开启令牌验证 + 'TOKEN_NAME' => '__hash__', // 令牌验证的表单隐藏字段名称 + 'TOKEN_TYPE' => 'md5', // 令牌验证哈希规则 + 'TOKEN_RESET' => true, // 令牌错误后是否重置 + ]; + + public function run(&$content){ + if(C('TOKEN_ON')) { + if(strpos($content,'{__TOKEN__}')) { + // 指定表单令牌隐藏域位置 + $content = str_replace('{__TOKEN__}',$this->buildToken(),$content); + }elseif(preg_match('/<\/form(\s*)>/is',$content,$match)) { + // 智能生成表单令牌隐藏域 + $content = str_replace($match[0],$this->buildToken().$match[0],$content); + } + }else{ + $content = str_replace('{__TOKEN__}','',$content); + } + } + + // 创建表单令牌 + private function buildToken() { + $tokenName = C('TOKEN_NAME'); + $tokenType = C('TOKEN_TYPE'); + if(!isset($_SESSION[$tokenName])) { + $_SESSION[$tokenName] = []; + } + // 标识当前页面唯一性 + $tokenKey = md5($_SERVER['REQUEST_URI']); + if(isset($_SESSION[$tokenName][$tokenKey])) {// 相同页面不重复生成session + $tokenValue = $_SESSION[$tokenName][$tokenKey]; + }else{ + $tokenValue = $tokenType(microtime(TRUE)); + $_SESSION[$tokenName][$tokenKey] = $tokenValue; + } + $token = ''; + return $token; + } +} diff --git a/Library/Think/Cache.php b/Library/Think/Cache.php new file mode 100644 index 00000000..885f3800 --- /dev/null +++ b/Library/Think/Cache.php @@ -0,0 +1,38 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Cache { + /** + * 操作句柄 + * @var object + * @access protected + */ + static protected $handler = null; + + /** + * 连接缓存 + * @access public + * @param array $options 配置数组 + * @return object + */ + static public function connect($options=[]) { + $type = !empty($options['type'])?$options['type']:'File'; + $class = 'Think\\Cache\\Driver\\'.ucwords($type); + self::$handler = new $class($options); + return self::$handler; + } + + static public function __callStatic($method, $params){ + return call_user_func_array(array(self::$handler, $method), $params); + } +} diff --git a/Library/Think/Cache/Driver/Apc.php b/Library/Think/Cache/Driver/Apc.php new file mode 100644 index 00000000..aad5bd11 --- /dev/null +++ b/Library/Think/Cache/Driver/Apc.php @@ -0,0 +1,101 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Apc缓存驱动 + * @author liu21st + */ +class Apc { + + protected $options = [ + 'expire' => 0, + 'prefix' => '', + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if(!function_exists('apc_cache_info')) { + E('_NOT_SUPPERT_:Apc'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + return apc_fetch($this->options['prefix'].$name); + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value, $expire = null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $name = $this->options['prefix'].$name; + if($result = apc_store($name, $value, $expire)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = apc_fetch('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + apc_delete($key); + } + apc_store('__info__', $queue); + } + } + return $result; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return apc_delete($this->options['prefix'].$name); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return apc_clear_cache(); + } +} diff --git a/Library/Think/Cache/Driver/Db.php b/Library/Think/Cache/Driver/Db.php new file mode 100644 index 00000000..c2a02898 --- /dev/null +++ b/Library/Think/Cache/Driver/Db.php @@ -0,0 +1,146 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * 数据库方式缓存驱动 + * CREATE TABLE think_cache ( + * cachekey varchar(255) NOT NULL, + * expire int(11) NOT NULL, + * data blob, + * datacrc int(32), + * UNIQUE KEY `cachekey` (`cachekey`) + * ); + * @author liu21st + */ +class Db { + + protected $handler = null; + protected $options = [ + 'db' => '', + 'table' => '', + 'prefix' => '', + 'expire' => 0, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + $this->handler = \Think\Db::instance(); + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $name = $this->options['prefix'].addslashes($name); + $result = $this->handler->query('SELECT `data`,`datacrc` FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\' AND (`expire` =0 OR `expire`>'.time().') LIMIT 0,1'); + if(false !== $result ) { + $result = $result[0]; + $content = $result['data']; + if(function_exists('gzcompress')) { + //启用数据压缩 + $content = gzuncompress($content); + } + $content = unserialize($content); + return $content; + } + else { + return false; + } + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value,$expire=null) { + $data = serialize($value); + $name = $this->options['prefix'].addslashes($name); + if(function_exists('gzcompress')) { + //数据压缩 + $data = gzcompress($data,3); + } + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存 + $result = $this->handler->query('select `cachekey` from `'.$this->options['table'].'` where `cachekey`=\''.$name.'\' limit 0,1'); + if(!empty($result) ) { + //更新记录 + $result = $this->handler->execute('UPDATE '.$this->options['table'].' SET data=\''.$data.'\' ,expire='.$expire.' WHERE `cachekey`=\''.$name.'\''); + }else { + //新增记录 + $result = $this->handler->execute('INSERT INTO '.$this->options['table'].' (`cachekey`,`data`,`expire`) VALUES (\''.$name.'\',\''.$data.'\','.$expire.')'); + } + if($result) { + if($this->options['length']>0) { + // 记录缓存队列 + $result = $this->handler->query('SELECT `data`,`datacrc` FROM `'.$this->options['table'].'` WHERE `cachekey`=\'__info__\' AND `expire` =0 LIMIT 0,1'); + $queue = xcache_get('__info__'); + if(!$result) { + $this->handler->execute('INSERT INTO '.$this->options['table'].' (`cachekey`,`data`,`expire`) VALUES (\'__info__\',\'\',0)'); + $queue = []; + }else{ + $queue = unserialize($result[0]['data']); + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + $this->handler->execute('DELETE FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$key.'\''); + } + $this->handler->execute('UPDATE '.$this->options['table'].' SET data=\''.serialize($queue).'\' ,expire=0 WHERE `cachekey`=\'__info__\''); + xcache_set('__info__', $queue); + } + return true; + }else { + return false; + } + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + $name = $this->options['prefix'].addslashes($name); + return $this->handler->execute('DELETE FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\''); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return $this->handler->execute('TRUNCATE TABLE `'.$this->options['table'].'`'); + } + +} diff --git a/Library/Think/Cache/Driver/Eaccelerator.php b/Library/Think/Cache/Driver/Eaccelerator.php new file mode 100644 index 00000000..a0ec2795 --- /dev/null +++ b/Library/Think/Cache/Driver/Eaccelerator.php @@ -0,0 +1,101 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Eaccelerator缓存驱动 + * @author liu21st + */ +class Eaccelerator { + + protected $options = [ + 'prefix' => '', + 'expire' => 0, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + return eaccelerator_get($this->options['prefix'].$name); + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value, $expire = null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $name = $this->options['prefix'].$name; + eaccelerator_lock($name); + if(eaccelerator_put($name, $value, $expire)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = eaccelerator_get('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + eaccelerator_rm($key); + } + eaccelerator_put('__info__', $queue); + } + return true; + } + return false; + } + + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return eaccelerator_rm($this->options['prefix'].$name); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return ; + } +} diff --git a/Library/Think/Cache/Driver/File.php b/Library/Think/Cache/Driver/File.php new file mode 100644 index 00000000..285fb9b1 --- /dev/null +++ b/Library/Think/Cache/Driver/File.php @@ -0,0 +1,184 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * 文件类型缓存类 + * @author liu21st + */ +class File { + + protected $options = [ + 'expire' => 0, + 'cache_subdir' => false, + 'path_level' => 1, + 'prefix' => '', + 'length' => 0, + 'temp' => '', + 'data_compress' => false, + ]; + + /** + * 架构函数 + * @access public + */ + public function __construct($options=[]) { + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; + $this->init(); + } + + /** + * 初始化检查 + * @access private + * @return boolen + */ + private function init() { + // 创建项目缓存目录 + if (!is_dir($this->options['temp'])) { + if (! mkdir($this->options['temp'],0755)) + return false; + } + } + + /** + * 取得变量的存储文件名 + * @access private + * @param string $name 缓存变量名 + * @return string + */ + private function filename($name) { + $name = md5($name); + if($this->options['cache_subdir']) { + // 使用子目录 + $dir = ''; + $len = $this->options['path_level']; + for($i=0;$i<$len;$i++) { + $dir .= $name{$i}.'/'; + } + if(!is_dir($this->options['temp'].$dir)) { + mkdir($this->options['temp'].$dir,0755,true); + } + $filename = $dir.$this->options['prefix'].$name.'.php'; + }else{ + $filename = $this->options['prefix'].$name.'.php'; + } + return $this->options['temp'].$filename; + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $filename = $this->filename($name); + if (!is_file($filename)) { + return false; + } + $content = file_get_contents($filename); + if( false !== $content) { + $expire = (int)substr($content,8, 12); + if($expire != 0 && time() > filemtime($filename) + $expire) { + //缓存过期删除缓存文件 + unlink($filename); + return false; + } + $content = substr($content,20, -3); + if($this->options['data_compress'] && function_exists('gzcompress')) { + //启用数据压缩 + $content = gzuncompress($content); + } + $content = unserialize($content); + return $content; + } + else { + return false; + } + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param int $expire 有效时间 0为永久 + * @return boolen + */ + public function set($name,$value,$expire=null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $filename = $this->filename($name); + $data = serialize($value); + if($this->options['data_compress'] && function_exists('gzcompress')) { + //数据压缩 + $data = gzcompress($data,3); + } + $data = ""; + $result = file_put_contents($filename,$data); + if($result) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue_file = dirname($filename).'/__info__.php'; + $queue = unserialize(file_get_contents($queue_file)); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + unlink($this->filename($key)); + } + file_put_contents($queue_file, serialize($queue)); + } + clearstatcache(); + return true; + }else { + return false; + } + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return unlink($this->filename($name)); + } + + /** + * 清除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function clear() { + $path = $this->options['temp']; + if ( $dir = opendir( $path ) ) { + while ( $file = readdir( $dir ) ) { + $check = is_dir( $file ); + if ( !$check ) + unlink( $path . $file ); + } + closedir( $dir ); + return true; + } + } +} diff --git a/Library/Think/Cache/Driver/Memcache.php b/Library/Think/Cache/Driver/Memcache.php new file mode 100644 index 00000000..bd3b0a3f --- /dev/null +++ b/Library/Think/Cache/Driver/Memcache.php @@ -0,0 +1,113 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Memcache缓存驱动 + * @author liu21st + */ +class Memcache { + protected $handler = null; + protected $options = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'expire' => 0, + 'timeout' => false, + 'persistent' => false, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if ( !extension_loaded('memcache') ) { + E('_NOT_SUPPERT_:memcache'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + $func = $this->options['persistent'] ? 'pconnect' : 'connect'; + $this->handler = new \Memcache; + $options['timeout'] === false ? + $this->handler->$func($options['host'], $options['port']) : + $this->handler->$func($options['host'], $options['port'], $options['timeout']); + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + return $this->handler->get($this->options['prefix'].$name); + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value, $expire = null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $name = $this->options['prefix'].$name; + if($this->handler->set($name, $value, 0, $expire)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = $this->handler->get('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + $this->handler->delete($key); + } + $this->handler->set('__info__', $queue); + } + return true; + } + return false; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name, $ttl = false) { + $name = $this->options['prefix'].$name; + return $ttl === false ? + $this->handler->delete($name) : + $this->handler->delete($name, $ttl); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return $this->handler->flush(); + } +} diff --git a/Library/Think/Cache/Driver/Redis.php b/Library/Think/Cache/Driver/Redis.php new file mode 100644 index 00000000..e66affdf --- /dev/null +++ b/Library/Think/Cache/Driver/Redis.php @@ -0,0 +1,116 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Redis缓存驱动 + * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis + * @author 尘缘 <130775@qq.com> + */ +class Redis { + protected $handler = null; + protected $options = [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'timeout' => false, + 'expire' => 0, + 'persistent' => false, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if ( !extension_loaded('redis') ) { + E('_NOT_SUPPERT_:redis'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + $func = $options['persistent'] ? 'pconnect' : 'connect'; + $this->handler = new \Redis; + $options['timeout'] === false ? + $this->handler->$func($options['host'], $options['port']) : + $this->handler->$func($options['host'], $options['port'], $options['timeout']); + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + return $this->handler->get($this->options['prefix'].$name); + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value, $expire = null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $name = $this->options['prefix'].$name; + if(is_int($expire)) { + $result = $this->handler->setex($name, $expire, $value); + }else{ + $result = $this->handler->set($name, $value); + } + if($result && $this->options['length']>0) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = $this->handler->get('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + $this->handler->delete($key); + } + $this->handler->set('__info__', $queue); + } + } + return $result; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return $this->handler->delete($this->options['prefix'].$name); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return $this->handler->flushDB(); + } + +} diff --git a/Library/Think/Cache/Driver/Secache.php b/Library/Think/Cache/Driver/Secache.php new file mode 100644 index 00000000..88d4bec0 --- /dev/null +++ b/Library/Think/Cache/Driver/Secache.php @@ -0,0 +1,722 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Secache缓存驱动 + * @author liu21st + */ +class Secache { + + protected $handler = null; + protected $options = [ + 'project' => '', + 'temp' => '', + 'expire' => 0, + 'prefix' => '', + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; + $this->handler = new SecacheClient; + $this->handler->workat($this->options['temp'].$this->options['project']); + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $name = $this->options['prefix'].$name; + $key = md5($name); + $this->handler->fetch($key,$return); + return $return; + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value) { + $name = $this->options['prefix'].$name; + $key = md5($name); + if($result = $this->handler->store($key, $value)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = $this->handler->fetch(md5('__info__')); + if(!$queue) { + $queue = []; + } + if(false===array_search($key, $queue)) array_push($queue,$key); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + $this->handler->delete($key); + } + $this->handler->store(md5('__info__'), $queue); + } + } + return $result; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + $name = $this->options['prefix'].$name; + $key = md5($name); + return $this->handler->delete($key); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return $this->handler->_format(true); + } + +} + +if(!defined('SECACHE_SIZE')){ + define('SECACHE_SIZE','15M'); +} +class SecacheClient{ + + var $idx_node_size = 40; + var $data_base_pos = 262588; //40+20+24*16+16*16*16*16*4; + var $schema_item_size = 24; + var $header_padding = 20; //保留空间 放置php标记防止下载 + var $info_size = 20; //保留空间 4+16 maxsize|ver + + //40起 添加20字节保留区域 + var $idx_seq_pos = 40; //id 计数器节点地址 + var $dfile_cur_pos = 44; //id 计数器节点地址 + var $idx_free_pos = 48; //id 空闲链表入口地址 + + var $idx_base_pos = 444; //40+20+24*16 + var $min_size = 10240; //10M最小值 + var $schema_struct = array('size','free','lru_head','lru_tail','hits','miss'); + var $ver = '$Rev: 3 $'; + var $name = '系统默认缓存(文件型)'; + + function workat($file){ + + $this->_file = $file.'.php'; + $this->_bsize_list = array( + 512=>10, + 3<<10=>10, + 8<<10=>10, + 20<<10=>4, + 30<<10=>2, + 50<<10=>2, + 80<<10=>2, + 96<<10=>2, + 128<<10=>2, + 224<<10=>2, + 256<<10=>2, + 512<<10=>1, + 1024<<10=>1, + ); + + $this->_node_struct = array( + 'next'=>array(0,'V'), + 'prev'=>array(4,'V'), + 'data'=>array(8,'V'), + 'size'=>array(12,'V'), + 'lru_right'=>array(16,'V'), + 'lru_left'=>array(20,'V'), + 'key'=>array(24,'H*'), + ); + + if(!file_exists($this->_file)){ + $this->create(); + }else{ + $this->_rs = fopen($this->_file,'rb+') or $this->trigger_error('Can\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR); + $this->_seek($this->header_padding); + $info = unpack('V1max_size/a*ver',fread($this->_rs,$this->info_size)); + if($info['ver']!=$this->ver){ + $this->_format(true); + }else{ + $this->max_size = $info['max_size']; + } + } + + $this->idx_node_base = $this->data_base_pos+$this->max_size; + $this->_block_size_list = array_keys($this->_bsize_list); + sort($this->_block_size_list); + return true; + } + + function create(){ + $this->_rs = fopen($this->_file,'wb+') or $this->trigger_error('Can\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR);; + fseek($this->_rs,0); + fputs($this->_rs,'<'.'?php exit()?'.'>'); + return $this->_format(); + } + + function _puts($offset,$data){ + if($offset < $this->max_size*1.5){ + $this->_seek($offset); + return fputs($this->_rs,$data); + }else{ + $this->trigger_error('Offset over quota:'.$offset,E_USER_ERROR); + } + } + + function _seek($offset){ + return fseek($this->_rs,$offset); + } + + function clear(){ + return $this->_format(true); + } + + function fetch($key,&$return){ + + if($this->lock(false)){ + $locked = true; + } + + if($this->search($key,$offset)){ + $info = $this->_get_node($offset); + $schema_id = $this->_get_size_schema_id($info['size']); + if($schema_id===false){ + if($locked) $this->unlock(); + return false; + } + + $this->_seek($info['data']); + $data = fread($this->_rs,$info['size']); + $return = unserialize($data); + + if($return===false){ + if($locked) $this->unlock(); + return false; + } + + if($locked){ + $this->_lru_push($schema_id,$info['offset']); + $this->_set_schema($schema_id,'hits',$this->_get_schema($schema_id,'hits')+1); + return $this->unlock(); + }else{ + return true; + } + }else{ + if($locked) $this->unlock(); + return false; + } + } + + /** + * lock + * 如果flock不管用,请继承本类,并重载此方法 + * + * @param mixed $is_block 是否阻塞 + * @access public + * @return void + */ + function lock($is_block,$whatever=false){ + return flock($this->_rs, $is_block?LOCK_EX:LOCK_EX+LOCK_NB); + } + + /** + * unlock + * 如果flock不管用,请继承本类,并重载此方法 + * + * @access public + * @return void + */ + function unlock(){ + return flock($this->_rs, LOCK_UN); + } + + function delete($key,$pos=false){ + if($pos || $this->search($key,$pos)){ + if($info = $this->_get_node($pos)){ + //删除data区域 + if($info['prev']){ + $this->_set_node($info['prev'],'next',$info['next']); + $this->_set_node($info['next'],'prev',$info['prev']); + }else{ //改入口位置 + $this->_set_node($info['next'],'prev',0); + $this->_set_node_root($key,$info['next']); + } + $this->_free_dspace($info['size'],$info['data']); + $this->_lru_delete($info); + $this->_free_node($pos); + return $info['prev']; + } + } + return false; + } + + function store($key,$value){ + + if($this->lock(true)){ + //save data + $data = serialize($value); + $size = strlen($data); + + //get list_idx + $has_key = $this->search($key,$list_idx_offset); + $schema_id = $this->_get_size_schema_id($size); + if($schema_id===false){ + $this->unlock(); + return false; + } + if($has_key){ + $hdseq = $list_idx_offset; + + $info = $this->_get_node($hdseq); + if($schema_id == $this->_get_size_schema_id($info['size'])){ + $dataoffset = $info['data']; + }else{ + //破掉原有lru + $this->_lru_delete($info); + if(!($dataoffset = $this->_dalloc($schema_id))){ + $this->unlock(); + return false; + } + $this->_free_dspace($info['size'],$info['data']); + $this->_set_node($hdseq,'lru_left',0); + $this->_set_node($hdseq,'lru_right',0); + } + + $this->_set_node($hdseq,'size',$size); + $this->_set_node($hdseq,'data',$dataoffset); + }else{ + + if(!($dataoffset = $this->_dalloc($schema_id))){ + $this->unlock(); + return false; + } + $hdseq = $this->_alloc_idx(array( + 'next'=>0, + 'prev'=>$list_idx_offset, + 'data'=>$dataoffset, + 'size'=>$size, + 'lru_right'=>0, + 'lru_left'=>0, + 'key'=>$key, + )); + + if($list_idx_offset>0){ + $this->_set_node($list_idx_offset,'next',$hdseq); + }else{ + $this->_set_node_root($key,$hdseq); + } + } + + if($dataoffset>$this->max_size){ + $this->trigger_error('alloc datasize:'.$dataoffset,E_USER_WARNING); + return false; + } + $this->_puts($dataoffset,$data); + + $this->_set_schema($schema_id,'miss',$this->_get_schema($schema_id,'miss')+1); + + $this->_lru_push($schema_id,$hdseq); + $this->unlock(); + return true; + }else{ + $this->trigger_error("Couldn't lock the file !",E_USER_WARNING); + return false; + } + + } + + /** + * search + * 查找指定的key + * 如果找到节点则$pos=节点本身 返回true + * 否则 $pos=树的末端 返回false + * + * @param mixed $key + * @access public + * @return void + */ + function search($key,&$pos){ + return $this->_get_pos_by_key($this->_get_node_root($key),$key,$pos); + } + + function _get_size_schema_id($size){ + foreach($this->_block_size_list as $k=>$block_size){ + if($size <= $block_size){ + return $k; + } + } + return false; + } + + function _parse_str_size($str_size,$default){ + if(preg_match('/^([0-9]+)\s*([gmk]|)$/i',$str_size,$match)){ + switch(strtolower($match[2])){ + case 'g': + if($match[1]>1){ + $this->trigger_error('Max cache size 1G',E_USER_ERROR); + } + $size = $match[1]<<30; + break; + case 'm': + $size = $match[1]<<20; + break; + case 'k': + $size = $match[1]<<10; + break; + default: + $size = $match[1]; + } + if($size<=0){ + $this->trigger_error('Error cache size '.$this->max_size,E_USER_ERROR); + return false; + }elseif($size<10485760){ + return 10485760; + }else{ + return $size; + } + }else{ + return $default; + } + } + + + function _format($truncate=false){ + if($this->lock(true,true)){ + + if($truncate){ + $this->_seek(0); + ftruncate($this->_rs,$this->idx_node_base); + } + + $this->max_size = $this->_parse_str_size(SECACHE_SIZE,15728640); //default:15m + $this->_puts($this->header_padding,pack('V1a*',$this->max_size,$this->ver)); + + ksort($this->_bsize_list); + $ds_offset = $this->data_base_pos; + $i=0; + foreach($this->_bsize_list as $size=>$count){ + + //将预分配的空间注册到free链表里 + $count *= min(3,floor($this->max_size/10485760)); + $next_free_node = 0; + for($j=0;$j<$count;$j++){ + $this->_puts($ds_offset,pack('V',$next_free_node)); + $next_free_node = $ds_offset; + $ds_offset+=intval($size); + } + + $code = pack(str_repeat('V1',count($this->schema_struct)),$size,$next_free_node,0,0,0,0); + + $this->_puts(60+$i*$this->schema_item_size,$code); + $i++; + } + $this->_set_dcur_pos($ds_offset); + + $this->_puts($this->idx_base_pos,str_repeat("\0",262144)); + $this->_puts($this->idx_seq_pos,pack('V',1)); + $this->unlock(); + return true; + }else{ + $this->trigger_error("Couldn't lock the file !",E_USER_ERROR); + return false; + } + } + + function _get_node_root($key){ + $this->_seek(hexdec(substr($key,0,4))*4+$this->idx_base_pos); + $a= fread($this->_rs,4); + list(,$offset) = unpack('V',$a); + return $offset; + } + + function _set_node_root($key,$value){ + return $this->_puts(hexdec(substr($key,0,4))*4+$this->idx_base_pos,pack('V',$value)); + } + + function _set_node($pos,$key,$value){ + + if(!$pos){ + return false; + } + + if(isset($this->_node_struct[$key])){ + return $this->_puts($pos*$this->idx_node_size+$this->idx_node_base+$this->_node_struct[$key][0],pack($this->_node_struct[$key][1],$value)); + }else{ + return false; + } + } + + function _get_pos_by_key($offset,$key,&$pos){ + if(!$offset){ + $pos = 0; + return false; + } + + $info = $this->_get_node($offset); + + if($info['key']==$key){ + $pos = $info['offset']; + return true; + }elseif($info['next'] && $info['next']!=$offset){ + return $this->_get_pos_by_key($info['next'],$key,$pos); + }else{ + $pos = $offset; + return false; + } + } + + function _lru_delete($info){ + + if($info['lru_right']){ + $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']); + }else{ + $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_tail',$info['lru_left']); + } + + if($info['lru_left']){ + $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']); + }else{ + $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_head',$info['lru_right']); + } + + return true; + } + + function _lru_push($schema_id,$offset){ + $lru_head = $this->_get_schema($schema_id,'lru_head'); + $lru_tail = $this->_get_schema($schema_id,'lru_tail'); + + if((!$offset) || ($lru_head==$offset))return; + + $info = $this->_get_node($offset); + + $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']); + $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']); + + $this->_set_node($offset,'lru_right',$lru_head); + $this->_set_node($offset,'lru_left',0); + + $this->_set_node($lru_head,'lru_left',$offset); + $this->_set_schema($schema_id,'lru_head',$offset); + + if($lru_tail==0){ + $this->_set_schema($schema_id,'lru_tail',$offset); + }elseif($lru_tail==$offset && $info['lru_left']){ + $this->_set_schema($schema_id,'lru_tail',$info['lru_left']); + } + return true; + } + + function _get_node($offset){ + $this->_seek($offset*$this->idx_node_size + $this->idx_node_base); + $info = unpack('V1next/V1prev/V1data/V1size/V1lru_right/V1lru_left/H*key',fread($this->_rs,$this->idx_node_size)); + $info['offset'] = $offset; + return $info; + } + + function _lru_pop($schema_id){ + if($node = $this->_get_schema($schema_id,'lru_tail')){ + $info = $this->_get_node($node); + if(!$info['data']){ + return false; + } + $this->delete($info['key'],$info['offset']); + if(!$this->_get_schema($schema_id,'free')){ + $this->trigger_error('pop lru,But nothing free...',E_USER_ERROR); + } + return $info; + }else{ + return false; + } + } + + function _dalloc($schema_id,$lru_freed=false){ + + if($free = $this->_get_schema($schema_id,'free')){ //如果lru里有链表 + $this->_seek($free); + list(,$next) = unpack('V',fread($this->_rs,4)); + $this->_set_schema($schema_id,'free',$next); + return $free; + }elseif($lru_freed){ + $this->trigger_error('Bat lru poped freesize',E_USER_ERROR); + return false; + }else{ + $ds_offset = $this->_get_dcur_pos(); + $size = $this->_get_schema($schema_id,'size'); + + if($size+$ds_offset > $this->max_size){ + if($info = $this->_lru_pop($schema_id)){ + return $this->_dalloc($schema_id,$info); + }else{ + $this->trigger_error('Can\'t alloc dataspace',E_USER_ERROR); + return false; + } + }else{ + $this->_set_dcur_pos($ds_offset+$size); + return $ds_offset; + } + } + } + + function _get_dcur_pos(){ + $this->_seek($this->dfile_cur_pos); + list(,$ds_offset) = unpack('V',fread($this->_rs,4)); + return $ds_offset; + } + function _set_dcur_pos($pos){ + return $this->_puts($this->dfile_cur_pos,pack('V',$pos)); + } + + function _free_dspace($size,$pos){ + + if($pos>$this->max_size){ + $this->trigger_error('free dspace over quota:'.$pos,E_USER_ERROR); + return false; + } + + $schema_id = $this->_get_size_schema_id($size); + if($free = $this->_get_schema($schema_id,'free')){ + $this->_puts($free,pack('V1',$pos)); + }else{ + $this->_set_schema($schema_id,'free',$pos); + } + $this->_puts($pos,pack('V1',0)); + } + + function _dfollow($pos,&$c){ + $c++; + $this->_seek($pos); + list(,$next) = unpack('V1',fread($this->_rs,4)); + if($next){ + return $this->_dfollow($next,$c); + }else{ + return $pos; + } + } + + function _free_node($pos){ + $this->_seek($this->idx_free_pos); + list(,$prev_free_node) = unpack('V',fread($this->_rs,4)); + $this->_puts($pos*$this->idx_node_size+$this->idx_node_base,pack('V',$prev_free_node).str_repeat("\0",$this->idx_node_size-4)); + return $this->_puts($this->idx_free_pos,pack('V',$pos)); + } + + function _alloc_idx($data){ + $this->_seek($this->idx_free_pos); + list(,$list_pos) = unpack('V',fread($this->_rs,4)); + if($list_pos){ + + $this->_seek($list_pos*$this->idx_node_size+$this->idx_node_base); + list(,$prev_free_node) = unpack('V',fread($this->_rs,4)); + $this->_puts($this->idx_free_pos,pack('V',$prev_free_node)); + + }else{ + $this->_seek($this->idx_seq_pos); + list(,$list_pos) = unpack('V',fread($this->_rs,4)); + $this->_puts($this->idx_seq_pos,pack('V',$list_pos+1)); + } + return $this->_create_node($list_pos,$data); + } + + function _create_node($pos,$data){ + $this->_puts($pos*$this->idx_node_size + $this->idx_node_base + ,pack('V1V1V1V1V1V1H*',$data['next'],$data['prev'],$data['data'],$data['size'],$data['lru_right'],$data['lru_left'],$data['key'])); + return $pos; + } + + function _set_schema($schema_id,$key,$value){ + $info = array_flip($this->schema_struct); + return $this->_puts(60+$schema_id*$this->schema_item_size + $info[$key]*4,pack('V',$value)); + } + + function _get_schema($id,$key){ + $info = array_flip($this->schema_struct); + + $this->_seek(60+$id*$this->schema_item_size); + unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size)); + + $this->_seek(60+$id*$this->schema_item_size + $info[$key]*4); + list(,$value) =unpack('V',fread($this->_rs,4)); + return $value; + } + + function _all_schemas(){ + $schema = []; + for($i=0;$i<16;$i++){ + $this->_seek(60+$i*$this->schema_item_size); + $info = unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size)); + if($info['size']){ + $info['id'] = $i; + $schema[$i] = $info; + }else{ + return $schema; + } + } + } + + function schemaStatus(){ + $return = []; + foreach($this->_all_schemas() as $k=>$schemaItem){ + if($schemaItem['free']){ + $this->_dfollow($schemaItem['free'],$schemaItem['freecount']); + } + $return[] = $schemaItem; + } + return $return; + } + + function status(&$curBytes,&$totalBytes){ + $totalBytes = $curBytes = 0; + $hits = $miss = 0; + + $schemaStatus = $this->schemaStatus(); + $totalBytes = $this->max_size; + $freeBytes = $this->max_size - $this->_get_dcur_pos(); + + foreach($schemaStatus as $schema){ + $freeBytes+=$schema['freecount']*$schema['size']; + $miss += $schema['miss']; + $hits += $schema['hits']; + } + $curBytes = $totalBytes-$freeBytes; + + $return[] = array('name'=>'缓存命中','value'=>$hits); + $return[] = array('name'=>'缓存未命中','value'=>$miss); + return $return; + } + + function trigger_error($errstr,$errno){ + trigger_error($errstr,$errno); + } + +} diff --git a/Library/Think/Cache/Driver/Simple.php b/Library/Think/Cache/Driver/Simple.php new file mode 100644 index 00000000..e6231d92 --- /dev/null +++ b/Library/Think/Cache/Driver/Simple.php @@ -0,0 +1,99 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * 文件类型缓存类 + * @author liu21st + */ +class Simple { + + protected $options = [ + 'prefix' => '', + 'temp' => '', + ]; + + /** + * 架构函数 + * @access public + */ + public function __construct($options=[]) { + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; + } + + /** + * 取得变量的存储文件名 + * @access private + * @param string $name 缓存变量名 + * @return string + */ + private function filename($name) { + return $this->options['temp'].$this->options['prefix'].md5($name).'.php'; + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $filename = $this->filename($name); + if (is_file($filename)) { + return include $filename; + }else{ + return false; + } + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param int $expire 有效时间 0为永久 + * @return boolen + */ + public function set($name,$value,$expire=null) { + $filename = $this->filename($name); + // 缓存数据 + $dir = dirname($filename); + // 目录不存在则创建 + //if (!is_dir($dir)) + // mkdir($dir,0755,true); + return file_put_contents($filename, ("")); + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return unlink($this->filename($name)); + } + + /** + * 清除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function clear() { + $filename = $this->filename('*'); + array_map("unlink", glob($filename)); + } +} diff --git a/Library/Think/Cache/Driver/Sqlite.php b/Library/Think/Cache/Driver/Sqlite.php new file mode 100644 index 00000000..d98da914 --- /dev/null +++ b/Library/Think/Cache/Driver/Sqlite.php @@ -0,0 +1,119 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Sqlite缓存驱动 + * @author liu21st + */ +class Sqlite { + + protected $options = [ + 'db' => ':memory:', + 'table' => 'sharedmemory', + 'prefix' => '', + 'expire' => 0, + 'length' => 0, + 'persistent' => false, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if ( !extension_loaded('sqlite') ) { + E('_NOT_SUPPERT_:sqlite'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + $func = $this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open'; + $this->handler = $func($this->options['db']); + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $name = $this->options['prefix'].sqlite_escape_string($name); + $sql = 'SELECT value FROM '.$this->options['table'].' WHERE var=\''.$name.'\' AND (expire=0 OR expire >'.time().') LIMIT 1'; + $result = sqlite_query($this->handler, $sql); + if (sqlite_num_rows($result)) { + $content = sqlite_fetch_single($result); + if(function_exists('gzcompress')) { + //启用数据压缩 + $content = gzuncompress($content); + } + return unserialize($content); + } + return false; + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value,$expire=null) { + $name = $this->options['prefix'].sqlite_escape_string($name); + $value = sqlite_escape_string(serialize($value)); + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存 + if(function_exists('gzcompress')) { + //数据压缩 + $value = gzcompress($value,3); + } + $sql = 'REPLACE INTO '.$this->options['table'].' (var, value,expire) VALUES (\''.$name.'\', \''.$value.'\', \''.$expire.'\')'; + if(sqlite_query($this->handler, $sql)){ + if($this->options['length']>0) { + // 记录缓存队列 + $this->queue($name); + } + return true; + } + return false; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + $name = $this->options['prefix'].sqlite_escape_string($name); + $sql = 'DELETE FROM '.$this->options['table'].' WHERE var=\''.$name.'\''; + sqlite_query($this->handler, $sql); + return true; + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + $sql = 'DELETE FROM '.$this->options['table']; + sqlite_query($this->handler, $sql); + return ; + } +} diff --git a/Library/Think/Cache/Driver/Wincache.php b/Library/Think/Cache/Driver/Wincache.php new file mode 100644 index 00000000..9b963f75 --- /dev/null +++ b/Library/Think/Cache/Driver/Wincache.php @@ -0,0 +1,103 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Wincache缓存驱动 + * @author liu21st + */ +class Wincache { + + protected $options = [ + 'prefix' => '', + 'expire' => 0, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if ( !function_exists('wincache_ucache_info') ) { + E('_NOT_SUPPERT_:WinCache'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $name = $this->options['prefix'].$name; + return wincache_ucache_exists($name)? wincache_ucache_get($name) : false; + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value,$expire=null) { + if(is_null($expire)) { + $expire = $this->options['expire']; + } + $name = $this->options['prefix'].$name; + if(wincache_ucache_set($name, $value, $expire)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = wincache_ucache_get('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + wincache_ucache_delete($key); + } + wincache_ucache_set('__info__', $queue); + } + return true; + } + return false; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return wincache_ucache_delete($this->options['prefix'].$name); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return ; + } +} diff --git a/Library/Think/Cache/Driver/Xcache.php b/Library/Think/Cache/Driver/Xcache.php new file mode 100644 index 00000000..ce4b37a8 --- /dev/null +++ b/Library/Think/Cache/Driver/Xcache.php @@ -0,0 +1,106 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Cache\Driver; + +/** + * Xcache缓存驱动 + * @author liu21st + */ +class Xcache { + + protected $options = [ + 'prefix' => '', + 'expire' => 0, + 'length' => 0, + ]; + + /** + * 架构函数 + * @param array $options 缓存参数 + * @access public + */ + public function __construct($options=[]) { + if ( !function_exists('xcache_info') ) { + E('_NOT_SUPPERT_:Xcache'); + } + if(!empty($options)) { + $this->options = array_merge($this->options,$options); + } + } + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public function get($name) { + $name = $this->options['prefix'].$name; + if (xcache_isset($name)) { + return xcache_get($name); + } + return false; + } + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param integer $expire 有效时间(秒) + * @return boolen + */ + public function set($name, $value,$expire=null) { + if(is_null($expire)) { + $expire = $this->options['expire'] ; + } + $name = $this->options['prefix'].$name; + if(xcache_set($name, $value, $expire)) { + if($this->options['length']>0) { + // 记录缓存队列 + $queue = xcache_get('__info__'); + if(!$queue) { + $queue = []; + } + if(false===array_search($name, $queue)) array_push($queue,$name); + if(count($queue) > $this->options['length']) { + // 出列 + $key = array_shift($queue); + // 删除缓存 + xcache_unset($key); + } + xcache_set('__info__', $queue); + } + return true; + } + return false; + } + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolen + */ + public function rm($name) { + return xcache_unset($this->options['prefix'].$name); + } + + /** + * 清除缓存 + * @access public + * @return boolen + */ + public function clear() { + return ; + } +} diff --git a/Library/Think/Config.php b/Library/Think/Config.php new file mode 100644 index 00000000..2b428abc --- /dev/null +++ b/Library/Think/Config.php @@ -0,0 +1,91 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Config { + static private $_config = []; // 配置参数 + static private $_range = '_sys_'; // 参数作用域 + + // 设定配置参数的作用域 + static public function range($range){ + self::$_range = $range; + } + + // 解析其他格式的配置参数 + static public function parse($config,$type='',$range=''){ + if(empty($type)) { + $type = substr(strrchr($config, '.'),1); + } + $class = '\Think\Config\Driver\\'.ucwords($type); + self::set((new $class())->parse($config),'',$range); + } + + // 加载配置文件 + static public function load($file,$range=''){ + return self::set(include $file,'',$range); + } + + // 检测配置是否存在 + static public function has($name,$range=''){ + $range = $range?$range:self::$_range; + $name = strtolower($name); + // 优先执行设置获取或赋值 + if (!strpos($name, '.')) { + return isset(self::$_config[$range][$name]); + } + // 二维数组设置和获取支持 + $name = explode('.', $name); + return isset(self::$_config[$range][$name[0]][$name[1]]); + } + + // 获取配置参数 为空则获取所有配置 + static public function get($name=null,$range='') { + $range = $range?$range:self::$_range; + // 无参数时获取所有 + if (empty($name)) { + return self::$_config[$range]; + } + $name = strtolower($name); + // 优先执行设置获取或赋值 + if (!strpos($name, '.')) { + return isset(self::$_config[$range][$name]) ? self::$_config[$range][$name] : null; + } + // 二维数组设置和获取支持 + $name = explode('.', $name); + return isset(self::$_config[$range][$name[0]][$name[1]]) ? self::$_config[$range][$name[0]][$name[1]] : null; + } + + // 设置配置参数 name为数组则为批量设置 + static public function set($name, $value=null,$range='') { + $range = $range?$range:self::$_range; + if(!isset(self::$_config[$range])) { + self::$_config[$range] = []; + } + if (is_string($name)) { + $name = strtolower($name); + if (!strpos($name, '.')) { + self::$_config[$range][$name] = $value; + return; + } + // 二维数组设置和获取支持 + $name = explode('.', $name); + self::$_config[$range][$name[0]][$name[1]] = $value; + return; + } + // 批量设置 + if (is_array($name)){ + self::$_config[$range] = array_merge(self::$_config[$range], array_change_key_case($name)); + return self::$_config[$range]; + } + return null; // 避免非法参数 + } +} diff --git a/Library/Think/Config/Driver/Ini.php b/Library/Think/Config/Driver/Ini.php new file mode 100644 index 00000000..398e631a --- /dev/null +++ b/Library/Think/Config/Driver/Ini.php @@ -0,0 +1,22 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Config\Driver; + +class Ini { + public function parse($config){ + if(is_file($config)) { + return parse_ini_file($config,true); + }else{ + return parse_ini_string($config,true); + } + } +} diff --git a/Library/Think/Config/Driver/Xml.php b/Library/Think/Config/Driver/Xml.php new file mode 100644 index 00000000..e19e3e48 --- /dev/null +++ b/Library/Think/Config/Driver/Xml.php @@ -0,0 +1,29 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Config\Driver; + +class Xml { + public function parse($config){ + if(is_file($config)) { + $content = simplexml_load_file($config); + }else{ + $content = simplexml_load_string($config); + } + $result = (array)$content; + foreach($result as $key=>$val){ + if(is_object($val)) { + $result[$key] = (array)$val; + } + } + return $result; + } +} diff --git a/Library/Think/Controller.php b/Library/Think/Controller.php new file mode 100644 index 00000000..87593b67 --- /dev/null +++ b/Library/Think/Controller.php @@ -0,0 +1,186 @@ + +// +---------------------------------------------------------------------- + +namespace Think; +use Think\View; + +class Controller { + // 视图类实例 + protected $view = null; + + /** + * 架构函数 初始化视图类 并采用内置模板引擎 + * @access public + */ + public function __construct(){ + // 模板引擎参数 + $config = [ + 'tpl_path' => MODULE_PATH . 'View/', + 'cache_path' => RUNTIME_PATH . 'Cache/', + ]; + $this->view = new View(); + $this->view->engine('think', $config); + + //控制器初始化 + if(method_exists($this, '_initialize')) + $this->_initialize(); + } + + /** + * 加载模板和页面输出 可以返回输出内容 + * @access public + * @param string $template 模板文件名 + * @param array $vars 模板输出变量 + * @param string $cache_id 模板缓存标识 + * @return mixed + */ + public function display($template = '', $vars = [], $cache_id = ''){ + $this->view->display($template, $vars, $cache_id); + } + + /** + * 渲染内容输出 + * @access public + * @param string $content 内容 + * @param array $vars 模板输出变量 + * @return mixed + */ + public function show($content, $vars = []){ + $this->view->http('http_render_content', true)->display($content, $vars); + } + + /** + * 模板变量赋值 + * @access protected + * @param mixed $name 要显示的模板变量 + * @param mixed $value 变量的值 + * @return void + */ + public function assign($name, $value = ''){ + $this->view->assign($name, $value); + } + + public function __set($name, $value){ + return $this->assign($name, $value); + } + + /** + * Ajax方式返回数据到客户端 + * @access protected + * @param mixed $data 要返回的数据 + * @param String $type AJAX返回数据格式 + * @return void + */ + protected function ajaxReturn($data, $type='') { + if(empty($type)) $type = C('default_ajax_return'); + switch (strtoupper($type)){ + case 'JSON': + // 返回JSON数据格式到客户端 包含状态信息 + header('Content-Type:application/json; charset=utf-8'); + exit(Think\Transform::jsonEncode($data)); + case 'XML': + // 返回xml格式数据 + header('Content-Type:text/xml; charset=utf-8'); + exit(Think\Transform::xmlEncode($data)); + case 'JSONP': + // 返回JSON数据格式到客户端 包含状态信息 + header('Content-Type:application/javascript; charset=utf-8'); + $handler = isset($_GET[C('var_jsonp_handler')]) ? $_GET[C('var_jsonp_handler')] : C('default_jsonp_handler'); + exit($handler . '(' . Think\Transform::jsonEncode($data) . ');'); + case 'SCRIPT': + // 返回可执行的js脚本 + header('Content-Type:application/javascript; charset=utf-8'); + exit($data); + case 'HTML': + // 返回html片段 + header('Content-Type:text/html; charset=utf-8'); + echo $data; + exit; + case 'TEXT': + // 返回一段纯文本 + header('Content-Type:text/plain; charset=utf-8'); + echo $data; + exit; + default: + // 用于扩展其他返回格式数据 + Tag::listen('ajax_return', $data); + } + } + + /** + * 操作错误跳转的快捷方法 + * @access protected + * @param string $message 错误信息 + * @param string $jumpUrl 页面跳转地址 + * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 + * @return void + */ + protected function error($message, $jumpUrl = '', $ajax = false) { + $this->dispatchJump($message, 0, $jumpUrl, $ajax); + } + + /** + * 操作成功跳转的快捷方法 + * @access protected + * @param string $message 提示信息 + * @param string $jumpUrl 页面跳转地址 + * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 + * @return void + */ + protected function success($message, $jumpUrl = '', $ajax = false) { + $this->dispatchJump($message, 1, $jumpUrl, $ajax); + } + + /** + * 默认跳转操作 支持错误导向和正确跳转 + * 调用模板显示 默认为public目录下面的success页面 + * 提示页面为可配置 支持模板标签 + * @access private + * @param string $message 提示信息 + * @param Boolean $status 状态 + * @param string $jumpUrl 页面跳转地址 + * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 + * @return void + */ + private function dispatchJump($message, $status = 1, $jumpUrl = '', $ajax = false) { + if(true === $ajax || IS_AJAX) {// AJAX提交 + $data = is_array($ajax) ? $ajax : []; + $data['info'] = $message; + $data['status'] = $status; + $data['url'] = $jumpUrl; + $this->ajaxReturn($data); + } + if(is_int($ajax)) $this->view->assign('waitSecond', $ajax); + if(!empty($jumpUrl)) $this->view->assign('jumpUrl', $jumpUrl); + // 提示标题 + $this->view->assign('msgTitle', $status ? L('_OPERATION_SUCCESS_') : L('_OPERATION_FAIL_')); + $this->view->assign('status', $status); // 状态 + //保证输出不受静态缓存影响 + C('HTML_CACHE_ON',false); + if($status) { //发送成功信息 + $this->view->assign('message', $message);// 提示信息 + // 成功操作后默认停留1秒 + $this->view->assign('waitSecond', '1'); + // 默认操作成功自动返回操作前页面 + if(!$jumpUrl) $this->view->assign("jumpUrl", $_SERVER["HTTP_REFERER"]); + $this->display(C('success_tmpl')); + }else{ + $this->view->assign('error', $message);// 提示信息 + //发生错误时候默认停留3秒 + $this->view->assign('waitSecond', '3'); + // 默认发生错误的话自动返回上页 + if(!$jumpUrl) $this->view->assign('jumpUrl', 'javascript:history.back(-1);'); + $this->display(C('error_tmpl')); + // 中止执行 避免出错后继续执行 + exit ; + } + } +} diff --git a/Library/Think/Controller/Amf.php b/Library/Think/Controller/Amf.php new file mode 100644 index 00000000..b4b9a6e8 --- /dev/null +++ b/Library/Think/Controller/Amf.php @@ -0,0 +1,29 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Controller; +abstract class Amf { + + /** + * PHPRpc控制器架构函数 + * @access public + */ + public function __construct() { + //导入类库 + Think\Loader::import('Vendor.Zend.Amf.Server'); + //实例化AMF + $server = new \Zend_Amf_Server(); + $server -> setClass($this); + echo $server -> handle(); + return ; + } + +} diff --git a/Library/Think/Controller/Phprpc.php b/Library/Think/Controller/Phprpc.php new file mode 100644 index 00000000..f4274e06 --- /dev/null +++ b/Library/Think/Controller/Phprpc.php @@ -0,0 +1,34 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Controller; + +abstract class Phprpc { + /** + * PHPRpc控制器架构函数 + * @access public + */ + public function __construct() { + //导入类库 + Think\Loader::import('Vendor.phpRPC.phprpc_server'); + //实例化phprpc + $server = new \PHPRPC_Server(); + $server->add($this); + if(APP_DEBUG) { + $server->setDebugMode(true); + } + $server->setEnableGZIP(true); + $server->start(); + //C('PHPRPC_COMMENT',$server->comment()); + echo $server->comment(); + } + +} diff --git a/Library/Think/Controller/Rest.php b/Library/Think/Controller/Rest.php new file mode 100644 index 00000000..00d07d5c --- /dev/null +++ b/Library/Think/Controller/Rest.php @@ -0,0 +1,215 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Controller; + +abstract class Rest { + + protected $_method = ''; // 当前请求类型 + protected $_type = ''; // 当前资源类型 + // 输出类型 + protected $restMethodList = 'get|post|put|delete'; + protected $restDefaultMethod = 'get'; + protected $restTypeList = 'html|xml|json|rss'; + protected $restDefaultType = 'html'; + protected $restOutputType = [ // REST允许输出的资源类型列表 + 'xml' => 'application/xml', + 'json' => 'application/json', + 'html' => 'text/html', + ]; + + /** + * 架构函数 取得模板对象实例 + * @access public + */ + public function __construct() { + // 资源类型检测 + if(''==__EXT__) { // 自动检测资源类型 + $this->_type = $this->getAcceptType(); + }elseif(!preg_match('/\('.$this->restTypeList.')$/i',__EXT__)) { + // 资源类型非法 则用默认资源类型访问 + $this->_type = $this->restDefaultType; + }else{ + $this->_type = __EXT__; + } + // 请求方式检测 + $method = strtolower($_SERVER['REQUEST_METHOD']); + if(false === stripos($this->restMethodList,$method)) { + // 请求方式非法 则用默认请求方法 + $method = $this->restDefaultMethod; + } + $this->_method = $method; + } + + /** + * REST 调用 + * @access public + * @param string $method 方法名 + * @param array $args 参数 + * @return mixed + */ + public function _empty($method,$args) { + if(method_exists($this,$method.'_'.$this->_method.'_'.$this->_type)) { // RESTFul方法支持 + $fun = $method.'_'.$this->_method.'_'.$this->_type; + }elseif($this->_method == $this->restDefaultMethod && method_exists($this,$method.'_'.$this->_type) ){ + $fun = $method.'_'.$this->_type; + }elseif($this->_type == $this->restDefaultType && method_exists($this,$method.'_'.$this->_method) ){ + $fun = $method.'_'.$this->_method; + } + if(isset($fun)) { + $this->$fun(); + }else{ + // 抛出异常 + E(L('_ERROR_ACTION_:').ACTION_NAME); + } + } + + /** + * 设置页面输出的CONTENT_TYPE和编码 + * @access public + * @param string $type content_type 类型对应的扩展名 + * @param string $charset 页面输出编码 + * @return void + */ + public function setContentType($type, $charset='utf-8'){ + if(headers_sent()) return; + $type = strtolower($type); + if(isset($this->restOutputType[$type])) //过滤content_type + header('Content-Type: '.$this->restOutputType[$type].'; charset='.$charset); + } + + /** + * 输出返回数据 + * @access protected + * @param mixed $data 要返回的数据 + * @param String $type 返回类型 JSON XML + * @param integer $code HTTP状态 + * @return void + */ + protected function response($data,$type='',$code=200) { + $this->sendHttpStatus($code); + exit($this->encodeData($data,strtolower($type))); + } + + /** + * 编码数据 + * @access protected + * @param mixed $data 要返回的数据 + * @param String $type 返回类型 JSON XML + * @return void + */ + protected function encodeData($data,$type='') { + if(empty($data)) return ''; + if('json' == $type) { + // 返回JSON数据格式到客户端 包含状态信息 + $data = json_encode($data); + }elseif('xml' == $type){ + // 返回xml格式数据 + $data = xml_encode($data); + }elseif('php'==$type){ + $data = serialize($data); + }// 默认直接输出 + $this->setContentType($type); + header('Content-Length: ' . strlen($data)); + return $data; + } + + // 发送Http状态信息 + protected function sendHttpStatus($status) { + static $_status = [ + // Informational 1xx + 100 => 'Continue', + 101 => 'Switching Protocols', + // Success 2xx + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + // Redirection 3xx + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Moved Temporarily ', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + // 306 is deprecated but reserved + 307 => 'Temporary Redirect', + // Client Error 4xx + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + // Server Error 5xx + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded' + ]; + if(isset($_status[$code])) { + header('HTTP/1.1 '.$code.' '.$_status[$code]); + // 确保FastCGI模式下正常 + header('Status:'.$code.' '.$_status[$code]); + } + } + + /** + * 获取当前请求的Accept头信息 + * @return string + */ + protected function getAcceptType(){ + $type = [ + 'html' => 'text/html,application/xhtml+xml,*/*', + 'xml' => 'application/xml,text/xml,application/x-xml', + 'json' => 'application/json,text/x-json,application/jsonrequest,text/json', + 'js' => 'text/javascript,application/javascript,application/x-javascript', + 'css' => 'text/css', + 'rss' => 'application/rss+xml', + 'yaml' => 'application/x-yaml,text/yaml', + 'atom' => 'application/atom+xml', + 'pdf' => 'application/pdf', + 'text' => 'text/plain', + 'png' => 'image/png', + 'jpg' => 'image/jpg,image/jpeg,image/pjpeg', + 'gif' => 'image/gif', + 'csv' => 'text/csv' + ]; + + foreach($type as $key=>$val){ + $array = explode(',',$val); + foreach($array as $k=>$v){ + if(stristr($_SERVER['HTTP_ACCEPT'], $v)) { + return $key; + } + } + } + return false; + } +} diff --git a/Library/Think/Cookie.php b/Library/Think/Cookie.php new file mode 100644 index 00000000..7b679b50 --- /dev/null +++ b/Library/Think/Cookie.php @@ -0,0 +1,131 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Cookie { + + static protected $config = [ + 'prefix' => '', // cookie 名称前缀 + 'expire' => 0, // cookie 保存时间 + 'path' => '/', // cookie 保存路径 + 'domain' => '', // cookie 有效域名 + ]; + + /** + * Cookie初始化 + * @param array $config + * @return void + */ + static public function init($config=[]){ + self::$config = array_merge(self::$config, array_change_key_case($config)); + } + + /** + * 设置或者获取cookie作用域(前缀) + * @param string $prefix + * @return string|void + */ + static public function prefix($prefix=''){ + if(empty($prefix)) { + return self::$config['prefix']; + }else{ + self::$config['prefix'] = $prefix; + } + } + + /** + * Cookie 设置、获取、删除 + * @param string $name cookie名称 + * @param mixed $value cookie值 + * @param mixed $options cookie参数 + * @return mixed + */ + static public function set($name, $value='', $option=null) { + // 参数设置(会覆盖黙认设置) + if (!is_null($option)) { + if (is_numeric($option)) + $option = ['expire' => $option]; + elseif (is_string($option)) + parse_str($option, $option); + $config = array_merge(self::$config, array_change_key_case($option)); + }else{ + $config = self::$config; + } + $name = $config['prefix'] . $name; + // 设置cookie + if(is_array($value)){ + $value = 'think:'.json_encode(array_map('urlencode',$value)); + } + $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0; + setcookie($name, $value, $expire, $config['path'], $config['domain']); + $_COOKIE[$name] = $value; + } + + /** + * Cookie获取 + * @param string $name cookie名称 + * @param string $prefix cookie前缀 + * @return mixed + */ + static public function get($name, $prefix='') { + $prefix = $prefix?$prefix:self::$config['prefix']; + $name = $prefix . $name; + if(isset($_COOKIE[$name])){ + $value = $_COOKIE[$name]; + if(0===strpos($value,'think:')){ + $value = substr($value,6); + return array_map('urldecode',json_decode($value,true)); + }else{ + return $value; + } + }else{ + return null; + } + } + + /** + * Cookie删除 + * @param string $name cookie名称 + * @param string $prefix cookie前缀 + * @return mixed + */ + static public function delete($name, $prefix='') { + $prefix = $prefix?$prefix:self::$config['prefix']; + $name = $prefix . $name; + setcookie($name, '', time() - 3600, self::$config['path'], self::$config['domain']); + unset($_COOKIE[$name]); // 删除指定cookie + } + + /** + * Cookie清空 + * @param string $prefix cookie前缀 + * @return mixed + */ + static public function clear($prefix='') { + // 清除指定前缀的所有cookie + if (empty($_COOKIE)) + return; + // 要删除的cookie前缀,不指定则删除config设置的指定前缀 + $prefix = $prefix ? $prefix: self::$config['prefix']; + if ($prefix) {// 如果前缀为空字符串将不作处理直接返回 + foreach ($_COOKIE as $key => $val) { + if (0 === strpos($key, $prefix)) { + setcookie($key, '', time() - 3600, self::$config['path'], self::$config['domain']); + unset($_COOKIE[$key]); + } + } + }else{ + unset($_COOKIE); + } + return; + } +} diff --git a/Library/Think/Create.php b/Library/Think/Create.php new file mode 100644 index 00000000..9073181e --- /dev/null +++ b/Library/Think/Create.php @@ -0,0 +1,102 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Create { + static public function build($build) { + // 锁定 + $lockfile = APP_PATH.'create.lock'; + if(is_writable($lockfile)) { + return ; + } else { + if(!touch($lockfile)){ + header('Content-Type:text/html; charset=utf-8'); + exit('目录 [ '.APP_PATH.' ] 不可写!'); + } + } + foreach ($build as $module=>$list){ + if(!is_dir(APP_PATH.$module)) {// 创建模块目录 + mkdir(APP_PATH.$module); + } + // 创建配置文件和公共文件 + self::buildCommonFile($module); + // 创建欢迎页面 + self::buildHelloController($module); + + // 创建子目录和文件 + foreach($list as $path=>$file){ + if(is_int($path)) { + // 生成文件 + if(!is_file(APP_PATH.$module.'/'.$file)) { + file_put_contents(APP_PATH.$module.'/'.$file," +// +---------------------------------------------------------------------- + +namespace Think; + +class Crypt { + /** + * 加密字符串 + * @access public + * @param string $str 字符串 + * @param string $key 加密key + * @return string + */ + static public function encrypt($data,$key,$expire=0){ + $key = md5($key); + $data = base64_encode($data); + $x = 0; + $len = strlen($data); + $l = strlen($key); + $char = ''; + for ($i = 0; $i< $len; $i++) { + if ($x == $l) $x = 0; + $char .=substr($key, $x, 1); + $x++; + } + $str = sprintf('%010d', $expire ? $expire + time() : 0); + for ($i=0; $i< $len; $i++) { + $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256); + } + return str_replace('=', '', base64_encode($str)); + } + + /** + * 解密字符串 + * @access public + * @param string $str 字符串 + * @param string $key 加密key + * @return string + */ + static public function decrypt($data,$key){ + $key = md5($key); + $x = 0; + $data = base64_decode($data); + $expire = substr($data,0,10); + $data = substr($data,10); + if($expire > 0 && $expire +// +---------------------------------------------------------------------- + +namespace Think; + +/** + * ThinkPHP 数据库中间层实现类 + */ +class Db { + + static private $instance = []; // 数据库连接实例 + static private $_instance = null; // 当前数据库连接实例 + + /** + * 取得数据库类实例 + * @static + * @access public + * @param mixed $config 连接配置 + * @param boolean $lite 是否lite方式 + * @return Object 返回数据库驱动类 + */ + static public function instance($config=[],$lite=false) { + $md5 = md5(serialize($config)); + if(!isset(self::$instance[$md5])) { + // 解析连接参数 支持数组和字符串 + $options = self::parseConfig($config); + // 如果采用lite方式 仅支持原生SQL 包括query和execute方法 + $class = $lite? 'Think\Db\Lite' : 'Think\\Db\\Driver\\'.ucwords($options['type']); + self::$instance[$md5] = new $class($options); + } + self::$_instance = self::$instance[$md5]; + return self::$_instance; + } + + /** + * 数据库连接参数解析 + * @static + * @access private + * @param mixed $config + * @return array + */ + static private function parseConfig($config){ + if(empty($config)) { + $config = Config::get('database'); + } + if(is_string($config)) { + return self::parseDsn($config); + }else{ + return $config; + } + } + + /** + * DSN解析 + * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1¶m2=val2#utf8 + * @static + * @access private + * @param string $dsnStr + * @return array + */ + static private function parseDsn($dsnStr) { + if( empty($dsnStr) ){return false;} + $info = parse_url($dsnStr); + if(!$info) { + return false; + } + $dsn = [ + 'type' => $info['scheme'], + 'username' => isset($info['user']) ? $info['user'] : '', + 'password' => isset($info['pass']) ? $info['pass'] : '', + 'hostname' => isset($info['host']) ? $info['host'] : '', + 'hostport' => isset($info['port']) ? $info['port'] : '', + 'database' => isset($info['path']) ? substr($info['path'],1) : '', + 'charset' => isset($info['fragment'])?$info['fragment']:'utf8', + ]; + + if(isset($info['query'])) { + parse_str($info['query'],$dsn['params']); + }else{ + $dsn['params'] = []; + } + return $dsn; + } + + // 调用驱动类的方法 + static public function __callStatic($method, $params){ + return call_user_func_array(array(self::$_instance, $method), $params); + } +} diff --git a/Library/Think/Db/Driver.php b/Library/Think/Db/Driver.php new file mode 100644 index 00000000..f0082973 --- /dev/null +++ b/Library/Think/Db/Driver.php @@ -0,0 +1,1037 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db; +use Think\Config; +use Think\Debug; +use Think\Log; +use PDO; + +abstract class Driver { + // PDO操作实例 + protected $PDOStatement = null; + // 当前操作所属的模型名 + protected $model = '_think_'; + // 当前SQL指令 + protected $queryStr = ''; + protected $modelSql = []; + // 最后插入ID + protected $lastInsID = null; + // 返回或者影响记录数 + protected $numRows = 0; + // 事务指令数 + protected $transTimes = 0; + // 错误信息 + protected $error = ''; + // 数据库连接ID 支持多个连接 + protected $linkID = []; + // 当前连接ID + protected $_linkID = null; + // 数据库连接参数配置 + protected $config = [ + 'type' => '', // 数据库类型 + 'hostname' => '127.0.0.1', // 服务器地址 + 'database' => '', // 数据库名 + 'username' => '', // 用户名 + 'password' => '', // 密码 + 'hostport' => '', // 端口 + 'dsn' => '', // + 'params' => [], // 数据库连接参数 + 'charset' => 'utf8', // 数据库编码默认采用utf8 + 'prefix' => '', // 数据库表前缀 + 'debug' => false, // 数据库调试模式 + 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'rw_separate' => false, // 数据库读写是否分离 主从式有效 + 'master_num' => 1, // 读写分离后 主服务器数量 + 'slave_no' => '', // 指定从服务器序号 + ]; + // 数据库表达式 + protected $comparison = ['eq'=>'=','neq'=>'<>','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE','in'=>'IN','notin'=>'NOT IN']; + // 查询表达式 + protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%'; + // 查询次数 + protected $queryTimes = 0; + // 执行次数 + protected $executeTimes = 0; + // PDO连接参数 + protected $options = [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + ]; + protected $bind = []; // 参数绑定 + + /** + * 架构函数 读取数据库配置信息 + * @access public + * @param array $config 数据库配置数组 + */ + public function __construct($config=''){ + if(!empty($config)) { + $this->config = array_merge($this->config,$config); + $this->config['params'] = $this->options+$this->config['params']; + } + } + + /** + * 连接数据库方法 + * @access public + */ + public function connect($config='',$linkNum=0) { + if ( !isset($this->linkID[$linkNum]) ) { + if(empty($config)) $config = $this->config; + try{ + if(empty($config['dsn'])) { + $config['dsn'] = $this->parseDsn($config); + } + $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']); + }catch (\PDOException $e) { + E($e->getMessage()); + } + } + return $this->linkID[$linkNum]; + } + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){} + + /** + * 释放查询结果 + * @access public + */ + public function free() { + $this->PDOStatement = null; + } + + /** + * 执行查询 返回数据集 + * @access public + * @param string $str sql指令 + * @param array $bind 参数绑定 + * @return mixed + */ + public function query($str,$bind=[]) { + $this->initConnect(false); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + if(!empty($bind)){ + $this->queryStr .= '[ '.print_r($bind,true).' ]'; + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->queryTimes++; + // 调试开始 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) + E($this->error()); + foreach ($bind as $key => $val) { + if(is_array($val)){ + $this->PDOStatement->bindValue($key, $val[0], $val[1]); + }else{ + $this->PDOStatement->bindValue($key, $val); + } + } + $result = $this->PDOStatement->execute(); + // 调试结束 + $this->debug(false); + if ( false === $result ) { + $this->error(); + return false; + } else { + return $this->getResult(); + } + } + + /** + * 执行语句 + * @access public + * @param string $str sql指令 + * @param array $bind 参数绑定 + * @return integer + */ + public function execute($str,$bind=[]) { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + if(!empty($bind)){ + $this->queryStr .= '[ '.print_r($bind,true).' ]'; + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->executeTimes++; + // 记录开始执行时间 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) { + E($this->error()); + } + foreach ($bind as $key => $val) { + if(is_array($val)){ + $this->PDOStatement->bindValue($key, $val[0], $val[1]); + }else{ + $this->PDOStatement->bindValue($key, $val); + } + } + $result = $this->PDOStatement->execute(); + $this->debug(false); + if ( false === $result) { + $this->error(); + return false; + } else { + $this->numRows = $this->PDOStatement->rowCount(); + if(preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { + $this->lastInsID = $this->_linkID->lastInsertId(); + } + return $this->numRows; + } + } + + /** + * 启动事务 + * @access public + * @return void + */ + public function startTrans() { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + //数据rollback 支持 + if ($this->transTimes == 0) { + $this->_linkID->beginTransaction(); + } + $this->transTimes++; + return ; + } + + /** + * 用于非自动提交状态下面的查询提交 + * @access public + * @return boolen + */ + public function commit() { + if ($this->transTimes > 0) { + $result = $this->_linkID->commit(); + $this->transTimes = 0; + if(!$result){ + $this->error(); + return false; + } + } + return true; + } + + /** + * 事务回滚 + * @access public + * @return boolen + */ + public function rollback() { + if ($this->transTimes > 0) { + $result = $this->_linkID->rollback(); + $this->transTimes = 0; + if(!$result){ + $this->error(); + return false; + } + } + return true; + } + + /** + * 获得所有的查询数据 + * @access private + * @return array + */ + private function getResult() { + //返回数据集 + $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC); + $this->numRows = count( $result ); + return $result; + } + + /** + * 获得查询次数 + * @access public + * @param boolean $execute 是否包含所有查询 + * @return integer + */ + public function getQueryTimes($execute=false){ + return $execute?$this->queryTimes+$this->executeTimes:$this->queryTimes; + } + + /** + * 获得执行次数 + * @access public + * @return integer + */ + public function getExecuteTimes(){ + return $this->executeTimes; + } + + /** + * 关闭数据库 + * @access public + */ + public function close() { + $this->_linkID = null; + } + + /** + * 数据库错误信息 + * 并显示当前的SQL语句 + * @access public + * @return string + */ + public function error() { + if($this->PDOStatement) { + $error = $this->PDOStatement->errorInfo(); + $this->error = $error[1].':'.$error[2]; + }else{ + $this->error = ''; + } + if('' != $this->queryStr){ + $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; + } + // 记录错误日志 + Log::record($this->error,'ERR'); + if($this->config['debug']) {// 开启数据库调试模式 + E($this->error); + }else{ + return $this->error; + } + } + + /** + * 设置锁机制 + * @access protected + * @return string + */ + protected function parseLock($lock=false) { + return $lock? ' FOR UPDATE ' : ''; + } + + /** + * set分析 + * @access protected + * @param array $data + * @return string + */ + protected function parseSet($data) { + foreach ($data as $key=>$val){ + if(is_scalar($val)) {// 过滤非标量数据 + if(0===strpos($val,':')){ + $set[] = $this->parseKey($key).'='.$this->escapeString($val); + }else{ + $name = count($this->bind); + $set[] = $this->parseKey($key).'=:'.$name; + $this->bindParam($name,$val); + } + } + } + return ' SET '.implode(',',$set); + } + + /** + * 参数绑定 + * @access protected + * @param string $name 绑定参数名 + * @param mixed $value 绑定值 + * @return void + */ + protected function bindParam($name,$value){ + $this->bind[':'.$name] = $value; + } + + /** + * 字段名分析 + * @access protected + * @param string $key + * @return string + */ + protected function parseKey(&$key) { + return $key; + } + + /** + * value分析 + * @access protected + * @param mixed $value + * @return string + */ + protected function parseValue($value) { + if(is_string($value)) { + $value = strpos($value,':') === 0 ? $this->escapeString($value) : '\''.$this->escapeString($value).'\''; + }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){ + $value = $this->escapeString($value[1]); + }elseif(is_array($value)) { + $value = array_map([$this, 'parseValue'],$value); + }elseif(is_bool($value)){ + $value = $value ? '1' : '0'; + }elseif(is_null($value)){ + $value = 'null'; + } + return $value; + } + + /** + * field分析 + * @access protected + * @param mixed $fields + * @return string + */ + protected function parseField($fields) { + if(is_string($fields) && strpos($fields,',')) { + $fields = explode(',',$fields); + } + if(is_array($fields)) { + // 完善数组方式传字段名的支持 + // 支持 'field1'=>'field2' 这样的字段别名定义 + $array = []; + foreach ($fields as $key=>$field){ + if(!is_numeric($key)) + $array[] = $this->parseKey($key).' AS '.$this->parseKey($field); + else + $array[] = $this->parseKey($field); + } + $fieldsStr = implode(',', $array); + }elseif(is_string($fields) && !empty($fields)) { + $fieldsStr = $this->parseKey($fields); + }else{ + $fieldsStr = '*'; + } + //TODO 如果是查询全部字段,并且是join的方式,那么就把要查的表加个别名,以免字段被覆盖 + return $fieldsStr; + } + + /** + * table分析 + * @access protected + * @param mixed $table + * @return string + */ + protected function parseTable($tables) { + if(is_array($tables)) {// 支持别名定义 + $array = []; + foreach ($tables as $table=>$alias){ + if(!is_numeric($table)) + $array[] = $this->parseKey($table).' '.$this->parseKey($alias); + else + $array[] = $this->parseKey($alias); + } + $tables = $array; + }elseif(is_string($tables)){ + $tables = explode(',',$tables); + array_walk($tables, [&$this, 'parseKey']); + } + return implode(',',$tables); + } + + /** + * where分析 + * @access protected + * @param mixed $where + * @return string + */ + protected function parseWhere($where) { + $whereStr = ''; + if(is_string($where)) { + // 直接使用字符串条件 + $whereStr = $where; + }else{ // 使用数组表达式 + $operate = isset($where['_logic'])?strtoupper($where['_logic']):''; + if(in_array($operate,['AND','OR','XOR'])){ + // 定义逻辑运算规则 例如 OR XOR AND NOT + $operate = ' '.$operate.' '; + unset($where['_logic']); + }else{ + // 默认进行 AND 运算 + $operate = ' AND '; + } + foreach ($where as $key=>$val){ + $whereStr .= '( '; + if(0===strpos($key,'_')) { + // 解析特殊条件表达式 + $whereStr .= $this->parseThinkWhere($key,$val); + }else{ + // 查询字段的安全过滤 + if(!preg_match('/^[A-Z_\|\&\-.a-z0-9\(\)\,]+$/',trim($key))){ + E(L('_EXPRESS_ERROR_').':'.$key); + } + // 多条件支持 + $multi = is_array($val) && isset($val['_multi']); + $key = trim($key); + if(strpos($key,'|')) { // 支持 name|title|nickname 方式定义查询字段 + $array = explode('|',$key); + $str = []; + foreach ($array as $m=>$k){ + $v = $multi?$val[$m]:$val; + $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')'; + } + $whereStr .= implode(' OR ',$str); + }elseif(strpos($key,'&')){ + $array = explode('&',$key); + $str = []; + foreach ($array as $m=>$k){ + $v = $multi?$val[$m]:$val; + $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')'; + } + $whereStr .= implode(' AND ',$str); + }else{ + $whereStr .= $this->parseWhereItem($this->parseKey($key),$val); + } + } + $whereStr .= ' )'.$operate; + } + $whereStr = substr($whereStr,0,-strlen($operate)); + } + return empty($whereStr)?'':' WHERE '.$whereStr; + } + + // where子单元分析 + protected function parseWhereItem($key,$val) { + $whereStr = ''; + if(is_array($val)) { + if(is_string($val[0])) { + if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT)$/i',$val[0])) { // 比较运算 + $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]); + }elseif(preg_match('/^(NOTLIKE|LIKE)$/i',$val[0])){// 模糊查找 + if(is_array($val[1])) { + $likeLogic = isset($val[2])?strtoupper($val[2]):'OR'; + if(in_array($likeLogic,['AND','OR','XOR'])){ + $likeStr = $this->comparison[strtolower($val[0])]; + $like = []; + foreach ($val[1] as $item){ + $like[] = $key.' '.$likeStr.' '.$this->parseValue($item); + } + $whereStr .= '('.implode(' '.$likeLogic.' ',$like).')'; + } + }else{ + $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]); + } + }elseif('bind'==strtolower($val[0])){ // 使用表达式 + $whereStr .= ' ('.$key.' = :'.$val[1].') '; + }elseif('exp'==strtolower($val[0])){ // 使用表达式 + $whereStr .= ' ('.$key.' '.$val[1].') '; + }elseif(preg_match('/IN/i',$val[0])){ // IN 运算 + if(isset($val[2]) && 'exp'==$val[2]) { + $whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1]; + }else{ + if(is_string($val[1])) { + $val[1] = explode(',',$val[1]); + } + $zone = implode(',',$this->parseValue($val[1])); + $whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')'; + } + }elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算 + $data = is_string($val[1])? explode(',',$val[1]):$val[1]; + $whereStr .= ' ('.$key.' '.strtoupper($val[0]).' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]).' )'; + }else{ + E(L('_EXPRESS_ERROR_').':'.$val[0]); + } + }else { + $count = count($val); + $rule = isset($val[$count-1])?strtoupper($val[$count-1]):''; + if(in_array($rule,['AND','OR','XOR'])) { + $count = $count -1; + }else{ + $rule = 'AND'; + } + for($i=0;$i<$count;$i++) { + $data = is_array($val[$i])?$val[$i][1]:$val[$i]; + if('exp'==strtolower($val[$i][0])) { + $whereStr .= '('.$key.' '.$data.') '.$rule.' '; + }else{ + $op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:'='; + $whereStr .= '('.$key.' '.$op.' '.$this->parseValue($data).') '.$rule.' '; + } + } + $whereStr = substr($whereStr,0,-4); + } + }else { + //对字符串类型字段采用模糊匹配 + if($this->config['db_like_fields'] && preg_match('/('.$this->config['db_like_fields'].')/i',$key)) { + $val = '%'.$val.'%'; + $whereStr .= $key.' LIKE '.$this->parseValue($val); + }else { + $whereStr .= $key.' = '.$this->parseValue($val); + } + } + return $whereStr; + } + + /** + * 特殊条件分析 + * @access protected + * @param string $key + * @param mixed $val + * @return string + */ + protected function parseThinkWhere($key,$val) { + $whereStr = ''; + switch($key) { + case '_string': + // 字符串模式查询条件 + $whereStr = $val; + break; + case '_complex': + // 复合查询条件 + $whereStr = substr($this->parseWhere($val),6); + break; + case '_query': + // 字符串模式查询条件 + parse_str($val,$where); + if(isset($where['_logic'])) { + $op = ' '.strtoupper($where['_logic']).' '; + unset($where['_logic']); + }else{ + $op = ' AND '; + } + $array = []; + foreach ($where as $field=>$data) + $array[] = $this->parseKey($field).' = '.$this->parseValue($data); + $whereStr = implode($op,$array); + break; + } + return $whereStr; + } + + /** + * limit分析 + * @access protected + * @param mixed $lmit + * @return string + */ + protected function parseLimit($limit) { + return !empty($limit)? ' LIMIT '.$limit.' ':''; + } + + /** + * join分析 + * @access protected + * @param mixed $join + * @return string + */ + protected function parseJoin($join) { + $joinStr = ''; + if(!empty($join)) { + if(is_array($join)) { + foreach ($join as $key=>$_join){ + if(false !== stripos($_join,'JOIN')) + $joinStr .= ' '.$_join; + else + $joinStr .= ' LEFT JOIN ' .$_join; + } + }else{ + $joinStr .= ' LEFT JOIN ' .$join; + } + } + //将__TABLE_NAME__这样的字符串替换成正规的表名,并且带上前缀和后缀 + $joinStr = preg_replace("/__([A-Z_-]+)__/esU",$this->config['prefix'].".strtolower('$1')",$joinStr); + return $joinStr; + } + + /** + * order分析 + * @access protected + * @param mixed $order + * @return string + */ + protected function parseOrder($order) { + if(is_array($order)) { + $array = []; + foreach ($order as $key=>$val){ + if(is_numeric($key)) { + $array[] = $this->parseKey($val); + }else{ + $array[] = $this->parseKey($key).' '.$val; + } + } + $order = implode(',',$array); + } + return !empty($order)? ' ORDER BY '.$order:''; + } + + /** + * group分析 + * @access protected + * @param mixed $group + * @return string + */ + protected function parseGroup($group) { + return !empty($group)? ' GROUP BY '.$group:''; + } + + /** + * having分析 + * @access protected + * @param string $having + * @return string + */ + protected function parseHaving($having) { + return !empty($having)? ' HAVING '.$having:''; + } + + /** + * comment分析 + * @access protected + * @param string $comment + * @return string + */ + protected function parseComment($comment) { + return !empty($comment)? ' /* '.$comment.' */':''; + } + + /** + * distinct分析 + * @access protected + * @param mixed $distinct + * @return string + */ + protected function parseDistinct($distinct) { + return !empty($distinct)? ' DISTINCT ' :''; + } + + /** + * union分析 + * @access protected + * @param mixed $union + * @return string + */ + protected function parseUnion($union) { + if(empty($union)) return ''; + if(isset($union['_all'])) { + $str = 'UNION ALL '; + unset($union['_all']); + }else{ + $str = 'UNION '; + } + foreach ($union as $u){ + $sql[] = $str.(is_array($u)?$this->buildSelectSql($u):$u); + } + return implode(' ',$sql); + } + + /** + * 参数绑定分析 + * @access protected + * @param array $bind + * @return array + */ + protected function parseBind($bind){ + $bind = array_merge($this->bind,$bind); + $this->bind = []; + return $bind; + } + + /** + * 插入记录 + * @access public + * @param mixed $data 数据 + * @param array $options 参数表达式 + * @param boolean $replace 是否replace + * @return false | integer + */ + public function insert($data,$options=[],$replace=false) { + $values = $fields = []; + $this->model = $options['model']; + foreach ($data as $key=>$val){ + if(is_scalar($val)) { // 过滤非标量数据 + $fields[] = $this->parseKey($key); + if(0===strpos($val,':')){ + $values[] = $this->escapeString($val); + }else{ + $name = count($this->bind); + $values[] = ':'.$name; + $this->bindParam($name,$val); + } + } + } + $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')'; + $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false); + $sql .= $this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 通过Select方式插入记录 + * @access public + * @param string $fields 要插入的数据表字段名 + * @param string $table 要插入的数据表名 + * @param array $option 查询数据参数 + * @return false | integer + */ + public function selectInsert($fields,$table,$options=[]) { + $this->model = $options['model']; + if(is_string($fields)) $fields = explode(',',$fields); + array_walk($fields, [$this, 'parseKey']); + $sql = 'INSERT INTO '.$this->parseTable($table).' ('.implode(',', $fields).') '; + $sql .= $this->buildSelectSql($options); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 更新记录 + * @access public + * @param mixed $data 数据 + * @param array $options 表达式 + * @return false | integer + */ + public function update($data,$options) { + $this->model = $options['model']; + $sql = 'UPDATE ' + .$this->parseTable($options['table']) + .$this->parseSet($data) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseOrder(!empty($options['order'])?$options['order']:'') + .$this->parseLimit(!empty($options['limit'])?$options['limit']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 删除记录 + * @access public + * @param array $options 表达式 + * @return false | integer + */ + public function delete($options=[]) { + $this->model = $options['model']; + $sql = 'DELETE FROM ' + .$this->parseTable($options['table']) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseOrder(!empty($options['order'])?$options['order']:'') + .$this->parseLimit(!empty($options['limit'])?$options['limit']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 查找记录 + * @access public + * @param array $options 表达式 + * @return mixed + */ + public function select($options=[]) { + $this->model = $options['model']; + $sql = $this->buildSelectSql($options); + $cache = isset($options['cache'])?$options['cache']:false; + if($cache) { // 查询缓存检测 + $key = is_string($cache['key'])?$cache['key']:md5($sql); + $value = S($key,'',$cache); + if(false !== $value) { + return $value; + } + } + $result = $this->query($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + if($cache && false !== $result ) { // 查询缓存写入 + S($key,$result,$cache); + } + return $result; + } + + /** + * 生成查询SQL + * @access public + * @param array $options 表达式 + * @return string + */ + public function buildSelectSql($options=[]) { + if(isset($options['page'])) { + // 根据页数计算limit + if(strpos($options['page'],',')) { + list($page,$listRows) = explode(',',$options['page']); + }else{ + $page = $options['page']; + } + $page = $page?$page:1; + $listRows= isset($listRows)?$listRows:(is_numeric($options['limit'])?$options['limit']:20); + $offset = $listRows*((int)$page-1); + $options['limit'] = $offset.','.$listRows; + } + $sql = $this->parseSql($this->selectSql,$options); + $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false); + return $sql; + } + + /** + * 替换SQL语句中表达式 + * @access public + * @param array $options 表达式 + * @return string + */ + public function parseSql($sql,$options=[]){ + $sql = str_replace( + ['%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%COMMENT%'], + [ + $this->parseTable($options['table']), + $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false), + $this->parseField(!empty($options['field'])?$options['field']:'*'), + $this->parseJoin(!empty($options['join'])?$options['join']:''), + $this->parseWhere(!empty($options['where'])?$options['where']:''), + $this->parseGroup(!empty($options['group'])?$options['group']:''), + $this->parseHaving(!empty($options['having'])?$options['having']:''), + $this->parseOrder(!empty($options['order'])?$options['order']:''), + $this->parseLimit(!empty($options['limit'])?$options['limit']:''), + $this->parseUnion(!empty($options['union'])?$options['union']:''), + $this->parseComment(!empty($options['comment'])?$options['comment']:'') + ],$sql); + return $sql; + } + + /** + * 获取最近一次查询的sql语句 + * @param string $model 模型名 + * @access public + * @return string + */ + public function getLastSql($model='') { + return $model?$this->modelSql[$model]:$this->queryStr; + } + + /** + * 获取最近插入的ID + * @access public + * @return string + */ + public function getLastInsID() { + return $this->lastInsID; + } + + /** + * 获取最近的错误信息 + * @access public + * @return string + */ + public function getError() { + return $this->error; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL字符串 + * @return string + */ + public function escapeString($str) { + return addslashes($str); + } + + /** + * 设置当前操作模型 + * @access public + * @param string $model 模型名 + * @return void + */ + public function setModel($model){ + $this->model = $model; + } + + /** + * 数据库调试 记录当前SQL + * @access protected + * @param boolean $start 调试开始标记 true 开始 false 结束 + */ + protected function debug($start) { + if($this->config['debug']) {// 开启数据库调试模式 + if($start) { + Debug::remark('queryStartTime','time'); + }else{ + $this->modelSql[$this->model] = $this->queryStr; + //$this->model = '_think_'; + // 记录操作结束时间 + Debug::remark('queryEndTime','time'); + Log::record($this->queryStr.' [ RunTime:'.Debug::getUseTime('queryStartTime','queryEndTime').'s ]','SQL'); + } + } + } + + /** + * 初始化数据库连接 + * @access protected + * @param boolean $master 主服务器 + * @return void + */ + protected function initConnect($master=true) { + if(!empty($this->config['deploy'])) + // 采用分布式数据库 + $this->_linkID = $this->multiConnect($master); + else + // 默认单数据库 + if ( !$this->_linkID ) $this->_linkID = $this->connect(); + } + + /** + * 连接分布式服务器 + * @access protected + * @param boolean $master 主服务器 + * @return void + */ + protected function multiConnect($master=false) { + static $_config = []; + if(empty($_config)) { + // 缓存分布式数据库配置解析 + $_config['username'] = explode(',',$$this->config['username']); + $_config['password'] = explode(',',$$this->config['password']); + $_config['hostname'] = explode(',',$$this->config['hostname']); + $_config['hostport'] = explode(',',$$this->config['hostport']); + $_config['database'] = explode(',',$$this->config['database']); + $_config['dsn'] = explode(',',$$this->config['dsn']); + } + // 数据库读写是否分离 + if($this->config['rw_separate']){ + // 主从式采用读写分离 + if($master) + // 主服务器写入 + $r = floor(mt_rand(0,$this->config['master_num']-1)); + else{ + if(is_numeric($this->config['slave_no'])) {// 指定服务器读 + $r = $this->config['slave_no']; + }else{ + // 读操作连接从服务器 + $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 + } + } + }else{ + // 读写操作不区分服务器 + $r = floor(mt_rand(0,count($_config['hostname'])-1)); // 每次随机连接的数据库 + } + $db_config = [ + 'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0], + 'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0], + 'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0], + 'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0], + 'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0], + 'dsn' => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0], + ]; + return $this->connect($db_config,$r); + } + + /** + * 析构方法 + * @access public + */ + public function __destruct() { + // 释放查询 + if ($this->PDOStatement){ + $this->free(); + } + // 关闭连接 + $this->close(); + } +} diff --git a/Library/Think/Db/Driver/Mongo.php b/Library/Think/Db/Driver/Mongo.php new file mode 100644 index 00000000..e17cbf77 --- /dev/null +++ b/Library/Think/Db/Driver/Mongo.php @@ -0,0 +1,735 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Mongo数据库驱动 + */ +class Mongo extends Driver { + + protected $_mongo = null; // MongoDb Object + protected $_collection = null; // MongoCollection Object + protected $_dbName = ''; // dbName + protected $_collectionName = ''; // collectionName + protected $_cursor = null; // MongoCursor Object + protected $comparison = ['neq'=>'ne','ne'=>'ne','gt'=>'gt','egt'=>'gte','gte'=>'gte','lt'=>'lt','elt'=>'lte','lte'=>'lte','in'=>'in','not in'=>'nin','nin'=>'nin']; + + /** + * 架构函数 读取数据库配置信息 + * @access public + * @param array $config 数据库配置数组 + */ + public function __construct($config=''){ + if ( !class_exists('mongoClient') ) { + E(L('_NOT_SUPPERT_').':Mongo'); + } + if(!empty($config)) { + $this->config = array_merge($this->config,$config); + if(empty($this->config['params'])){ + $this->config['params'] = []; + } + } + } + + /** + * 连接数据库方法 + * @access public + */ + public function connect($config='',$linkNum=0) { + if ( !isset($this->linkID[$linkNum]) ) { + if(empty($config)) $config = $this->config['connection']; + $host = 'mongodb://'.($config['username']?"{$config['username']}":'').($config['password']?":{$config['password']}@":'').$config['hostname'].($config['hostport']?":{$config['hostport']}":'').'/'.($config['database']?"{$config['database']}":''); + try{ + $this->linkID[$linkNum] = new \mongoClient( $host,$this->config['params']); + }catch (\MongoConnectionException $e){ + E($e->getmessage()); + } + } + return $this->linkID[$linkNum]; + } + + /** + * 切换当前操作的Db和Collection + * @access public + * @param string $collection collection + * @param string $db db + * @param boolean $master 是否主服务器 + * @return void + */ + public function switchCollection($collection,$db='',$master=true){ + // 当前没有连接 则首先进行数据库连接 + if ( !$this->_linkID ) $this->initConnect($master); + try{ + if(!empty($db)) { // 传人Db则切换数据库 + // 当前MongoDb对象 + $this->_dbName = $db; + $this->_mongo = $this->_linkID->selectDb($db); + } + // 当前MongoCollection对象 + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.getCollection('.$collection.')'; + } + if($this->_collectionName != $collection) { + $this->queryTimes++; + $this->debug(true); + $this->_collection = $this->_mongo->selectCollection($collection); + $this->debug(false); + $this->_collectionName = $collection; // 记录当前Collection名称 + } + }catch (MongoException $e){ + E($e->getMessage()); + } + } + + /** + * 释放查询结果 + * @access public + */ + public function free() { + $this->_cursor = null; + } + + /** + * 执行命令 + * @access public + * @param array $command 指令 + * @return array + */ + public function command($command=[]) { + $this->executeTimes++; + $this->debug(true); + $this->queryStr = 'command:'.json_encode($command); + $result = $this->_mongo->command($command); + $this->debug(false); + if(!$result['ok']) { + E($result['errmsg']); + } + return $result; + } + + /** + * 执行语句 + * @access public + * @param string $code sql指令 + * @param array $args 参数 + * @return mixed + */ + public function execute($code,$args=[]) { + $this->executeTimes++; + $this->debug(true); + $this->queryStr = 'execute:'.$code; + $result = $this->_mongo->execute($code,$args); + $this->debug(false); + if($result['ok']) { + return $result['retval']; + }else{ + E($result['errmsg']); + } + } + + /** + * 关闭数据库 + * @access public + */ + public function close() { + if($this->_linkID) { + $this->_linkID->close(); + $this->_linkID = null; + $this->_mongo = null; + $this->_collection = null; + $this->_cursor = null; + } + } + + /** + * 数据库错误信息 + * @access public + * @return string + */ + public function error() { + $this->error = $this->_mongo->lastError(); + Log::record($this->error,'ERR'); + return $this->error; + } + + /** + * 插入记录 + * @access public + * @param mixed $data 数据 + * @param array $options 参数表达式 + * @param boolean $replace 是否replace + * @return false | integer + */ + public function insert($data,$options=[],$replace=false) { + if(isset($options['table'])) { + $this->switchCollection($options['table']); + } + $this->model = $options['model']; + $this->executeTimes++; + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.insert('; + $this->queryStr .= $data?json_encode($data):'{}'; + $this->queryStr .= ')'; + } + try{ + $this->debug(true); + $result = $replace? $this->_collection->save($data): $this->_collection->insert($data); + $this->debug(false); + if($result) { + $_id = $data['_id']; + if(is_object($_id)) { + $_id = $_id->__toString(); + } + $this->lastInsID = $_id; + } + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 插入多条记录 + * @access public + * @param array $dataList 数据 + * @param array $options 参数表达式 + * @return bool + */ + public function insertAll($dataList,$options=[]) { + if(isset($options['table'])) { + $this->switchCollection($options['table']); + } + $this->model = $options['model']; + $this->executeTimes++; + try{ + $this->debug(true); + $result = $this->_collection->batchInsert($dataList); + $this->debug(false); + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 生成下一条记录ID 用于自增非MongoId主键 + * @access public + * @param string $pk 主键名 + * @return integer + */ + public function getMongoNextId($pk) { + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find({},{'.$pk.':1}).sort({'.$pk.':-1}).limit(1)'; + } + try{ + $this->debug(true); + $result = $this->_collection->find([],[$pk=>1])->sort([$pk=>-1])->limit(1); + $this->debug(false); + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + $data = $result->getNext(); + return isset($data[$pk])?$data[$pk]+1:1; + } + + /** + * 更新记录 + * @access public + * @param mixed $data 数据 + * @param array $options 表达式 + * @return bool + */ + public function update($data,$options) { + if(isset($options['table'])) { + $this->switchCollection($options['table']); + } + $this->executeTimes++; + $this->model = $options['model']; + $query = $this->parseWhere($options['where']); + $set = $this->parseSet($data); + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.update('; + $this->queryStr .= $query?json_encode($query):'{}'; + $this->queryStr .= ','.json_encode($set).')'; + } + try{ + $this->debug(true); + if(isset($options['limit']) && $options['limit'] == 1) { + $multiple = ["multiple" => false]; + }else{ + $multiple = ["multiple" => true]; + } + $result = $this->_collection->update($query,$set,$multiple); + $this->debug(false); + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 删除记录 + * @access public + * @param array $options 表达式 + * @return false | integer + */ + public function delete($options=[]) { + if(isset($options['table'])) { + $this->switchCollection($options['table']); + } + $query = $this->parseWhere($options['where']); + $this->model = $options['model']; + $this->executeTimes++; + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove('.json_encode($query).')'; + } + try{ + $this->debug(true); + $result = $this->_collection->remove($query); + $this->debug(false); + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 清空记录 + * @access public + * @param array $options 表达式 + * @return false | integer + */ + public function clear($options=[]){ + if(isset($options['table'])) { + $this->switchCollection($options['table']); + } + $this->model = $options['model']; + $this->executeTimes++; + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove({})'; + } + try{ + $this->debug(true); + $result = $this->_collection->drop(); + $this->debug(false); + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 查找记录 + * @access public + * @param array $options 表达式 + * @return iterator + */ + public function select($options=[]) { + if(isset($options['table'])) { + $this->switchCollection($options['table'],'',false); + } + $cache = isset($options['cache'])?$options['cache']:false; + if($cache) { // 查询缓存检测 + $key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); + $value = S($key,'','',$cache['type']); + if(false !== $value) { + return $value; + } + } + $this->model = $options['model']; + $this->queryTimes++; + $query = $this->parseWhere($options['where']); + $field = $this->parseField($options['field']); + try{ + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find('; + $this->queryStr .= $query? json_encode($query):'{}'; + $this->queryStr .= $field? ','.json_encode($field):''; + $this->queryStr .= ')'; + } + $this->debug(true); + $_cursor = $this->_collection->find($query,$field); + if($options['order']) { + $order = $this->parseOrder($options['order']); + if($this->config['debug']) { + $this->queryStr .= '.sort('.json_encode($order).')'; + } + $_cursor = $_cursor->sort($order); + } + if(isset($options['page'])) { // 根据页数计算limit + if(strpos($options['page'],',')) { + list($page,$length) = explode(',',$options['page']); + }else{ + $page = $options['page']; + } + $page = $page?$page:1; + $length = isset($length)?$length:(is_numeric($options['limit'])?$options['limit']:20); + $offset = $length*((int)$page-1); + $options['limit'] = $offset.','.$length; + } + if(isset($options['limit'])) { + list($offset,$length) = $this->parseLimit($options['limit']); + if(!empty($offset)) { + if($this->config['debug']) { + $this->queryStr .= '.skip('.intval($offset).')'; + } + $_cursor = $_cursor->skip(intval($offset)); + } + if($this->config['debug']) { + $this->queryStr .= '.limit('.intval($length).')'; + } + $_cursor = $_cursor->limit(intval($length)); + } + $this->debug(false); + $this->_cursor = $_cursor; + $resultSet = iterator_to_array($_cursor); + if($cache && $resultSet ) { // 查询缓存写入 + S($key,$resultSet,$cache['expire'],$cache['type']); + } + return $resultSet; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 查找某个记录 + * @access public + * @param array $options 表达式 + * @return array + */ + public function find($options=[]){ + if(isset($options['table'])) { + $this->switchCollection($options['table'],'',false); + } + $cache = isset($options['cache'])?$options['cache']:false; + if($cache) { // 查询缓存检测 + $key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); + $value = S($key,'','',$cache['type']); + if(false !== $value) { + return $value; + } + } + $this->model = $options['model']; + $this->queryTimes++; + $query = $this->parseWhere($options['where']); + $fields = $this->parseField($options['field']); + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne('; + $this->queryStr .= $query?json_encode($query):'{}'; + $this->queryStr .= $fields?','.json_encode($fields):''; + $this->queryStr .= ')'; + } + try{ + $this->debug(true); + $result = $this->_collection->findOne($query,$fields); + $this->debug(false); + if($cache && $result ) { // 查询缓存写入 + S($key,$result,$cache['expire'],$cache['type']); + } + return $result; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + /** + * 统计记录数 + * @access public + * @param array $options 表达式 + * @return iterator + */ + public function count($options=[]){ + if(isset($options['table'])) { + $this->switchCollection($options['table'],'',false); + } + $this->model = $options['model']; + $this->queryTimes++; + $query = $this->parseWhere($options['where']); + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName; + $this->queryStr .= $query?'.find('.json_encode($query).')':''; + $this->queryStr .= '.count()'; + } + try{ + $this->debug(true); + $count = $this->_collection->count($query); + $this->debug(false); + return $count; + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + } + + public function group($keys,$initial,$reduce,$options=[]){ + $this->_collection->group($keys,$initial,$reduce,$options); + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($collection=''){ + if(!empty($collection) && $collection != $this->_collectionName) { + $this->switchCollection($collection,'',false); + } + $this->queryTimes++; + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne()'; + } + try{ + $this->debug(true); + $result = $this->_collection->findOne(); + $this->debug(false); + } catch (\MongoCursorException $e) { + E($e->getMessage()); + } + if($result) { // 存在数据则分析字段 + $info = []; + foreach ($result as $key=>$val){ + $info[$key] = [ + 'name' => $key, + 'type' => getType($val), + ]; + } + return $info; + } + // 暂时没有数据 返回false + return false; + } + + /** + * 取得当前数据库的collection信息 + * @access public + */ + public function getTables(){ + if($this->config['debug']) { + $this->queryStr = $this->_dbName.'.getCollenctionNames()'; + } + $this->queryTimes++; + $this->debug(true); + $list = $this->_mongo->listCollections(); + $this->debug(false); + $info = []; + foreach ($list as $collection){ + $info[] = $collection->getName(); + } + return $info; + } + + /** + * set分析 + * @access protected + * @param array $data + * @return string + */ + protected function parseSet($data) { + $result = []; + foreach ($data as $key=>$val){ + if(is_array($val)) { + switch($val[0]) { + case 'inc': + $result['$inc'][$key] = (int)$val[1]; + break; + case 'set': + case 'unset': + case 'push': + case 'pushall': + case 'addtoset': + case 'pop': + case 'pull': + case 'pullall': + $result['$'.$val[0]][$key] = $val[1]; + break; + default: + $result['$set'][$key] = $val; + } + }else{ + $result['$set'][$key] = $val; + } + } + return $result; + } + + /** + * order分析 + * @access protected + * @param mixed $order + * @return array + */ + protected function parseOrder($order) { + if(is_string($order)) { + $array = explode(',',$order); + $order = []; + foreach ($array as $key=>$val){ + $arr = explode(' ',trim($val)); + if(isset($arr[1])) { + $arr[1] = $arr[1]=='asc'?1:-1; + }else{ + $arr[1] = 1; + } + $order[$arr[0]] = $arr[1]; + } + } + return $order; + } + + /** + * limit分析 + * @access protected + * @param mixed $limit + * @return array + */ + protected function parseLimit($limit) { + if(strpos($limit,',')) { + $array = explode(',',$limit); + }else{ + $array = [0,$limit]; + } + return $array; + } + + /** + * field分析 + * @access protected + * @param mixed $fields + * @return array + */ + public function parseField($fields){ + if(empty($fields)) { + $fields = []; + } + if(is_string($fields)) { + $fields = explode(',',$fields); + } + return $fields; + } + + /** + * where分析 + * @access protected + * @param mixed $where + * @return array + */ + public function parseWhere($where){ + $query = []; + foreach ($where as $key=>$val){ + if('_id' != $key && 0===strpos($key,'_')) { + // 解析特殊条件表达式 + $query = $this->parseThinkWhere($key,$val); + }else{ + // 查询字段的安全过滤 + if(!preg_match('/^[A-Z_\|\&\-.a-z0-9]+$/',trim($key))){ + E(L('_ERROR_QUERY_').':'.$key); + } + $key = trim($key); + if(strpos($key,'|')) { + $array = explode('|',$key); + $str = []; + foreach ($array as $k){ + $str[] = $this->parseWhereItem($k,$val); + } + $query['$or'] = $str; + }elseif(strpos($key,'&')){ + $array = explode('&',$key); + $str = []; + foreach ($array as $k){ + $str[] = $this->parseWhereItem($k,$val); + } + $query = array_merge($query,$str); + }else{ + $str = $this->parseWhereItem($key,$val); + $query = array_merge($query,$str); + } + } + } + return $query; + } + + /** + * 特殊条件分析 + * @access protected + * @param string $key + * @param mixed $val + * @return string + */ + protected function parseThinkWhere($key,$val) { + $query = []; + switch($key) { + case '_query': // 字符串模式查询条件 + parse_str($val,$query); + if(isset($query['_logic']) && strtolower($query['_logic']) == 'or' ) { + unset($query['_logic']); + $query['$or'] = $query; + } + break; + case '_string':// MongoCode查询 + $query['$where'] = new \MongoCode($val); + break; + } + return $query; + } + + /** + * where子单元分析 + * @access protected + * @param string $key + * @param mixed $val + * @return array + */ + protected function parseWhereItem($key,$val) { + $query = []; + if(is_array($val)) { + if(is_string($val[0])) { + $con = strtolower($val[0]); + if(in_array($con,['neq','ne','gt','egt','gte','lt','lte','elt'])) { // 比较运算 + $k = '$'.$this->comparison[$con]; + $query[$key] = [$k=>$val[1]]; + }elseif('like'== $con){ // 模糊查询 采用正则方式 + $query[$key] = new \MongoRegex("/".$val[1]."/"); + }elseif('mod'==$con){ // mod 查询 + $query[$key] = ['$mod'=>$val[1]]; + }elseif('regex'==$con){ // 正则查询 + $query[$key] = new \MongoRegex($val[1]); + }elseif(in_array($con,['in','nin','not in'])){ // IN NIN 运算 + $data = is_string($val[1])? explode(',',$val[1]):$val[1]; + $k = '$'.$this->comparison[$con]; + $query[$key] = [$k=>$data]; + }elseif('all'==$con){ // 满足所有指定条件 + $data = is_string($val[1])? explode(',',$val[1]):$val[1]; + $query[$key] = ['$all'=>$data]; + }elseif('between'==$con){ // BETWEEN运算 + $data = is_string($val[1])? explode(',',$val[1]):$val[1]; + $query[$key] = ['$gte'=>$data[0],'$lte'=>$data[1]]; + }elseif('not between'==$con){ + $data = is_string($val[1])? explode(',',$val[1]):$val[1]; + $query[$key] = ['$lt'=>$data[0],'$gt'=>$data[1]]; + }elseif('exp'==$con){ // 表达式查询 + $query['$where'] = new \MongoCode($val[1]); + }elseif('exists'==$con){ // 字段是否存在 + $query[$key] =['$exists'=>(bool)$val[1]]; + }elseif('size'==$con){ // 限制属性大小 + $query[$key] =['$size'=>intval($val[1])]; + }elseif('type'==$con){ // 限制字段类型 1 浮点型 2 字符型 3 对象或者MongoDBRef 5 MongoBinData 7 MongoId 8 布尔型 9 MongoDate 10 NULL 15 MongoCode 16 32位整型 17 MongoTimestamp 18 MongoInt64 如果是数组的话判断元素的类型 + $query[$key] =['$type'=>intval($val[1])]; + }else{ + $query[$key] = $val; + } + return $query; + } + } + $query[$key] = $val; + return $query; + } +} diff --git a/Library/Think/Db/Driver/Mysql.php b/Library/Think/Db/Driver/Mysql.php new file mode 100644 index 00000000..b0d4008e --- /dev/null +++ b/Library/Think/Db/Driver/Mysql.php @@ -0,0 +1,92 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * mysql数据库驱动 + */ +class Mysql extends Driver{ + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'mysql:dbname='.$config['database'].';host='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ';port='.$config['hostport']; + }elseif(!empty($config['socket'])){ + $dsn .= ';unix_socket='.$config['socket']; + } + if(!empty($config['charset'])){ + $dsn .= ';charset='.$config['charset']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + */ + public function getFields($tableName) { + $this->initConnect(true); + list($tableName) = explode(' ', $tableName); + $sql = 'SHOW COLUMNS FROM `'.$tableName.'`'; + $result = $this->query($sql); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['key']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + */ + public function getTables($dbName='') { + $sql = !empty($dbName)?'SHOW TABLES FROM '.$dbName:'SHOW TABLES '; + $result = $this->query($sql); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * 字段和表名处理 + * @access protected + * @param string $key + * @return string + */ + protected function parseKey(&$key) { + $key = trim($key); + if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { + $key = '`'.$key.'`'; + } + return $key; + } + +} diff --git a/Library/Think/Db/Driver/Oracle.php b/Library/Think/Db/Driver/Oracle.php new file mode 100644 index 00000000..2dfbe41b --- /dev/null +++ b/Library/Think/Db/Driver/Oracle.php @@ -0,0 +1,153 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Oracle数据库驱动 + */ +class Oracle extends Driver{ + + private $table = ''; + protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%'; + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'oci:dbname='.$config['database']; + if(!empty($config['charset'])) { + $dsn .= ';charset='.$config['charset']; + } + return $dsn; + } + + /** + * 执行语句 + * @access public + * @param string $str sql指令 + * @return integer + */ + public function execute($str,$bind=[]) { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + if(!empty($bind)){ + $this->queryStr .= '[ '.print_r($bind,true).' ]'; + } + $flag = false; + if(preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $str, $match)) { + $this->table = C("DB_SEQUENCE_PREFIX").str_ireplace(C("DB_PREFIX"), "", $match[2]); + $flag = (boolean)$this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'"); + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->executeTimes++; + // 记录开始执行时间 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) { + E($this->error()); + } + $result = $this->PDOStatement->execute($bind); + $this->debug(false); + if ( false === $result) { + $this->error(); + return false; + } else { + $this->numRows = $this->PDOStatement->rowCount(); + if($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { + $this->lastInsID = $this->_linkID->lastInsertId(); + } + return $this->numRows; + } + } + + /** + * 取得数据表的字段信息 + * @access public + */ + public function getFields($tableName) { + list($tableName) = explode(' ', $tableName); + $result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_default,decode(a.column_name,b.column_name,1,0) pk " + ."from user_tab_columns a,(select column_name from user_constraints c,user_cons_columns col " + ."where c.constraint_name=col.constraint_name and c.constraint_type='P'and c.table_name='".strtoupper($tableName) + ."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)"); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[strtolower($val['column_name'])] = [ + 'name' => strtolower($val['column_name']), + 'type' => strtolower($val['data_type']), + 'notnull' => $val['notnull'], + 'default' => $val['data_default'], + 'primary' => $val['pk'], + 'autoinc' => $val['pk'], + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息(暂时实现取得用户表信息) + * @access public + */ + public function getTables($dbName='') { + $result = $this->query("select table_name from user_tables"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL指令 + * @return string + */ + public function escapeString($str) { + return str_ireplace("'", "''", $str); + } + + /** + * limit + * @access public + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) + $limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")"; + else + $limitStr = "(numrow>0 AND numrow<=".$limit[0].")"; + } + return $limitStr?' WHERE '.$limitStr:''; + } + + /** + * 设置锁机制 + * @access protected + * @return string + */ + protected function parseLock($lock=false) { + if(!$lock) return ''; + return ' FOR UPDATE NOWAIT '; + } +} diff --git a/Library/Think/Db/Driver/Pgsql.php b/Library/Think/Db/Driver/Pgsql.php new file mode 100644 index 00000000..266c4ca1 --- /dev/null +++ b/Library/Think/Db/Driver/Pgsql.php @@ -0,0 +1,91 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Pgsql数据库驱动 + */ +class Pgsql extends Driver{ + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'pgsql:dbname='.$config['database'].';host='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ';port='.$config['hostport']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + list($tableName) = explode(' ', $tableName); + $result = $this->query('select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg('.$tableName.');'); + $info = []; + if($result){ + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['key']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * limit分析 + * @access protected + * @param mixed $lmit + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) { + $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; + }else{ + $limitStr .= ' LIMIT '.$limit[0].' '; + } + } + return $limitStr; + } + +} diff --git a/Library/Think/Db/Driver/Sqlite.php b/Library/Think/Db/Driver/Sqlite.php new file mode 100644 index 00000000..dac545d7 --- /dev/null +++ b/Library/Think/Db/Driver/Sqlite.php @@ -0,0 +1,98 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Sqlite数据库驱动 + */ +class Sqlite extends Driver { + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'sqlite:'.$config['database']; + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + list($tableName) = explode(' ', $tableName); + $result = $this->query('PRAGMA table_info( '.$tableName.' )'); + $info = []; + if($result){ + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['dey']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("SELECT name FROM sqlite_master WHERE type='table' " + . "UNION ALL SELECT name FROM sqlite_temp_master " + . "WHERE type='table' ORDER BY name"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL指令 + * @return string + */ + public function escapeString($str) { + return str_ireplace("'", "''", $str); + } + + /** + * limit + * @access public + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) { + $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; + }else{ + $limitStr .= ' LIMIT '.$limit[0].' '; + } + } + return $limitStr; + } +} diff --git a/Library/Think/Db/Driver/Sqlsrv.php b/Library/Think/Db/Driver/Sqlsrv.php new file mode 100644 index 00000000..85666c2a --- /dev/null +++ b/Library/Think/Db/Driver/Sqlsrv.php @@ -0,0 +1,164 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; +use PDO; + +/** + * Sqlsrv数据库驱动 + */ +class Sqlsrv extends Driver{ + protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; + // PDO连接参数 + protected $options = [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, + ]; + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'sqlsrv:dbname='.$config['database'].';Server='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ','.$config['hostport']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + list($tableName) = explode(' ', $tableName); + $result = $this->query("SELECT column_name, data_type, column_default, is_nullable + FROM information_schema.tables AS t + JOIN information_schema.columns AS c + ON t.table_catalog = c.table_catalog + AND t.table_schema = c.table_schema + AND t.table_name = c.table_name + WHERE t.table_name = '$tableName'"); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[$val['column_name']] = [ + 'name' => $val['column_name'], + 'type' => $val['data_type'], + 'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes + 'default' => $val['column_default'], + 'primary' => false, + 'autoinc' => false, + ]; + } + } + return $info; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("SELECT TABLE_NAME + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_TYPE = 'BASE TABLE' + "); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * order分析 + * @access protected + * @param mixed $order + * @return string + */ + protected function parseOrder($order) { + return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()'; + } + + /** + * 字段名分析 + * @access protected + * @param string $key + * @return string + */ + protected function parseKey(&$key) { + $key = trim($key); + if(!preg_match('/[,\'\"\*\(\)\[.\s]/',$key)) { + $key = '['.$key.']'; + } + return $key; + } + + /** + * limit + * @access public + * @param mixed $limit + * @return string + */ + public function parseLimit($limit) { + if(empty($limit)) return ''; + $limit = explode(',',$limit); + if(count($limit)>1) + $limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')'; + else + $limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")"; + return 'WHERE '.$limitStr; + } + + /** + * 更新记录 + * @access public + * @param mixed $data 数据 + * @param array $options 表达式 + * @return false | integer + */ + public function update($data,$options) { + $this->model = $options['model']; + $sql = 'UPDATE ' + .$this->parseTable($options['table']) + .$this->parseSet($data) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 删除记录 + * @access public + * @param array $options 表达式 + * @return false | integer + */ + public function delete($options=[]) { + $this->model = $options['model']; + $sql = 'DELETE FROM ' + .$this->parseTable($options['table']) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + +} \ No newline at end of file diff --git a/Library/Think/Db/Lite.php b/Library/Think/Db/Lite.php new file mode 100644 index 00000000..76e7bad5 --- /dev/null +++ b/Library/Think/Db/Lite.php @@ -0,0 +1,449 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Db; +use Think\Config; +use Think\Debug; +use Think\Log; +use PDO; + +class Lite { + // PDO操作实例 + protected $PDOStatement = null; + // 当前操作所属的模型名 + protected $model = '_think_'; + // 当前SQL指令 + protected $queryStr = ''; + protected $modelSql = []; + // 最后插入ID + protected $lastInsID = null; + // 返回或者影响记录数 + protected $numRows = 0; + // 事务指令数 + protected $transTimes = 0; + // 错误信息 + protected $error = ''; + // 数据库连接ID 支持多个连接 + protected $linkID = []; + // 当前连接ID + protected $_linkID = null; + // 数据库连接参数配置 + protected $config = [ + 'type' => '', // 数据库类型 + 'hostname' => '127.0.0.1', // 服务器地址 + 'database' => '', // 数据库名 + 'username' => '', // 用户名 + 'password' => '', // 密码 + 'hostport' => '', // 端口 + 'dsn' => '', // + 'params' => [], // 数据库连接参数 + 'charset' => 'utf8', // 数据库编码默认采用utf8 + 'prefix' => '', // 数据库表前缀 + 'debug' => false, // 数据库调试模式 + 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'rw_separate' => false, // 数据库读写是否分离 主从式有效 + 'master_num' => 1, // 读写分离后 主服务器数量 + 'slave_no' => '', // 指定从服务器序号 + ]; + // 数据库表达式 + protected $comparison = ['eq'=>'=','neq'=>'<>','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE','in'=>'IN','notin'=>'NOT IN']; + // 查询表达式 + protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%'; + // 查询次数 + protected $queryTimes = 0; + // 执行次数 + protected $executeTimes = 0; + // PDO连接参数 + protected $options = [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + ]; + + /** + * 架构函数 读取数据库配置信息 + * @access public + * @param array $config 数据库配置数组 + */ + public function __construct($config=''){ + if(!empty($config)) { + $this->config = array_merge($this->config,$config); + $this->config['params'] = $this->options+$this->config['params']; + } + } + + /** + * 连接数据库方法 + * @access public + */ + public function connect($config='',$linkNum=0) { + if ( !isset($this->linkID[$linkNum]) ) { + if(empty($config)) $config = $this->config; + try{ + if(empty($config['dsn'])) { + E('Think/Db/Lite 必须设置 dsn参数'); + } + $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']); + }catch (\PDOException $e) { + E($e->getMessage()); + } + } + return $this->linkID[$linkNum]; + } + + /** + * 释放查询结果 + * @access public + */ + public function free() { + $this->PDOStatement = null; + } + + /** + * 执行查询 返回数据集 + * @access public + * @param string $str sql指令 + * @param array $bind 参数绑定 + * @return mixed + */ + public function query($str,$bind=[]) { + $this->initConnect(false); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + if(!empty($bind)){ + $this->queryStr .= '[ '.print_r($bind,true).' ]'; + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->queryTimes++; + // 调试开始 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) + E($this->error()); + foreach ($bind as $key => $val) { + if(is_array($val)){ + $this->PDOStatement->bindValue($key, $val[0], $val[1]); + }else{ + $this->PDOStatement->bindValue($key, $val); + } + } + $result = $this->PDOStatement->execute(); + // 调试结束 + $this->debug(false); + if ( false === $result ) { + $this->error(); + return false; + } else { + return $this->getResult(); + } + } + + /** + * 执行语句 + * @access public + * @param string $str sql指令 + * @param array $bind 参数绑定 + * @return integer + */ + public function execute($str,$bind=[]) { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + if(!empty($bind)){ + $this->queryStr .= '[ '.print_r($bind,true).' ]'; + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->executeTimes++; + // 记录开始执行时间 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) { + E($this->error()); + } + foreach ($bind as $key => $val) { + if(is_array($val)){ + $this->PDOStatement->bindValue($key, $val[0], $val[1]); + }else{ + $this->PDOStatement->bindValue($key, $val); + } + } + $result = $this->PDOStatement->execute(); + $this->debug(false); + if ( false === $result) { + $this->error(); + return false; + } else { + $this->numRows = $this->PDOStatement->rowCount(); + if(preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { + $this->lastInsID = $this->_linkID->lastInsertId(); + } + return $this->numRows; + } + } + + /** + * 启动事务 + * @access public + * @return void + */ + public function startTrans() { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + //数据rollback 支持 + if ($this->transTimes == 0) { + $this->_linkID->beginTransaction(); + } + $this->transTimes++; + return ; + } + + /** + * 用于非自动提交状态下面的查询提交 + * @access public + * @return boolen + */ + public function commit() { + if ($this->transTimes > 0) { + $result = $this->_linkID->commit(); + $this->transTimes = 0; + if(!$result){ + $this->error(); + return false; + } + } + return true; + } + + /** + * 事务回滚 + * @access public + * @return boolen + */ + public function rollback() { + if ($this->transTimes > 0) { + $result = $this->_linkID->rollback(); + $this->transTimes = 0; + if(!$result){ + $this->error(); + return false; + } + } + return true; + } + + /** + * 获得所有的查询数据 + * @access private + * @return array + */ + private function getResult() { + //返回数据集 + $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC); + $this->numRows = count( $result ); + return $result; + } + + /** + * 获得查询次数 + * @access public + * @param boolean $execute 是否包含所有查询 + * @return integer + */ + public function getQueryTimes($execute=false){ + return $execute?$this->queryTimes+$this->executeTimes:$this->queryTimes; + } + + /** + * 获得执行次数 + * @access public + * @return integer + */ + public function getExecuteTimes(){ + return $this->executeTimes; + } + + /** + * 关闭数据库 + * @access public + */ + public function close() { + $this->_linkID = null; + } + + /** + * 数据库错误信息 + * 并显示当前的SQL语句 + * @access public + * @return string + */ + public function error() { + if($this->PDOStatement) { + $error = $this->PDOStatement->errorInfo(); + $this->error = $error[1].':'.$error[2]; + }else{ + $this->error = ''; + } + if('' != $this->queryStr){ + $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; + } + // 记录错误日志 + Log::record($this->error,'ERR'); + if($this->config['debug']) {// 开启数据库调试模式 + E($this->error); + }else{ + return $this->error; + } + } + + /** + * 获取最近一次查询的sql语句 + * @param string $model 模型名 + * @access public + * @return string + */ + public function getLastSql($model='') { + return $model?$this->modelSql[$model]:$this->queryStr; + } + + /** + * 获取最近插入的ID + * @access public + * @return string + */ + public function getLastInsID() { + return $this->lastInsID; + } + + /** + * 获取最近的错误信息 + * @access public + * @return string + */ + public function getError() { + return $this->error; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL字符串 + * @return string + */ + public function escapeString($str) { + return addslashes($str); + } + + /** + * 设置当前操作模型 + * @access public + * @param string $model 模型名 + * @return void + */ + public function setModel($model){ + $this->model = $model; + } + + /** + * 数据库调试 记录当前SQL + * @access protected + * @param boolean $start 调试开始标记 true 开始 false 结束 + */ + protected function debug($start) { + if($this->config['debug']) {// 开启数据库调试模式 + if($start) { + Debug::remark('queryStartTime','time'); + }else{ + $this->modelSql[$this->model] = $this->queryStr; + //$this->model = '_think_'; + // 记录操作结束时间 + Debug::remark('queryEndTime','time'); + Log::record($this->queryStr.' [ RunTime:'.Debug::getUseTime('queryStartTime','queryEndTime').'s ]','SQL'); + } + } + } + + /** + * 初始化数据库连接 + * @access protected + * @param boolean $master 主服务器 + * @return void + */ + protected function initConnect($master=true) { + if(!empty($this->config['deploy'])) + // 采用分布式数据库 + $this->_linkID = $this->multiConnect($master); + else + // 默认单数据库 + if ( !$this->_linkID ) $this->_linkID = $this->connect(); + } + + /** + * 连接分布式服务器 + * @access protected + * @param boolean $master 主服务器 + * @return void + */ + protected function multiConnect($master=false) { + static $_config = []; + if(empty($_config)) { + // 缓存分布式数据库配置解析 + $_config['username'] = explode(',',$$this->config['username']); + $_config['password'] = explode(',',$$this->config['password']); + $_config['hostname'] = explode(',',$$this->config['hostname']); + $_config['hostport'] = explode(',',$$this->config['hostport']); + $_config['database'] = explode(',',$$this->config['database']); + $_config['dsn'] = explode(',',$$this->config['dsn']); + } + // 数据库读写是否分离 + if($this->config['rw_separate']){ + // 主从式采用读写分离 + if($master) + // 主服务器写入 + $r = floor(mt_rand(0,$this->config['master_num']-1)); + else{ + if(is_numeric($this->config['slave_no'])) {// 指定服务器读 + $r = $this->config['slave_no']; + }else{ + // 读操作连接从服务器 + $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 + } + } + }else{ + // 读写操作不区分服务器 + $r = floor(mt_rand(0,count($_config['hostname'])-1)); // 每次随机连接的数据库 + } + $db_config = [ + 'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0], + 'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0], + 'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0], + 'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0], + 'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0], + 'dsn' => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0], + ]; + return $this->connect($db_config,$r); + } + + /** + * 析构方法 + * @access public + */ + public function __destruct() { + // 释放查询 + if ($this->PDOStatement){ + $this->free(); + } + // 关闭连接 + $this->close(); + } +} \ No newline at end of file diff --git a/Library/Think/Debug.php b/Library/Think/Debug.php new file mode 100644 index 00000000..340b1627 --- /dev/null +++ b/Library/Think/Debug.php @@ -0,0 +1,112 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Debug { + + static protected $_info = []; + static protected $_mem = []; + + /** + * 记录时间(微秒)和内存使用情况 + * @param string $name 标记位置 + * @param mixed $value 标记值 留空则取当前 time 表示仅记录时间 否则同时记录时间和内存 + * @return mixed + */ + static public function remark($name,$value='') { + // 记录时间和内存使用 + self::$_info[$name] = is_float($value)?$value:microtime(TRUE); + if('time' != $value && function_exists('memory_get_usage')) { + self::$_mem['mem'][$name] = is_float($value)?$value:memory_get_usage(); + self::$_mem['peak'][$name] = function_exists('memory_get_peak_usage')?memory_get_peak_usage(): self::$_mem['mem'][$name]; + } + } + + /** + * 统计某个区间的时间(微秒)使用情况 + * @param string $start 开始标签 + * @param string $end 结束标签 + * @param integer|string $dec 小数位或者m + * @return mixed + */ + static public function getUseTime($start,$end,$dec=6) { + if(!isset(self::$_info[$end])) self::$_info[$end] = microtime(TRUE); + return number_format((self::$_info[$end]-self::$_info[$start]),$dec); + } + + /** + * 记录内存使用情况 + * @param string $start 开始标签 + * @param string $end 结束标签 + * @param integer|string $dec 小数位或者m + * @return mixed + */ + static public function getUseMem($start,$end,$dec=2) { + if(!isset(self::$_mem['mem'][$end])) + self::$_mem['mem'][$end] = memory_get_usage(); + $size = self::$_mem['mem'][$end]-self::$_mem['mem'][$start]; + $a = ['B', 'KB', 'MB', 'GB', 'TB']; + $pos = 0; + while ($size >= 1024) { + $size /= 1024; + $pos++; + } + return round($size,$dec)." ".$a[$pos]; + } + + /** + * 统计内存峰值情况 + * @param string $start 开始标签 + * @param string $end 结束标签 + * @param integer|string $dec 小数位或者m + * @return mixed + */ + static public function getMemPeak($start,$end,$dec=2) { + if(!isset(self::$_mem['peak'][$end])) self::$_mem['peak'][$end] = function_exists('memory_get_peak_usage')?memory_get_peak_usage():memory_get_usage(); + $size = self::$_mem['peak'][$end]-self::$_mem['peak'][$start]; + $a = ['B', 'KB', 'MB', 'GB', 'TB']; + $pos = 0; + while ($size >= 1024) { + $size /= 1024; + $pos++; + } + return round($size,$dec)." ".$a[$pos]; + } + + /** + * 浏览器友好的变量输出 + * @param mixed $var 变量 + * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 + * @param string $label 标签 默认为空 + * @return void|string + */ + static public function dump($var, $echo=true, $label=null) { + $label = ($label === null) ? '' : rtrim($label) . ':'; + ob_start(); + var_dump($var); + $output = ob_get_clean(); + $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output); + if(IS_CLI) { + $output = PHP_EOL . $label. $output . PHP_EOL; + }else{ + if (!extension_loaded('xdebug')) { + $output = htmlspecialchars($output, ENT_QUOTES); + } + $output = '
' . $label . $output . '
'; + } + if ($echo) { + echo($output); + return null; + }else + return $output; + } +} diff --git a/Library/Think/Error.php b/Library/Think/Error.php new file mode 100644 index 00000000..b7675325 --- /dev/null +++ b/Library/Think/Error.php @@ -0,0 +1,128 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Error { + /** + * 自定义异常处理 + * @access public + * @param mixed $e 异常对象 + */ + static public function appException($e) { + $error = []; + $error['message'] = $e->getMessage(); + $trace = $e->getTrace(); + if('E' == $trace[0]['function']) { + $error['file'] = $trace[0]['file']; + $error['line'] = $trace[0]['line']; + }else{ + $error['file'] = $e->getFile(); + $error['line'] = $e->getLine(); + } + $error['trace'] = $e->getTraceAsString(); + // 记录异常日志 + Log::record($error['message'],'ERR'); + // 发送404信息 + header('HTTP/1.1 404 Not Found'); + header('Status:404 Not Found'); + // 输出异常页面 + self::halt($error); + } + + /** + * 自定义错误处理 + * @access public + * @param int $errno 错误类型 + * @param string $errstr 错误信息 + * @param string $errfile 错误文件 + * @param int $errline 错误行数 + * @return void + */ + static public function appError($errno, $errstr, $errfile, $errline) { + $errorStr = "[{$errno}] {$errstr} {$errfile} 第 {$errline} 行."; + switch ($errno) { + case E_ERROR: + case E_PARSE: + case E_CORE_ERROR: + case E_COMPILE_ERROR: + case E_USER_ERROR: + Log::record($errorStr, 'ERROR'); + self::halt($errorStr); + break; + case E_STRICT: + case E_USER_WARNING: + case E_USER_NOTICE: + default: + Log::record($errorStr, 'NOTIC'); + break; + } + } + + /** + * 应用关闭处理 + * @return void + */ + static public function appShutdown(){ + // 记录日志 + Log::save(); + if ($e = error_get_last()) { + switch ($e['type']) { + case E_ERROR: + case E_PARSE: + case E_CORE_ERROR: + case E_COMPILE_ERROR: + case E_USER_ERROR: + ob_end_clean(); + self::halt($e); + break; + } + } + } + + /** + * 错误输出 + * @param mixed $error 错误 + * @return void + */ + static public function halt($error) { + IS_CLI && exit(is_array($error)?$error['message']:$error); + $e = []; + if (Config::get('app_debug')) { + //调试模式下输出错误信息 + if (!is_array($error)) { + $trace = debug_backtrace(); + $e['message'] = $error; + $e['file'] = $trace[0]['file']; + $e['line'] = $trace[0]['line']; + ob_start(); + debug_print_backtrace(); + $e['trace'] = ob_get_clean(); + } else { + $e = $error; + } + } else { + //否则定向到错误页面 + $error_page = Config::get('error_page'); + if (!empty($error_page)) { + header('Location: ' . $error_page); + } else { + if (Config::get('show_error_msg')) + $e['message'] = is_array($error) ? $error['message'] : $error; + else + $e['message'] = C('error_message'); + } + } + // 包含异常页面模板 + include Config::get('exception_tmpl'); + exit; + } +} diff --git a/Library/Think/Exception.php b/Library/Think/Exception.php new file mode 100644 index 00000000..3e8529ad --- /dev/null +++ b/Library/Think/Exception.php @@ -0,0 +1,16 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Exception extends \Exception { + +} diff --git a/Library/Think/Filter.php b/Library/Think/Filter.php new file mode 100644 index 00000000..6fcda662 --- /dev/null +++ b/Library/Think/Filter.php @@ -0,0 +1,222 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Filter { + //html标签设置 + static public $htmlTags = [ + 'allow' => 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a', + 'ban' => 'html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml', + ]; + + static public function filter($data,$filter,$option=''){ + return filter_var($data,is_int($filter)?$filter:filter_id($filter),$option); + } + + static private function filter_input($type,$name,$filter,$options=''){ + return filter_input($type,$name,is_int($filter)?$filter:filter_id($filter),$option); + } + + static public function get($name,$filter,$option=''){ + return self::filter_input(INPUT_GET,$name,$filter,$option); + } + + static public function post($name,$filter,$option=''){ + return self::filter_input(INPUT_POST,$name,$filter,$option); + } + + static public function cookie($name,$filter,$option=''){ + return self::filter_input(INPUT_COOKIE,$name,$filter,$option); + } + + static public function server($name,$filter,$option=''){ + return self::filter_input(INPUT_SERVER,$name,$filter,$option); + } + + /** + * 处理字符串,以便可以正常进行搜索 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forSearch($string) { + return str_replace( ['%','_'], ['\%','\_'], $string ); + } + + /** + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forShow($string) { + return self::nl2Br( self::hsc($string) ); + } + + /** + * 处理纯文本数据,以便在textarea标签中显示 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forTarea($string) { + return str_ireplace([''], ['<textarea>','</textarea>'], $string); + } + + /** + * 将数据中的单引号和双引号进行转义 + * @access public + * @param string $text 要处理的字符串 + * @return string + */ + static public function forTag($string) { + return str_replace(['"',"'"], ['"','''], $string); + } + + /** + * 把换行转换为
标签 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function nl2Br($string) { + return nl2Br($string); + } + + /** + * 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function addSlashes($string) { + return addslashes($string); + } + + /** + * 用于在textbox表单中显示html代码 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static function hsc($string) { + return preg_replace(["/&/i", "/ /i"], ['&', '&nbsp;'], htmlspecialchars($string, ENT_QUOTES)); + } + + /** + * 是hsc()方法的逆操作 + * @access public + * @param string $text 要处理的字符串 + * @return string + */ + static function undoHsc($text) { + return preg_replace(["/>/i", "/</i", "/"/i", "/'/i", '/&nbsp;/i'], [">", "<", "\"", "'", " "], $text); + } + + /** + * 输出安全的html,用于过滤危险代码 + * @access public + * @param string $text 要处理的字符串 + * @param mixed $allowTags 允许的标签列表,如 table|td|th|td + * @return string + */ + static public function safeHtml($text, $allowTags = null) { + $text = trim($text); + //完全过滤注释 + $text = preg_replace('//','',$text); + //完全过滤动态代码 + $text = preg_replace('/<\?|\?'.'>/','',$text); + //完全过滤js + $text = preg_replace('//','',$text); + + $text = str_replace('[','[',$text); + $text = str_replace(']',']',$text); + $text = str_replace('|','|',$text); + //过滤换行符 + $text = preg_replace('/\r?\n/','',$text); + //br + $text = preg_replace('//i','[br]',$text); + $text = preg_replace('/(\[br\]\s*){10,}/i','[br]',$text); + //过滤危险的属性,如:过滤on事件lang js + while(preg_match('/(<[^><]+)(lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1],$text); + } + while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1].$mat[3],$text); + } + if( empty($allowTags) ) { $allowTags = self::$htmlTags['allow']; } + //允许的HTML标签 + $text = preg_replace('/<('.$allowTags.')( [^><\[\]]*)>/i','[\1\2]',$text); + //过滤多余html + if ( empty($banTag) ) { $banTag = self::$htmlTags['ban']; } + $text = preg_replace('/<\/?('.$banTag.')[^><]*>/i','',$text); + //过滤合法的html标签 + while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){ + $text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text); + } + //转换引号 + while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text); + } + //空属性转换 + $text = str_replace('\'\'','||',$text); + $text = str_replace('""','||',$text); + //过滤错误的单个引号 + while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){ + $text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text); + } + //转换其它所有不合法的 < > + $text = str_replace('<','<',$text); + $text = str_replace('>','>',$text); + $text = str_replace('"','"',$text); + //反转换 + $text = str_replace('[','<',$text); + $text = str_replace(']','>',$text); + $text = str_replace('|','"',$text); + //过滤多余空格 + $text = str_replace(' ',' ',$text); + return $text; + } + + /** + * 删除html标签,得到纯文本。可以处理嵌套的标签 + * @access public + * @param string $string 要处理的html + * @return string + */ + static public function deleteHtmlTags($string) { + while(strstr($string, '>')) { + $currentBeg = strpos($string, '<'); + $currentEnd = strpos($string, '>'); + $tmpStringBeg = @substr($string, 0, $currentBeg); + $tmpStringEnd = @substr($string, $currentEnd + 1, strlen($string)); + $string = $tmpStringBeg.$tmpStringEnd; + } + return $string; + } + + /** + * 处理文本中的换行 + * @access public + * @param string $string 要处理的字符串 + * @param mixed $br 对换行的处理, + * false:去除换行;true:保留原样;string:替换成string + * @return string + */ + static public function nl2($string, $br = '
') { + if ($br == false) { + $string = preg_replace("/(\015\012)|(\015)|(\012)/", '', $string); + } elseif ($br != true){ + $string = preg_replace("/(\015\012)|(\015)|(\012)/", $br, $string); + } + return $string; + } +} diff --git a/Library/Think/Image.php b/Library/Think/Image.php new file mode 100644 index 00000000..3db9b3cc --- /dev/null +++ b/Library/Think/Image.php @@ -0,0 +1,61 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +/* 缩略图相关常量定义 */ +define('THINKIMAGE_THUMB_SCALING', 1); //常量,标识缩略图等比例缩放类型 +define('THINKIMAGE_THUMB_FILLED', 2); //常量,标识缩略图缩放后填充类型 +define('THINKIMAGE_THUMB_CENTER', 3); //常量,标识缩略图居中裁剪类型 +define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量,标识缩略图左上角裁剪类型 +define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量,标识缩略图右下角裁剪类型 +define('THINKIMAGE_THUMB_FIXED', 6); //常量,标识缩略图固定尺寸缩放类型 + +/* 水印相关常量定义 */ +define('THINKIMAGE_WATER_NORTHWEST', 1); //常量,标识左上角水印 +define('THINKIMAGE_WATER_NORTH', 2); //常量,标识上居中水印 +define('THINKIMAGE_WATER_NORTHEAST', 3); //常量,标识右上角水印 +define('THINKIMAGE_WATER_WEST', 4); //常量,标识左居中水印 +define('THINKIMAGE_WATER_CENTER', 5); //常量,标识居中水印 +define('THINKIMAGE_WATER_EAST', 6); //常量,标识右居中水印 +define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量,标识左下角水印 +define('THINKIMAGE_WATER_SOUTH', 8); //常量,标识下居中水印 +define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量,标识右下角水印 + +/** + * 图片处理驱动类,可配置图片处理库 + * 目前支持GD库和imagick + * @author 麦当苗儿 + */ +class Image { + /** + * 图片资源 + * @var resource + */ + private static $im; + + /** + * 初始化方法,用于实例化一个图片处理对象 + * @param string $type 要使用的类库,默认使用GD库 + */ + static public function init($type = 'Gd', $imgname = null){ + /* 引入处理库,实例化图片处理对象 */ + $class = '\\Think\\Image\\Driver\\'.ucwords($type); + self::$im = new $class($imgname); + return self::$im; + } + + // 调用驱动类的方法 + static public function __callStatic($method, $params){ + self::$im || self::init(); + return call_user_func_array([self::$im, $method], $params); + } +} diff --git a/Library/Think/Image/Driver/Gd.php b/Library/Think/Image/Driver/Gd.php new file mode 100644 index 00000000..34facecd --- /dev/null +++ b/Library/Think/Image/Driver/Gd.php @@ -0,0 +1,549 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Gd{ + /** + * 图像资源对象 + * @var resource + */ + private $im; + private $gif; + /** + * 图像信息,包括width,height,type,mime,size + * @var array + */ + private $info; + + /** + * 构造方法,可用于打开一张图像 + * @param string $imgname 图像路径 + */ + public function __construct($imgname = null) { + $imgname && $this->open($imgname); + } + + /** + * 打开一张图像 + * @param string $imgname 图像路径 + */ + public function open($imgname){ + //检测图像文件 + if(!is_file($imgname)) throw new \Exception('不存在的图像文件'); + + //获取图像信息 + $info = getimagesize($imgname); + + //检测图像合法性 + if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ + throw new \Exception('非法图像文件'); + } + + //设置图像信息 + $this->info = [ + 'width' => $info[0], + 'height' => $info[1], + 'type' => image_type_to_extension($info[2], false), + 'mime' => $info['mime'], + ]; + + //销毁已存在的图像 + empty($this->im) || imagedestroy($this->im); + + //打开图像 + if('gif' == $this->info['type']){ + $class = '\\Think\\Image\\Driver\\Gif'; + $this->gif = new $class($imgname); + $this->im = imagecreatefromstring($this->gif->image()); + } else { + $fun = "imagecreatefrom{$this->info['type']}"; + $this->im = $fun($imgname); + } + return $this; + } + + /** + * 保存图像 + * @param string $imgname 图像保存名称 + * @param string $type 图像类型 + * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 + */ + public function save($imgname, $type = null, $interlace = true){ + if(empty($this->im)) throw new \Exception('没有可以被保存的图像资源'); + + //自动获取图像类型 + if(is_null($type)){ + $type = $this->info['type']; + } else { + $type = strtolower($type); + } + + //JPEG图像设置隔行扫描 + if('jpeg' == $type || 'jpg' == $type){ + $type = 'jpeg'; + imageinterlace($this->im, $interlace); + } + + //保存图像 + if('gif' == $type && !empty($this->gif)){ + $this->gif->save($imgname); + } else { + $fun = "image{$type}"; + $fun($this->im, $imgname); + } + return $this; + } + + /** + * 返回图像宽度 + * @return integer 图像宽度 + */ + public function width(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['width']; + } + + /** + * 返回图像高度 + * @return integer 图像高度 + */ + public function height(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['height']; + } + + /** + * 返回图像类型 + * @return string 图像类型 + */ + public function type(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['type']; + } + + /** + * 返回图像MIME类型 + * @return string 图像MIME类型 + */ + public function mime(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['mime']; + } + + /** + * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 + * @return array 图像尺寸 + */ + public function size(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return [$this->info['width'], $this->info['height']]; + } + + /** + * 裁剪图像 + * @param integer $w 裁剪区域宽度 + * @param integer $h 裁剪区域高度 + * @param integer $x 裁剪区域x坐标 + * @param integer $y 裁剪区域y坐标 + * @param integer $width 图像保存宽度 + * @param integer $height 图像保存高度 + */ + public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ + if(empty($this->im)) throw new \Exception('没有可以被裁剪的图像资源'); + + //设置保存尺寸 + empty($width) && $width = $w; + empty($height) && $height = $h; + + do { + //创建新图像 + $img = imagecreatetruecolor($width, $height); + // 调整默认颜色 + $color = imagecolorallocate($img, 255, 255, 255); + imagefill($img, 0, 0, $color); + + //裁剪 + imagecopyresampled($img, $this->im, 0, 0, $x, $y, $width, $height, $w, $h); + imagedestroy($this->im); //销毁原图 + + //设置新图像 + $this->im = $img; + } while(!empty($this->gif) && $this->gifNext()); + + $this->info['width'] = $width; + $this->info['height'] = $height; + return $this; + } + + /** + * 生成缩略图 + * @param integer $width 缩略图最大宽度 + * @param integer $height 缩略图最大高度 + * @param integer $type 缩略图裁剪类型 + */ + public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ + if(empty($this->im)) throw new \Exception('没有可以被缩略的图像资源'); + + //原图宽度和高度 + $w = $this->info['width']; + $h = $this->info['height']; + + /* 计算缩略图生成的必要参数 */ + switch ($type) { + /* 等比例缩放 */ + case THINKIMAGE_THUMB_SCALING: + //原图尺寸小于缩略图尺寸则不进行缩略 + if($w < $width && $h < $height) return; + + //计算缩放比例 + $scale = min($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $width = $w * $scale; + $height = $h * $scale; + break; + + /* 居中裁剪 */ + case THINKIMAGE_THUMB_CENTER: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = ($this->info['width'] - $w)/2; + $y = ($this->info['height'] - $h)/2; + break; + + /* 左上角裁剪 */ + case THINKIMAGE_THUMB_NORTHWEST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $w = $width/$scale; + $h = $height/$scale; + break; + + /* 右下角裁剪 */ + case THINKIMAGE_THUMB_SOUTHEAST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = $this->info['width'] - $w; + $y = $this->info['height'] - $h; + break; + + /* 填充 */ + case THINKIMAGE_THUMB_FILLED: + //计算缩放比例 + if($w < $width && $h < $height){ + $scale = 1; + } else { + $scale = min($width/$w, $height/$h); + } + + //设置缩略图的坐标及宽度和高度 + $neww = $w * $scale; + $newh = $h * $scale; + $posx = ($width - $w * $scale)/2; + $posy = ($height - $h * $scale)/2; + + do{ + //创建新图像 + $img = imagecreatetruecolor($width, $height); + // 调整默认颜色 + $color = imagecolorallocate($img, 255, 255, 255); + imagefill($img, 0, 0, $color); + + //裁剪 + imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h); + imagedestroy($this->im); //销毁原图 + $this->im = $img; + } while(!empty($this->gif) && $this->gifNext()); + + $this->info['width'] = $width; + $this->info['height'] = $height; + return $this; + + /* 固定 */ + case THINKIMAGE_THUMB_FIXED: + $x = $y = 0; + break; + + default: + throw new \Exception('不支持的缩略图裁剪类型'); + } + + /* 裁剪图像 */ + $this->crop($w, $h, $x, $y, $width, $height); + return $this; + } + + /** + * 添加水印 + * @param string $source 水印图片路径 + * @param integer $locate 水印位置 + * @param integer $alpha 水印透明度 + */ + public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被添加水印的图像资源'); + if(!is_file($source)) throw new \Exception('水印图像不存在'); + + //获取水印图像信息 + $info = getimagesize($source); + if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ + throw new \Exception('非法水印文件'); + } + + //创建水印图像资源 + $fun = 'imagecreatefrom' . image_type_to_extension($info[2], false); + $water = $fun($source); + + //设定水印图像的混色模式 + imagealphablending($water, true); + + /* 设定水印位置 */ + switch ($locate) { + /* 右下角水印 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x = $this->info['width'] - $info[0]; + $y = $this->info['height'] - $info[1]; + break; + + /* 左下角水印 */ + case THINKIMAGE_WATER_SOUTHWEST: + $x = 0; + $y = $this->info['height'] - $info[1]; + break; + + /* 左上角水印 */ + case THINKIMAGE_WATER_NORTHWEST: + $x = $y = 0; + break; + + /* 右上角水印 */ + case THINKIMAGE_WATER_NORTHEAST: + $x = $this->info['width'] - $info[0]; + $y = 0; + break; + + /* 居中水印 */ + case THINKIMAGE_WATER_CENTER: + $x = ($this->info['width'] - $info[0])/2; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 下居中水印 */ + case THINKIMAGE_WATER_SOUTH: + $x = ($this->info['width'] - $info[0])/2; + $y = $this->info['height'] - $info[1]; + break; + + /* 右居中水印 */ + case THINKIMAGE_WATER_EAST: + $x = $this->info['width'] - $info[0]; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 上居中水印 */ + case THINKIMAGE_WATER_NORTH: + $x = ($this->info['width'] - $info[0])/2; + $y = 0; + break; + + /* 左居中水印 */ + case THINKIMAGE_WATER_WEST: + $x = 0; + $y = ($this->info['height'] - $info[1])/2; + break; + + default: + /* 自定义水印坐标 */ + if(is_array($locate)){ + list($x, $y) = $locate; + } else { + throw new \Exception('不支持的水印位置类型'); + } + } + + do{ + //添加水印 + $src = imagecreatetruecolor($info[0], $info[1]); + // 调整默认颜色 + $color = imagecolorallocate($src, 255, 255, 255); + imagefill($src, 0, 0, $color); + + imagecopy($src, $this->im, 0, 0, $x, $y, $info[0], $info[1]); + imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]); + imagecopymerge($this->im, $src, $x, $y, 0, 0, $info[0], $info[1], 100); + + //销毁零时图片资源 + imagedestroy($src); + } while(!empty($this->gif) && $this->gifNext()); + + //销毁水印资源 + imagedestroy($water); + return $this; + } + + /** + * 图像添加文字 + * @param string $text 添加的文字 + * @param string $font 字体路径 + * @param integer $size 字号 + * @param string $color 文字颜色 + * @param integer $locate 文字写入位置 + * @param integer $offset 文字相对当前位置的偏移量 + * @param integer $angle 文字倾斜角度 + */ + public function text($text, $font, $size, $color = '#00000000', + $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被写入文字的图像资源'); + if(!is_file($font)) throw new \Exception("不存在的字体文件:{$font}"); + + //获取文字信息 + $info = imagettfbbox($size, $angle, $font, $text); + $minx = min($info[0], $info[2], $info[4], $info[6]); + $maxx = max($info[0], $info[2], $info[4], $info[6]); + $miny = min($info[1], $info[3], $info[5], $info[7]); + $maxy = max($info[1], $info[3], $info[5], $info[7]); + + /* 计算文字初始坐标和尺寸 */ + $x = $minx; + $y = abs($miny); + $w = $maxx - $minx; + $h = $maxy - $miny; + + /* 设定文字位置 */ + switch ($locate) { + /* 右下角文字 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x += $this->info['width'] - $w; + $y += $this->info['height'] - $h; + break; + + /* 左下角文字 */ + case THINKIMAGE_WATER_SOUTHWEST: + $y += $this->info['height'] - $h; + break; + + /* 左上角文字 */ + case THINKIMAGE_WATER_NORTHWEST: + // 起始坐标即为左上角坐标,无需调整 + break; + + /* 右上角文字 */ + case THINKIMAGE_WATER_NORTHEAST: + $x += $this->info['width'] - $w; + break; + + /* 居中文字 */ + case THINKIMAGE_WATER_CENTER: + $x += ($this->info['width'] - $w)/2; + $y += ($this->info['height'] - $h)/2; + break; + + /* 下居中文字 */ + case THINKIMAGE_WATER_SOUTH: + $x += ($this->info['width'] - $w)/2; + $y += $this->info['height'] - $h; + break; + + /* 右居中文字 */ + case THINKIMAGE_WATER_EAST: + $x += $this->info['width'] - $w; + $y += ($this->info['height'] - $h)/2; + break; + + /* 上居中文字 */ + case THINKIMAGE_WATER_NORTH: + $x += ($this->info['width'] - $w)/2; + break; + + /* 左居中文字 */ + case THINKIMAGE_WATER_WEST: + $y += ($this->info['height'] - $h)/2; + break; + + default: + /* 自定义文字坐标 */ + if(is_array($locate)){ + list($posx, $posy) = $locate; + $x += $posx; + $y += $posy; + } else { + throw new \Exception('不支持的文字位置类型'); + } + } + + /* 设置偏移量 */ + if(is_array($offset)){ + $offset = array_map('intval', $offset); + list($ox, $oy) = $offset; + } else{ + $offset = intval($offset); + $ox = $oy = $offset; + } + + /* 设置颜色 */ + if(is_string($color) && 0 === strpos($color, '#')){ + $color = str_split(substr($color, 1), 2); + $color = array_map('hexdec', $color); + if(empty($color[3]) || $color[3] > 127){ + $color[3] = 0; + } + } elseif (!is_array($color)) { + throw new \Exception('错误的颜色值'); + } + + do{ + /* 写入文字 */ + $col = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $color[3]); + imagettftext($this->im, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text); + } while(!empty($this->gif) && $this->gifNext()); + return $this; + } + + /* 切换到GIF的下一帧并保存当前帧,内部使用 */ + private function gifNext(){ + ob_start(); + ob_implicit_flush(0); + imagegif($this->im); + $img = ob_get_clean(); + + $this->gif->image($img); + $next = $this->gif->nextImage(); + + if($next){ + $this->im = imagecreatefromstring($next); + return $next; + } else { + $this->im = imagecreatefromstring($this->gif->image()); + return false; + } + } + + /** + * 析构方法,用于销毁图像资源 + */ + public function __destruct() { + empty($this->im) || imagedestroy($this->im); + } +} diff --git a/Library/Think/Image/Driver/Gif.php b/Library/Think/Image/Driver/Gif.php new file mode 100644 index 00000000..5e2b6d69 --- /dev/null +++ b/Library/Think/Image/Driver/Gif.php @@ -0,0 +1,570 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Gif{ + /** + * GIF帧列表 + * @var array + */ + private $frames = []; + + /** + * 每帧等待时间列表 + * @var array + */ + private $delays = []; + + /** + * 构造方法,用于解码GIF图片 + * @param string $src GIF图片数据 + * @param string $mod 图片数据类型 + */ + public function __construct($src = null, $mod = 'url') { + if(!is_null($src)){ + if('url' == $mod && is_file($src)){ + $src = file_get_contents($src); + } + + /* 解码GIF图片 */ + try{ + $de = new GIFDecoder($src); + $this->frames = $de->GIFGetFrames(); + $this->delays = $de->GIFGetDelays(); + } catch(Exception $e){ + throw new \Exception("解码GIF图片出错"); + } + } + } + + /** + * 设置或获取当前帧的数据 + * @param string $stream 二进制数据流 + * @return boolean 获取到的数据 + */ + public function image($stream = null){ + if(is_null($stream)){ + $current = current($this->frames); + return false === $current ? reset($this->frames) : $current; + } else { + $this->frames[key($this->frames)] = $stream; + } + } + + /** + * 将当前帧移动到下一帧 + * @return string 当前帧数据 + */ + public function nextImage(){ + return next($this->frames); + } + + /** + * 编码并保存当前GIF图片 + * @param string $gifname 图片名称 + */ + public function save($gifname){ + $gif = new GIFEncoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin'); + file_put_contents($gifname, $gif->GetAnimation()); + } + +} + + +/* +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu +:: +:: This class is a rewritten 'GifMerge.class.php' version. +:: +:: Modification: +:: - Simplified and easy code, +:: - Ultra fast encoding, +:: - Built-in errors, +:: - Stable working +:: +:: +:: Updated at 2007. 02. 13. '00.05.AM' +:: +:: +:: +:: Try on-line GIFBuilder Form demo based on GIFEncoder. +:: +:: http://gifs.hu/phpclasses/demos/GifBuilder/ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +*/ + +Class GIFEncoder { + var $GIF = "GIF89a"; /* GIF header 6 bytes */ + var $VER = "GIFEncoder V2.05"; /* Encoder version */ + + var $BUF = array ( ); + var $LOP = 0; + var $DIS = 2; + var $COL = -1; + var $IMG = -1; + + var $ERR = array ( + 'ERR00'=>"Does not supported function for only one image!", + 'ERR01'=>"Source is not a GIF image!", + 'ERR02'=>"Unintelligible flag ", + 'ERR03'=>"Does not make animation from animated GIF source", + ); + + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFEncoder... + :: + */ + function GIFEncoder ( + $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis, + $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod + ) { + if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) { + printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] ); + exit ( 0 ); + } + $this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0; + $this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2; + $this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ? + ( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1; + + for ( $i = 0; $i < count ( $GIF_src ); $i++ ) { + if ( strToLower ( $GIF_mod ) == "url" ) { + $this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) ); + } + else if ( strToLower ( $GIF_mod ) == "bin" ) { + $this->BUF [ ] = $GIF_src [ $i ]; + } + else { + printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod ); + exit ( 0 ); + } + if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) { + printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] ); + exit ( 0 ); + } + for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) { + switch ( $this->BUF [ $i ] { $j } ) { + case "!": + if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) { + printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) ); + exit ( 0 ); + } + break; + case ";": + $k = FALSE; + break; + } + } + } + GIFEncoder::GIFAddHeader ( ); + for ( $i = 0; $i < count ( $this->BUF ); $i++ ) { + GIFEncoder::GIFAddFrames ( $i, $GIF_dly [ $i ] ); + } + GIFEncoder::GIFAddFooter ( ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddHeader... + :: + */ + function GIFAddHeader ( ) { + $cmap = 0; + + if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) { + $cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ); + + $this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 ); + $this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap ); + $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0"; + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFrames... + :: + */ + function GIFAddFrames ( $i, $d ) { + + $Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); + + $Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1; + $Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end ); + + $Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + + $Global_rgb = substr ( $this->BUF [ 0 ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) ); + $Locals_rgb = substr ( $this->BUF [ $i ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ); + + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0"; + + if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) { + for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) { + if ( + ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) && + ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >> 8 ) & 0xFF ) && + ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >> 0 ) & 0xFF ) + ) { + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 1 ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0"; + break; + } + } + } + switch ( $Locals_tmp { 0 } ) { + case "!": + $Locals_img = substr ( $Locals_tmp, 8, 10 ); + $Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 ); + break; + case ",": + $Locals_img = substr ( $Locals_tmp, 0, 10 ); + $Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 ); + break; + } + if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) { + if ( $Global_len == $Locals_len ) { + if ( GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + $this->IMG = 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFooter... + :: + */ + function GIFAddFooter ( ) { + $this->GIF .= ";"; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFBlockCompare... + :: + */ + function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) { + + for ( $i = 0; $i < $Len; $i++ ) { + if ( + $GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } || + $GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } || + $GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 } + ) { + return ( 0 ); + } + } + + return ( 1 ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFWord... + :: + */ + function GIFWord ( $int ) { + + return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GetAnimation... + :: + */ + function GetAnimation ( ) { + return ( $this->GIF ); + } +} + + +/* +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: GIFDecoder Version 2.0 by László Zsidi, http://gifs.hu +:: +:: Created at 2007. 02. 01. '07.47.AM' +:: +:: +:: +:: +:: Try on-line GIFBuilder Form demo based on GIFDecoder. +:: +:: http://gifs.hu/phpclasses/demos/GifBuilder/ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +*/ + +Class GIFDecoder { + var $GIF_buffer = array ( ); + var $GIF_arrays = array ( ); + var $GIF_delays = array ( ); + var $GIF_stream = ""; + var $GIF_string = ""; + var $GIF_bfseek = 0; + + var $GIF_screen = array ( ); + var $GIF_global = array ( ); + var $GIF_sorted; + var $GIF_colorS; + var $GIF_colorC; + var $GIF_colorF; + + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFDecoder ( $GIF_pointer ) + :: + */ + function GIFDecoder ( $GIF_pointer ) { + $this->GIF_stream = $GIF_pointer; + + GIFDecoder::GIFGetByte ( 6 ); // GIF89a + GIFDecoder::GIFGetByte ( 7 ); // Logical Screen Descriptor + + $this->GIF_screen = $this->GIF_buffer; + $this->GIF_colorF = $this->GIF_buffer [ 4 ] & 0x80 ? 1 : 0; + $this->GIF_sorted = $this->GIF_buffer [ 4 ] & 0x08 ? 1 : 0; + $this->GIF_colorC = $this->GIF_buffer [ 4 ] & 0x07; + $this->GIF_colorS = 2 << $this->GIF_colorC; + + if ( $this->GIF_colorF == 1 ) { + GIFDecoder::GIFGetByte ( 3 * $this->GIF_colorS ); + $this->GIF_global = $this->GIF_buffer; + } + /* + * + * 05.06.2007. + * Made a little modification + * + * + - for ( $cycle = 1; $cycle; ) { + + if ( GIFDecoder::GIFGetByte ( 1 ) ) { + - switch ( $this->GIF_buffer [ 0 ] ) { + - case 0x21: + - GIFDecoder::GIFReadExtensions ( ); + - break; + - case 0x2C: + - GIFDecoder::GIFReadDescriptor ( ); + - break; + - case 0x3B: + - $cycle = 0; + - break; + - } + - } + + else { + + $cycle = 0; + + } + - } + */ + for ( $cycle = 1; $cycle; ) { + if ( GIFDecoder::GIFGetByte ( 1 ) ) { + switch ( $this->GIF_buffer [ 0 ] ) { + case 0x21: + GIFDecoder::GIFReadExtensions ( ); + break; + case 0x2C: + GIFDecoder::GIFReadDescriptor ( ); + break; + case 0x3B: + $cycle = 0; + break; + } + } + else { + $cycle = 0; + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadExtension ( ) + :: + */ + function GIFReadExtensions ( ) { + GIFDecoder::GIFGetByte ( 1 ); + for ( ; ; ) { + GIFDecoder::GIFGetByte ( 1 ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + GIFDecoder::GIFGetByte ( $u ); + /* + * 07.05.2007. + * Implemented a new line for a new function + * to determine the originaly delays between + * frames. + * + */ + if ( $u == 4 ) { + $this->GIF_delays [ ] = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 ); + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadExtension ( ) + :: + */ + function GIFReadDescriptor ( ) { + $GIF_screen = array ( ); + + GIFDecoder::GIFGetByte ( 9 ); + $GIF_screen = $this->GIF_buffer; + $GIF_colorF = $this->GIF_buffer [ 8 ] & 0x80 ? 1 : 0; + if ( $GIF_colorF ) { + $GIF_code = $this->GIF_buffer [ 8 ] & 0x07; + $GIF_sort = $this->GIF_buffer [ 8 ] & 0x20 ? 1 : 0; + } + else { + $GIF_code = $this->GIF_colorC; + $GIF_sort = $this->GIF_sorted; + } + $GIF_size = 2 << $GIF_code; + $this->GIF_screen [ 4 ] &= 0x70; + $this->GIF_screen [ 4 ] |= 0x80; + $this->GIF_screen [ 4 ] |= $GIF_code; + if ( $GIF_sort ) { + $this->GIF_screen [ 4 ] |= 0x08; + } + $this->GIF_string = "GIF87a"; + GIFDecoder::GIFPutByte ( $this->GIF_screen ); + if ( $GIF_colorF == 1 ) { + GIFDecoder::GIFGetByte ( 3 * $GIF_size ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + else { + GIFDecoder::GIFPutByte ( $this->GIF_global ); + } + $this->GIF_string .= chr ( 0x2C ); + $GIF_screen [ 8 ] &= 0x40; + GIFDecoder::GIFPutByte ( $GIF_screen ); + GIFDecoder::GIFGetByte ( 1 ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + for ( ; ; ) { + GIFDecoder::GIFGetByte ( 1 ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + GIFDecoder::GIFGetByte ( $u ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + $this->GIF_string .= chr ( 0x3B ); + /* + Add frames into $GIF_stream array... + */ + $this->GIF_arrays [ ] = $this->GIF_string; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetByte ( $len ) + :: + */ + + /* + * + * 05.06.2007. + * Made a little modification + * + * + - function GIFGetByte ( $len ) { + - $this->GIF_buffer = array ( ); + - + - for ( $i = 0; $i < $len; $i++ ) { + + if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { + + return 0; + + } + - $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); + - } + + return 1; + - } + */ + function GIFGetByte ( $len ) { + $this->GIF_buffer = array ( ); + + for ( $i = 0; $i < $len; $i++ ) { + if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { + return 0; + } + $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); + } + return 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFPutByte ( $bytes ) + :: + */ + function GIFPutByte ( $bytes ) { + for ( $i = 0; $i < count ( $bytes ); $i++ ) { + $this->GIF_string .= chr ( $bytes [ $i ] ); + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: PUBLIC FUNCTIONS + :: + :: + :: GIFGetFrames ( ) + :: + */ + function GIFGetFrames ( ) { + return ( $this->GIF_arrays ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetDelays ( ) + :: + */ + function GIFGetDelays ( ) { + return ( $this->GIF_delays ); + } +} diff --git a/Library/Think/Image/Driver/Imagick.php b/Library/Think/Image/Driver/Imagick.php new file mode 100644 index 00000000..85d9b5ef --- /dev/null +++ b/Library/Think/Image/Driver/Imagick.php @@ -0,0 +1,591 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Imagick{ + /** + * 图像资源对象 + * @var resource + */ + private $im; + + /** + * 图像信息,包括width,height,type,mime,size + * @var array + */ + private $info; + + /** + * 构造方法,可用于打开一张图像 + * @param string $imgname 图像路径 + */ + public function __construct($imgname = null) { + if ( !extension_loaded('Imagick') ) { + E(L('_NOT_SUPPERT_').':Imagick'); + } + $imgname && $this->open($imgname); + } + + /** + * 打开一张图像 + * @param string $imgname 图像路径 + */ + public function open($imgname){ + //检测图像文件 + if(!is_file($imgname)) throw new \Exception('不存在的图像文件'); + + //销毁已存在的图像 + empty($this->im) || $this->im->destroy(); + + //载入图像 + $this->im = new \Imagick(realpath($imgname)); + + //设置图像信息 + $this->info = [ + 'width' => $this->im->getImageWidth(), + 'height' => $this->im->getImageHeight(), + 'type' => strtolower($this->im->getImageFormat()), + 'mime' => $this->im->getImageMimeType(), + ]; + } + + /** + * 保存图像 + * @param string $imgname 图像保存名称 + * @param string $type 图像类型 + * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 + */ + public function save($imgname, $type = null, $interlace = true){ + if(empty($this->im)) throw new \Exception('没有可以被保存的图像资源'); + + //设置图片类型 + if(is_null($type)){ + $type = $this->info['type']; + } else { + $type = strtolower($type); + $this->im->setImageFormat($type); + } + + //JPEG图像设置隔行扫描 + if('jpeg' == $type || 'jpg' == $type){ + $this->im->setImageInterlaceScheme(1); + } + + //去除图像配置信息 + $this->im->stripImage(); + + //保存图像 + $imgname = realpath(dirname($imgname)) . '/' . basename($imgname); //强制绝对路径 + if ('gif' == $type) { + $this->im->writeImages($imgname, true); + } else { + $this->im->writeImage($imgname); + } + } + + /** + * 返回图像宽度 + * @return integer 图像宽度 + */ + public function width(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['width']; + } + + /** + * 返回图像高度 + * @return integer 图像高度 + */ + public function height(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['height']; + } + + /** + * 返回图像类型 + * @return string 图像类型 + */ + public function type(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['type']; + } + + /** + * 返回图像MIME类型 + * @return string 图像MIME类型 + */ + public function mime(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['mime']; + } + + /** + * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 + * @return array 图像尺寸 + */ + public function size(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return [$this->info['width'], $this->info['height']]; + } + + /** + * 裁剪图像 + * @param integer $w 裁剪区域宽度 + * @param integer $h 裁剪区域高度 + * @param integer $x 裁剪区域x坐标 + * @param integer $y 裁剪区域y坐标 + * @param integer $width 图像保存宽度 + * @param integer $height 图像保存高度 + */ + public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ + if(empty($this->im)) throw new \Exception('没有可以被裁剪的图像资源'); + + //设置保存尺寸 + empty($width) && $width = $w; + empty($height) && $height = $h; + + //裁剪图片 + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + + //循环裁剪每一帧 + do { + $this->_crop($w, $h, $x, $y, $width, $height, $img); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + } else { + $this->_crop($w, $h, $x, $y, $width, $height); + } + } + + /* 裁剪图片,内部调用 */ + private function _crop($w, $h, $x, $y, $width, $height, $img = null){ + is_null($img) && $img = $this->im; + + //裁剪 + $info = $this->info; + if($x != 0 || $y != 0 || $w != $info['width'] || $h != $info['height']){ + $img->cropImage($w, $h, $x, $y); + $img->setImagePage($w, $h, 0, 0); //调整画布和图片一致 + } + + //调整大小 + if($w != $width || $h != $height){ + $img->scaleImage($width, $height); + } + + //设置缓存尺寸 + $this->info['width'] = $w; + $this->info['height'] = $h; + } + + /** + * 生成缩略图 + * @param integer $width 缩略图最大宽度 + * @param integer $height 缩略图最大高度 + * @param integer $type 缩略图裁剪类型 + */ + public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ + if(empty($this->im)) throw new \Exception('没有可以被缩略的图像资源'); + + //原图宽度和高度 + $w = $this->info['width']; + $h = $this->info['height']; + + /* 计算缩略图生成的必要参数 */ + switch ($type) { + /* 等比例缩放 */ + case THINKIMAGE_THUMB_SCALING: + //原图尺寸小于缩略图尺寸则不进行缩略 + if($w < $width && $h < $height) return; + + //计算缩放比例 + $scale = min($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $width = $w * $scale; + $height = $h * $scale; + break; + + /* 居中裁剪 */ + case THINKIMAGE_THUMB_CENTER: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = ($this->info['width'] - $w)/2; + $y = ($this->info['height'] - $h)/2; + break; + + /* 左上角裁剪 */ + case THINKIMAGE_THUMB_NORTHWEST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $w = $width/$scale; + $h = $height/$scale; + break; + + /* 右下角裁剪 */ + case THINKIMAGE_THUMB_SOUTHEAST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = $this->info['width'] - $w; + $y = $this->info['height'] - $h; + break; + + /* 填充 */ + case THINKIMAGE_THUMB_FILLED: + //计算缩放比例 + if($w < $width && $h < $height){ + $scale = 1; + } else { + $scale = min($width/$w, $height/$h); + } + + //设置缩略图的坐标及宽度和高度 + $neww = $w * $scale; + $newh = $h * $scale; + $posx = ($width - $w * $scale)/2; + $posy = ($height - $h * $scale)/2; + + //创建一张新图像 + $newimg = new Imagick(); + $newimg->newImage($width, $height, 'white', $this->info['type']); + + + if('gif' == $this->info['type']){ + $imgs = $this->im->coalesceImages(); + $img = new Imagick(); + $this->im->destroy(); //销毁原图 + + //循环填充每一帧 + do { + //填充图像 + $image = $this->_fill($newimg, $posx, $posy, $neww, $newh, $imgs); + + $img->addImage($image); + $img->setImageDelay($imgs->getImageDelay()); + $img->setImagePage($width, $height, 0, 0); + + $image->destroy(); //销毁零时图片 + + } while ($imgs->nextImage()); + + //压缩图片 + $this->im->destroy(); + $this->im = $img->deconstructImages(); + $imgs->destroy(); //销毁零时图片 + $img->destroy(); //销毁零时图片 + + } else { + //填充图像 + $img = $this->_fill($newimg, $posx, $posy, $neww, $newh); + //销毁原图 + $this->im->destroy(); + $this->im = $img; + } + + //设置新图像属性 + $this->info['width'] = $width; + $this->info['height'] = $height; + return; + + /* 固定 */ + case THINKIMAGE_THUMB_FIXED: + $x = $y = 0; + break; + + default: + throw new \Exception('不支持的缩略图裁剪类型'); + } + + /* 裁剪图像 */ + $this->crop($w, $h, $x, $y, $width, $height); + } + + /* 填充指定图像,内部使用 */ + private function _fill($newimg, $posx, $posy, $neww, $newh, $img = null){ + is_null($img) && $img = $this->im; + + /* 将指定图片绘入空白图片 */ + $draw = new ImagickDraw(); + $draw->composite($img->getImageCompose(), $posx, $posy, $neww, $newh, $img); + $image = $newimg->clone(); + $image->drawImage($draw); + $draw->destroy(); + + return $image; + } + + /** + * 添加水印 + * @param string $source 水印图片路径 + * @param integer $locate 水印位置 + * @param integer $alpha 水印透明度 + */ + public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被添加水印的图像资源'); + if(!is_file($source)) throw new \Exception('水印图像不存在'); + + //创建水印图像资源 + $water = new Imagick(realpath($source)); + $info = [$water->getImageWidth(), $water->getImageHeight()]; + + /* 设定水印位置 */ + switch ($locate) { + /* 右下角水印 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x = $this->info['width'] - $info[0]; + $y = $this->info['height'] - $info[1]; + break; + + /* 左下角水印 */ + case THINKIMAGE_WATER_SOUTHWEST: + $x = 0; + $y = $this->info['height'] - $info[1]; + break; + + /* 左上角水印 */ + case THINKIMAGE_WATER_NORTHWEST: + $x = $y = 0; + break; + + /* 右上角水印 */ + case THINKIMAGE_WATER_NORTHEAST: + $x = $this->info['width'] - $info[0]; + $y = 0; + break; + + /* 居中水印 */ + case THINKIMAGE_WATER_CENTER: + $x = ($this->info['width'] - $info[0])/2; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 下居中水印 */ + case THINKIMAGE_WATER_SOUTH: + $x = ($this->info['width'] - $info[0])/2; + $y = $this->info['height'] - $info[1]; + break; + + /* 右居中水印 */ + case THINKIMAGE_WATER_EAST: + $x = $this->info['width'] - $info[0]; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 上居中水印 */ + case THINKIMAGE_WATER_NORTH: + $x = ($this->info['width'] - $info[0])/2; + $y = 0; + break; + + /* 左居中水印 */ + case THINKIMAGE_WATER_WEST: + $x = 0; + $y = ($this->info['height'] - $info[1])/2; + break; + + default: + /* 自定义水印坐标 */ + if(is_array($locate)){ + list($x, $y) = $locate; + } else { + throw new \Exception('不支持的水印位置类型'); + } + } + + //创建绘图资源 + $draw = new ImagickDraw(); + $draw->composite($water->getImageCompose(), $x, $y, $info[0], $info[1], $water); + + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + + do{ + //添加水印 + $img->drawImage($draw); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + + } else { + //添加水印 + $this->im->drawImage($draw); + } + + //销毁水印资源 + $draw->destroy(); + $water->destroy(); + } + + /** + * 图像添加文字 + * @param string $text 添加的文字 + * @param string $font 字体路径 + * @param integer $size 字号 + * @param string $color 文字颜色 + * @param integer $locate 文字写入位置 + * @param integer $offset 文字相对当前位置的偏移量 + * @param integer $angle 文字倾斜角度 + */ + public function text($text, $font, $size, $color = '#00000000', + $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被写入文字的图像资源'); + if(!is_file($font)) throw new \Exception("不存在的字体文件:{$font}"); + + //获取颜色和透明度 + if(is_array($color)){ + $color = array_map('dechex', $color); + foreach ($color as &$value) { + $value = str_pad($value, 2, '0', STR_PAD_LEFT); + } + $color = '#' . implode('', $color); + } elseif(!is_string($color) || 0 !== strpos($color, '#')) { + throw new \Exception('错误的颜色值'); + } + $col = substr($color, 0, 7); + $alp = strlen($color) == 9 ? substr($color, -2) : 0; + + + //获取文字信息 + $draw = new ImagickDraw(); + $draw->setFont(realpath($font)); + $draw->setFontSize($size); + $draw->setFillColor($col); + $draw->setFillAlpha(1-hexdec($alp)/127); + $draw->setTextAntialias(true); + $draw->setStrokeAntialias(true); + + $metrics = $this->im->queryFontMetrics($draw, $text); + + /* 计算文字初始坐标和尺寸 */ + $x = 0; + $y = $metrics['ascender']; + $w = $metrics['textWidth']; + $h = $metrics['textHeight']; + + /* 设定文字位置 */ + switch ($locate) { + /* 右下角文字 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x += $this->info['width'] - $w; + $y += $this->info['height'] - $h; + break; + + /* 左下角文字 */ + case THINKIMAGE_WATER_SOUTHWEST: + $y += $this->info['height'] - $h; + break; + + /* 左上角文字 */ + case THINKIMAGE_WATER_NORTHWEST: + // 起始坐标即为左上角坐标,无需调整 + break; + + /* 右上角文字 */ + case THINKIMAGE_WATER_NORTHEAST: + $x += $this->info['width'] - $w; + break; + + /* 居中文字 */ + case THINKIMAGE_WATER_CENTER: + $x += ($this->info['width'] - $w)/2; + $y += ($this->info['height'] - $h)/2; + break; + + /* 下居中文字 */ + case THINKIMAGE_WATER_SOUTH: + $x += ($this->info['width'] - $w)/2; + $y += $this->info['height'] - $h; + break; + + /* 右居中文字 */ + case THINKIMAGE_WATER_EAST: + $x += $this->info['width'] - $w; + $y += ($this->info['height'] - $h)/2; + break; + + /* 上居中文字 */ + case THINKIMAGE_WATER_NORTH: + $x += ($this->info['width'] - $w)/2; + break; + + /* 左居中文字 */ + case THINKIMAGE_WATER_WEST: + $y += ($this->info['height'] - $h)/2; + break; + + default: + /* 自定义文字坐标 */ + if(is_array($locate)){ + list($posx, $posy) = $locate; + $x += $posx; + $y += $posy; + } else { + throw new \Exception('不支持的文字位置类型'); + } + } + + /* 设置偏移量 */ + if(is_array($offset)){ + $offset = array_map('intval', $offset); + list($ox, $oy) = $offset; + } else{ + $offset = intval($offset); + $ox = $oy = $offset; + } + + /* 写入文字 */ + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + do{ + $img->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + + } else { + $this->im->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); + } + $draw->destroy(); + } + + /** + * 析构方法,用于销毁图像资源 + */ + public function __destruct() { + empty($this->im) || $this->im->destroy(); + } +} diff --git a/Library/Think/Input.php b/Library/Think/Input.php new file mode 100644 index 00000000..b6d14ebc --- /dev/null +++ b/Library/Think/Input.php @@ -0,0 +1,90 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Input { + // 全局过滤规则 + static $filter = NULL; + + /** + * 获取系统变量 支持过滤和默认值 + * @access public + * @param string $type 输入数据类型 + * @param array $args 参数 array(key,filter,default) + * @return mixed + */ + static public function __callStatic($type,$args=[]) { + switch(strtolower($type)) { + case 'get': $input =& $_GET;break; + case 'post': $input =& $_POST;break; + case 'put' : parse_str(file_get_contents('php://input'), $input);break; + case 'param' : + switch($_SERVER['REQUEST_METHOD']) { + case 'POST': + $input = $_POST; + break; + case 'PUT': + parse_str(file_get_contents('php://input'), $input); + break; + default: + $input = $_GET; + } + break; + case 'request': $input =& $_REQUEST;break; + case 'server': $input =& $_SERVER;break; + case 'cookie': $input =& $_COOKIE;break; + case 'session': $input =& $_SESSION;break; + case 'globals': $input =& $GLOBALS;break; + default:return NULL; + } + // 变量全局过滤 + array_walk_recursive($input,'self::filter_exp'); + if(self::$filter) { + $_filters = explode(',',self::$filter); + foreach($_filters as $_filter){ + // 全局参数过滤 + array_walk_recursive($input,$_filter); + } + } + if(''== $args[0]) { + // 返回全部数据 + return $input; + }elseif(isset($input[$args[0]])) { + $data = $input[$args[0]]; + if(!empty($args[1])) { + $filters = explode(',',$args[1]); + foreach($filters as $filter){ + if(is_callable($filter)) { + $data = is_array($data)?array_map($filter,$data):$filter($data); // 参数过滤 + }else{ + $data = filter_var($data,is_int($filter)?$filter:filter_id($filter)); + if(false === $data) { + return isset($args[2])?$args[2]:NULL; + } + } + } + } + + }else{ + // 不存在指定输入 + $data = isset($args[2])?$args[2]:NULL; + } + return $data; + } + + // 过滤表单中的表达式 + static private function filter_exp(&$value){ + if (in_array(strtolower($value),['exp','or'])){ + $value .= ' '; + } + } +} diff --git a/Library/Think/Lang.php b/Library/Think/Lang.php new file mode 100644 index 00000000..d4c17fd8 --- /dev/null +++ b/Library/Think/Lang.php @@ -0,0 +1,54 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Lang { + static private $_lang = []; // 语言参数 + static private $_range = '_sys_'; // 作用域 + + // 设定语言参数的作用域 + static public function range($range){ + self::$_range = $range; + } + + /** + * 设置语言定义(不区分大小写) + * @param string|array $name 语言变量 + * @param string $value 语言值 + * @param string $range 作用域 + * @return mixed + */ + static public function set($name, $value=null,$range='') { + $range = $range?$range:self::$_range; + // 批量定义 + if (is_array($name)){ + return self::$_lang[$range] = array_merge(self::$_lang[$range], array_change_key_case($name)); + }else{ + return self::$_lang[$range][strtolower($name)] = $value; + } + } + + /** + * 获取语言定义(不区分大小写) + * @param string|null $name 语言变量 + * @param string $range 作用域 + * @return mixed + */ + static public function get($name=null, $range='') { + $range = $range?$range:self::$_range; + // 空参数返回所有定义 + if (empty($name)) + return self::$_lang[$range]; + $name = strtolower($name); + return isset(self::$_lang[$range][$name]) ? self::$_lang[$range][$name] : $name; + } +} diff --git a/Library/Think/Loader.php b/Library/Think/Loader.php new file mode 100644 index 00000000..52038331 --- /dev/null +++ b/Library/Think/Loader.php @@ -0,0 +1,233 @@ + +// +---------------------------------------------------------------------- + +namespace Think; +use Think\Config; + +class Loader { + // 类名映射 + static protected $map = []; + // 命名空间 + static protected $namespace = []; + + // 自动加载 + static public function autoload($class){ + // 检查是否定义classmap + if(isset(self::$map[$class])) { + include self::$map[$class]; + }else{ // 命名空间自动加载 + $name = strstr($class, '\\', true); + if(isset(self::$namespace[$name])){ // 注册的命名空间 + $path = dirname(self::$namespace[$name]) . '/'; + }elseif(is_dir(LIB_PATH.$name)){ // Library目录下面的命名空间自动定位 + $path = LIB_PATH; + }else{ // 项目命名空间 + $path = APP_PATH; + } + //$path = isset(self::$namespace[$name]) ? dirname(self::$namespace[$name]) . '/' : APP_PATH; + $filename = $path . str_replace('\\', '/', $class) . EXT; + if(is_file($filename)) { + // Win环境下面严格区分大小写 + if (IS_WIN && false === strpos(str_replace('/', '\\', realpath($filename)), $class . EXT)){ + return ; + } + include $filename; + } + } + } + + // 注册classmap + static public function addMap($class, $map=''){ + if(is_array($class)){ + self::$map = array_merge(self::$map, $class); + }else{ + self::$map[$class] = $map; + } + } + + // 注册命名空间 + static public function addNamespace($namespace, $path){ + self::$namespace[$namespace] = $path; + } + + // 注册自动加载机制 + static public function register($autoload = ''){ + spl_autoload_register($autoload ? $autoload : ['Think\Loader', 'autoload']); + } + + /** + * 导入所需的类库 同java的Import 本函数有缓存功能 + * @param string $class 类库命名空间字符串 + * @param string $baseUrl 起始路径 + * @param string $ext 导入的文件扩展名 + * @return boolean + */ + static public function import($class, $baseUrl = '', $ext= EXT ) { + static $_file = []; + $class = str_replace(['.', '#'], ['/', '.'], $class); + if (isset($_file[$class . $baseUrl])) + return true; + else + $_file[$class . $baseUrl] = true; + $class_strut = explode('/', $class); + if (empty($baseUrl)) { + if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) { + //加载当前项目应用类库 + $class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1); + $baseUrl = MODULE_PATH; + }elseif (in_array($class_strut[0], ['Think','Org', 'Com'])) { + // org 第三方公共类库 com 企业公共类库 + $baseUrl = LIB_PATH; + }elseif(in_array($class_strut[0], ['Vendor', 'Traits'])){ + $baseUrl = THINK_PATH; + }else { // 加载其他项目应用类库 + $class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1); + $baseUrl = APP_PATH . $class_strut[0] . '/'; + } + } + if (substr($baseUrl, -1) != '/') + $baseUrl .= '/'; + // 如果类存在 则导入类库文件 + $filename = $baseUrl . $class . $ext; + if(is_file($filename)) { + include $filename; + return true; + } + return false; + } + + /** + * 实例化一个没有模型文件的Model(对应数据表) + * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User + * @param array $options 模型参数 + * @return Model + */ + static public function table($name = '', $options=[]) { + static $_model = []; + if(strpos($name, ':')) { + list($class, $name) = explode(':', $name); + }else{ + $class = 'Think\Model'; + } + $guid = $name . '_' . $class; + if (!isset($_model[$guid])) + $_model[$guid] = new $class($name, $options); + return $_model[$guid]; + } + + /** + * 实例化(分层)模型 + * @param string $name Model名称 + * @param string $layer 业务层名称 + * @return Object + */ + static public function model($name = '', $layer = 'Model') { + if(empty($name)) return new Model; + static $_model = []; + if(isset($_model[$name . $layer])) return $_model[$name . $layer]; + if(strpos($name, '/')) { + list($module, $name) = explode('/', $name); + }else{ + $module = MODULE_NAME; + } + $class = $module . '\\' . $layer . '\\' . parse_name($name, 1). $layer; + if(class_exists($class)) { + $model = new $class($name); + }else { + Log::record('实例化不存在的类:' . $class, 'NOTIC'); + $model = new Model($name); + } + $_model[$name . $layer] = $model; + return $model; + } + + /** + * 实例化(分层)控制器 格式:[模块名/]控制器名 + * @param string $name 资源地址 + * @param string $layer 控制层名称 + * @return Object|false + */ + static public function controller($name, $layer = 'Controller') { + static $_instance = []; + if(isset($_instance[$name.$layer])) return $_instance[$name . $layer]; + if(strpos($name, '/')) { + list($module,$name) = explode('/', $name); + }else{ + $module = MODULE_NAME; + } + $class = $module . '\\' . $layer . '\\' . parse_name($name, 1) . $layer; + if(class_exists($class)) { + $action = new $class; + $_instance[$name . $layer] = $action; + return $action; + }elseif(class_exists($module . '\\' . $layer . '\\Empty' . $layer)){ + $class = $module . '\\' . $layer . '\\Empty' . $layer; + return new $class; + }else{ + return false; + } + } + + /** + * 实例化数据库 + * @param mixed $config 数据库配置 + * @param boolean $lite 是否采用lite方式连接 + * @return object + */ + static public function db($config, $lite = false) { + return Db::instance($config, $lite); + } + + /** + * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 + * @param string $url 调用地址 + * @param string|array $vars 调用参数 支持字符串和数组 + * @param string $layer 要调用的控制层名称 + * @return mixed + */ + static public function action($url, $vars = [], $layer = 'Controller') { + $info = pathinfo($url); + $action = $info['basename']; + $module = '.' != $info['dirname'] ? $info['dirname'] : CONTROLLER_NAME; + $class = self::controller($module, $layer); + if($class){ + if(is_string($vars)) { + parse_str($vars, $vars); + } + return call_user_func_array([&$class, $action . Config::get('action_suffix')], $vars); + }else{ + return false; + } + } + + /** + * 取得对象实例 支持调用类的静态方法 + * @param string $class 对象类名 + * @param string $method 类的静态方法名 + * @return object + */ + static public function instance($class, $method = '') { + static $_instance = []; + $identify = $class . $method; + if(!isset($_instance[$identify])) { + if(class_exists($class)){ + $o = new $class(); + if(!empty($method) && method_exists($o, $method)) + $_instance[$identify] = call_user_func_array([&$o, $method]); + else + $_instance[$identify] = $o; + } + else + E('_CLASS_NOT_EXIST_:' . $class); + } + return $_instance[$identify]; + } +} diff --git a/Library/Think/Log.php b/Library/Think/Log.php new file mode 100644 index 00000000..00e5689f --- /dev/null +++ b/Library/Think/Log.php @@ -0,0 +1,84 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Log { + // 日志信息 + static protected $log = []; + static protected $level = ['ERR','NOTIC','DEBUG','SQL','INFO']; + static protected $storage = null; + + // 日志初始化 + static public function init($config=[]){ + $type = isset($config['type'])?$config['type']:'File'; + $class = 'Think\\Log\\Driver\\'. ucwords($type); + unset($config['type']); + self::$storage = new $class($config); + } + + /** + * 记录日志 并且会过滤未经设置的级别 + * @access public + * @param string $message 日志信息 + * @param string $level 日志级别 + * @param boolean $record 是否强制记录 + * @return void + */ + static public function record($message,$level='INFO') { + self::$log[$level][] = "{$level}: {$message}"; + } + + /** + * 获取内存中的日志信息 + * @access public + * @param string $level 日志级别 + * @return array + */ + static public function getLog($level=''){ + return $level?self::$log[$level]:self::$log; + } + + /** + * 日志保存 + * @access public + * @param string $destination 写入目标 + * @param string $level 保存的日志级别 + * @return void + */ + static public function save($destination='',$level='') { + $log = $level?self::$log[$level]:self::$log; + if(empty($log)) return ; + $message = ''; + if($level) { + $message .= implode("\r\n",$log); + self::$log[$level] = []; + }else{ + foreach($log as $info){ + $message .= implode("\r\n",$info)."\r\n"; + } + self::$log = []; + } + self::$storage && self::$storage->write($message,$destination); + } + + /** + * 日志直接写入 + * @access public + * @param string $log 日志信息 + * @param string $level 日志级别 + * @param string $destination 写入目标 + * @return void + */ + static public function write($log,$level,$destination='') { + self::$storage && self::$storage->write("{$level}: {$log}",$destination); + } +} diff --git a/Library/Think/Log/Driver/File.php b/Library/Think/Log/Driver/File.php new file mode 100644 index 00000000..1c2e81d3 --- /dev/null +++ b/Library/Think/Log/Driver/File.php @@ -0,0 +1,43 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Log\Driver; + +class File { + + protected $config = [ + 'log_time_format' => ' c ', + 'log_file_size' => 2097152, + 'log_path' => '', + ]; + + // 实例化并传入参数 + public function __construct($config=[]){ + $this->config = array_merge($this->config,$config); + } + + /** + * 日志写入接口 + * @access public + * @param string $log 日志信息 + * @param string $destination 写入目标 + * @return void + */ + public function write($log,$destination='') { + $now = date($this->config['log_time_format']); + if(empty($destination)) + $destination = $this->config['log_path'].date('y_m_d').'.log'; + //检测日志文件大小,超过配置大小则备份日志文件重新生成 + if(is_file($destination) && floor($this->config['log_file_size']) <= filesize($destination) ) + rename($destination,dirname($destination).'/'.time().'-'.basename($destination)); + error_log("[{$now}] ".$_SERVER['REMOTE_ADDR'].' '.$_SERVER['REQUEST_URI']."\r\n{$log}\r\n", 3,$destination); + } +} diff --git a/Library/Think/Model.php b/Library/Think/Model.php new file mode 100644 index 00000000..89d54ca2 --- /dev/null +++ b/Library/Think/Model.php @@ -0,0 +1,1031 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Model { + // 操作状态 + const MODEL_INSERT = 1; // 插入模型数据 + const MODEL_UPDATE = 2; // 更新模型数据 + const MODEL_BOTH = 3; // 包含上面两种方式 + // 当前数据库操作对象 + protected $db = null; + // 主键名称 + protected $pk = 'id'; + // 数据表前缀 + protected $tablePrefix = ''; + // 模型名称 + protected $name = ''; + // 数据库名称 + protected $dbName = ''; + //数据库配置 + protected $connection = ''; + // 数据表名(不包含表前缀) + protected $tableName = ''; + // 实际数据表名(包含表前缀) + protected $trueTableName = ''; + // 最近错误信息 + protected $error = ''; + // 字段信息 + protected $fields = []; + // 数据信息 + protected $data = []; + // 查询表达式参数 + protected $options = []; + // 命名范围定义 + protected $scope = []; + // 字段映射定义 + protected $map = []; + // 是否自动检测数据表字段信息 + protected $autoCheckFields = false; + + /** + * 架构函数 + * 取得DB类的实例对象 字段检查 + * @access public + * @param string $name 模型名称 + * @param array $config 模型配置 + */ + public function __construct($name='',$config=[]) { + // 模型初始化 + $this->_initialize(); + // 传入模型参数 + if(!empty($name)){ + $this->name = $name; + }elseif(empty($this->name)){ + $this->name = $this->getModelName(); + } + if(strpos($this->name,'.')) { // 支持 数据库名.模型名的 定义 + list($this->dbName,$this->name) = explode('.',$this->name); + } + + if(isset($config['table_prefix'])) { + $this->tablePrefix = $config['table_prefix']; + } + if(isset($config['connection'])) { + $this->connection = $config['connection']; + } + if(isset($config['table_name'])) { + $this->tableName = $config['table_name']; + } + if(isset($config['true_table_name'])) { + $this->trueTableName = $config['true_table_name']; + } + if(isset($config['db_name'])) { + $this->dbName = $config['db_name']; + } + + // 设置表前缀 + if(empty($this->tablePrefix)) { + $this->tablePrefix = is_null($this->tablePrefix)?'':C('database.prefix'); + } + + // 数据库初始化操作 + // 获取数据库操作对象 + // 当前模型有独立的数据库连接信息 + $this->db(0,$this->connection); + } + + /** + * 设置数据对象的值 + * @access public + * @param string $name 名称 + * @param mixed $value 值 + * @return void + */ + public function __set($name,$value) { + // 设置数据对象属性 + $this->data[$name] = $value; + } + + /** + * 获取数据对象的值 + * @access public + * @param string $name 名称 + * @return mixed + */ + public function __get($name) { + return isset($this->data[$name])?$this->data[$name]:null; + } + + /** + * 检测数据对象的值 + * @access public + * @param string $name 名称 + * @return boolean + */ + public function __isset($name) { + return isset($this->data[$name]); + } + + /** + * 销毁数据对象的值 + * @access public + * @param string $name 名称 + * @return void + */ + public function __unset($name) { + unset($this->data[$name]); + } + + // 回调方法 初始化模型 + protected function _initialize() {} + + /** + * 对写入到数据库的数据进行处理 + * @access protected + * @param mixed $data 要操作的数据 + * @return array + */ + protected function _write_data($data) { + // 检查字段映射 + if(!empty($this->map)) { + foreach ($this->map as $key=>$val){ + if(isset($data[$key])) { + $data[$val] = $data[$key]; + unset($data[$key]); + } + } + } + // 检查非数据字段 + if(!empty($this->fields)) { + foreach ($data as $key=>$val){ + if(!in_array($key,$this->fields,true)){ + unset($data[$key]); + }elseif(is_scalar($val) && empty($this->options['bind'][':'.$key])) { + // 字段类型检查 + $this->_parseType($data,$key); + } + } + } + // 安全过滤 + if(!empty($this->options['filter'])) { + $data = array_map($this->options['filter'],$data); + unset($this->options['filter']); + } + // 回调方法 + $this->_before_write($data); + return $data; + } + // 写入数据前的回调方法 包括新增和更新 + protected function _before_write(&$data) {} + + /** + * 新增数据 + * @access public + * @param mixed $data 数据 + * @param boolean $replace 是否replace + * @return mixed + */ + public function add($data='',$replace=false) { + if(empty($data)) { + // 没有传递数据,获取当前数据对象的值 + if(!empty($this->data)) { + $data = $this->data; + // 重置数据 + $this->data = []; + }else{ + $this->error = L('_DATA_TYPE_INVALID_'); + return false; + } + } + // 数据处理 + $data = $this->_write_data($data); + // 分析表达式 + $options = $this->_parseOptions(); + if(false === $this->_before_insert($data,$options)) { + return false; + } + // 写入数据到数据库 + $result = $this->db->insert($data,$options,$replace); + if(false !== $result ) { + $insertId = $this->getLastInsID(); + if($insertId) { + // 自增主键返回插入ID + $data[$this->getPk()] = $insertId; + $this->_after_insert($data,$options); + return $insertId; + } + $this->_after_insert($data,$options); + } + return $result; + } + // 插入数据前的回调方法 + protected function _before_insert(&$data,$options) {} + // 插入成功后的回调方法 + protected function _after_insert($data,$options) {} + + /** + * 保存数据 + * @access public + * @param mixed $data 数据 + * @return boolean + */ + public function save($data='') { + if(empty($data)) { + // 没有传递数据,获取当前数据对象的值 + if(!empty($this->data)) { + $data = $this->data; + // 重置数据 + $this->data = []; + }else{ + $this->error = L('_DATA_TYPE_INVALID_'); + return false; + } + } + // 数据处理 + $data = $this->_write_data($data); + // 分析表达式 + $options = $this->_parseOptions(); + if(false === $this->_before_update($data,$options)) { + return false; + } + if(!isset($options['where']) ) { + // 如果存在主键数据 则自动作为更新条件 + if(isset($data[$this->getPk()])) { + $pk = $this->getPk(); + $where[$pk] = $data[$pk]; + $options['where'] = $where; + $pkValue = $data[$pk]; + unset($data[$pk]); + }else{ + // 如果没有任何更新条件则不执行 + $this->error = Lang::get('_OPERATION_WRONG_'); + return false; + } + } + $result = $this->db->update($data,$options); + if(false !== $result) { + if(isset($pkValue)) $data[$pk] = $pkValue; + $this->_after_update($data,$options); + } + return $result; + } + // 更新数据前的回调方法 + protected function _before_update(&$data,$options) {} + // 更新成功后的回调方法 + protected function _after_update($data,$options) {} + + /** + * 删除数据 + * @access public + * @param mixed $options 表达式 + * @return mixed + */ + public function delete($options=[]) { + if(empty($options) && empty($this->options['where'])) { + // 如果删除条件为空 则删除当前数据对象所对应的记录 + if(!empty($this->data) && isset($this->data[$this->getPk()])) + return $this->delete($this->data[$this->getPk()]); + else + return false; + } + if(is_numeric($options) || is_string($options)) { + // 根据主键删除记录 + $pk = $this->getPk(); + if(strpos($options,',')) { + $where[$pk] = ['IN', $options]; + }else{ + $where[$pk] = $options; + } + $pkValue = $where[$pk]; + $options = []; + $options['where'] = $where; + } + // 分析表达式 + $options = $this->_parseOptions($options); + $result= $this->db->delete($options); + if(false !== $result) { + $data = []; + if(isset($pkValue)) $data[$pk] = $pkValue; + $this->_after_delete($data,$options); + } + // 返回删除记录个数 + return $result; + } + // 删除成功后的回调方法 + protected function _after_delete($data,$options) {} + + /** + * 查询数据集 + * @access public + * @param mixed $options 表达式参数 + * @return mixed + */ + public function select($options=[]) { + if(is_string($options) || is_numeric($options)) { + // 根据主键查询 + $pk = $this->getPk(); + if(strpos($options,',')) { + $where[$pk] = ['IN',$options]; + }else{ + $where[$pk] = $options; + } + $options = []; + $options['where'] = $where; + }elseif(false === $options){ // 用于子查询 不查询只返回SQL + $options = []; + // 分析表达式 + $options = $this->_parseOptions($options); + return '( '.$this->db->buildSelectSql($options).' )'; + } + // 分析表达式 + $options = $this->_parseOptions($options); + $resultSet = $this->db->select($options); + if(false === $resultSet) { + return false; + } + if(empty($resultSet)) { // 查询结果为空 + return null; + } + // 数据列表读取后的处理 + $resultSet = $this->_read_datalist($resultSet); + return $resultSet; + } + + /** + * 数据列表读取后的处理 + * @access protected + * @param array $data 当前数据 + * @return array + */ + protected function _read_datalist($resultSet) { + $resultSet = array_map([$this,'_read_data'],$resultSet); + $this->_after_select($resultSet); + return $resultSet; + } + // 查询成功后的回调方法 + protected function _after_select(&$resultSet) {} + + /** + * 生成查询SQL 可用于子查询 + * @access public + * @param array $options 表达式参数 + * @return string + */ + public function buildSql($options=[]) { + // 分析表达式 + $options = $this->_parseOptions($options); + return '( '.$this->db->buildSelectSql($options).' )'; + } + + /** + * 分析表达式(可用于查询或者写入操作) + * @access protected + * @param array $options 表达式参数 + * @return array + */ + protected function _parseOptions($options=[]) { + if(is_array($options)) + $options = array_merge($this->options,$options); + // 查询过后清空sql表达式组装 避免影响下次查询 + $this->options = []; + + if(!empty($options['alias'])) { + $options['table'] .= ' '.$options['alias']; + } + // 记录操作的模型名称 + $options['model'] = $this->name; + + if(isset($options['table'])) {// 动态指定表名 + $fields = $this->db->getFields($options['table']); + $fields = $fields?array_keys($fields):false; + }else{ + $options['table'] = $this->getTableName(); + $fields = $this->getDbFields(); + } + // 字段类型验证 + if(isset($options['where']) && is_array($options['where']) && !empty($fields)) { + // 对数组查询条件进行字段类型检查 + foreach ($options['where'] as $key=>$val){ + $key = trim($key); + if(in_array($key,$fields,true)){ + if(is_scalar($val) && empty($options['bind'][':'.$key])) { + $this->_parseType($options['where'],$key); + } + }elseif('_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){ + unset($options['where'][$key]); + } + } + } + // 表达式过滤 + $this->_options_filter($options); + return $options; + } + // 表达式过滤回调方法 + protected function _options_filter(&$options) {} + + /** + * 数据类型检测 + * @access protected + * @param mixed $data 数据 + * @param string $key 字段名 + * @return void + */ + protected function _parseType(&$data,$key) { + if(isset($this->fields['_type'][$key])) { + $fieldType = strtolower($this->fields['_type'][$key]); + if(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) { + $data[$key] = intval($data[$key]); + }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){ + $data[$key] = floatval($data[$key]); + }elseif(false !== strpos($fieldType,'bool')){ + $data[$key] = (bool)$data[$key]; + } + } + } + + /** + * 查询数据 + * @access public + * @param mixed $options 表达式参数 + * @return mixed + */ + public function find($options=[]) { + if(is_numeric($options) || is_string($options)) { + $where[$this->getPk()] = $options; + $options = []; + $options['where'] = $where; + } + // 总是查找一条记录 + $options['limit'] = 1; + // 分析表达式 + $options = $this->_parseOptions($options); + $resultSet = $this->db->select($options); + if(false === $resultSet) { + return false; + } + if(empty($resultSet)) {// 查询结果为空 + return null; + } + // 数据处理 + $data = $this->_read_data($resultSet[0]); + // 数据对象赋值 + $this->data = $data; + return $this->data; + } + + /** + * 数据读取后的处理 + * @access protected + * @param array $data 当前数据 + * @return array + */ + protected function _read_data($data) { + // 检查字段映射 + if(!empty($this->map)) { + foreach ($this->map as $key=>$val){ + if(isset($data[$val])) { + $data[$key] = $data[$val]; + unset($data[$val]); + } + } + } + $this->_after_find($data); + return $data; + } + // 数据读取成功后的回调方法 + protected function _after_find(&$result) {} + + /** + * 创建数据对象 但不保存到数据库 + * @access public + * @param mixed $data 创建数据 + * @param string $type 状态 + * @return mixed + */ + public function create($data='',$type='') { + // 如果没有传值默认取POST数据 + if(empty($data)) { + $data = $_POST; + }elseif(is_object($data)){ + $data = get_object_vars($data); + } + // 验证数据 + if(empty($data) || !is_array($data)) { + $this->error = L('_DATA_TYPE_INVALID_'); + return false; + } + + // 状态 + $type = $type?$type:(!empty($data[$this->getPk()])?self::MODEL_UPDATE:self::MODEL_INSERT); + + // 检测提交字段的合法性 + if(isset($this->options['field'])) { // $this->field('field1,field2...')->create() + $fields = $this->options['field']; + unset($this->options['field']); + }elseif($type == self::MODEL_INSERT && isset($this->insertFields)) { + $fields = $this->insertFields; + }elseif($type == self::MODEL_UPDATE && isset($this->updateFields)) { + $fields = $this->updateFields; + } + if(isset($fields)) { + if(is_string($fields)) { + $fields = explode(',',$fields); + } + foreach ($data as $key=>$val){ + if(!in_array($key,$fields)) { + unset($data[$key]); + } + } + } + // 过滤创建的数据 + $this->_create_filter($data); + // 赋值当前数据对象 + $this->data = $data; + // 返回创建的数据以供其他调用 + return $data; + } + // 数据对象创建后的回调方法 + protected function _create_filter(&$data){} + + /** + * 切换当前的数据库连接 + * @access public + * @param integer $linkNum 连接序号 + * @param mixed $config 数据库连接信息 + * @return Model + */ + public function db($linkNum='',$config=''){ + if(''===$linkNum && $this->db) { + return $this->db; + } + static $_linkNum = []; + static $_db = []; + if(!isset($_db[$linkNum]) || (isset($_db[$linkNum]) && $config && $_linkNum[$linkNum]!=$config) ) { + // 创建一个新的实例 + if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数 + $config = C($config); + } + $_db[$linkNum] = Db::instance($config); + }elseif(NULL === $config){ + $_db[$linkNum]->close(); // 关闭数据库连接 + unset($_db[$linkNum]); + return ; + } + + // 记录连接信息 + $_linkNum[$linkNum] = $config; + // 切换数据库连接 + $this->db = $_db[$linkNum]; + $this->_after_db(); + return $this; + } + // 数据库切换后回调方法 + protected function _after_db() {} + + /** + * 得到当前的数据对象名称 + * @access public + * @return string + */ + public function getModelName() { + if(empty($this->name)) + $this->name = substr(get_class($this),0,-5); + return $this->name; + } + + /** + * 得到完整的数据表名 + * @access public + * @return string + */ + public function getTableName() { + if(empty($this->trueTableName)) { + $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; + if(!empty($this->tableName)) { + $tableName .= $this->tableName; + }else{ + $tableName .= parse_name($this->name); + } + $this->trueTableName = strtolower($tableName); + } + return (!empty($this->dbName)?$this->dbName.'.':'').$this->trueTableName; + } + + /** + * 返回模型的错误信息 + * @access public + * @return string + */ + public function getError(){ + return $this->error; + } + + /** + * 返回数据库的错误信息 + * @access public + * @return string + */ + public function getDbError() { + return $this->db->getError(); + } + + /** + * 返回最后插入的ID + * @access public + * @return string + */ + public function getLastInsID() { + return $this->db->getLastInsID(); + } + + /** + * 返回最后执行的sql语句 + * @access public + * @return string + */ + public function getLastSql() { + return $this->db->getLastSql($this->name); + } + + /** + * 获取主键名称 + * @access public + * @return string + */ + public function getPk() { + return isset($this->fields['_pk'])?$this->fields['_pk']:$this->pk; + } + + /** + * 获取数据表字段信息 + * @access public + * @return array + */ + public function getDbFields(){ + if($this->fields) { + $fields = $this->fields; + unset($fields['_pk'],$fields['_type']); + return $fields; + }else{ + $fields = Cache::get(md5($this->getTableName())); + if(!$fields) { + $fields = $this->db->getFields($this->getTableName()); + $this->fields = array_keys($fields); + foreach ($fields as $key=>$val){ + // 记录字段类型 + $type[$key] = $val['type']; + if($val['primary']) { + $this->fields['_pk'] = $key; + } + } + // 记录字段类型信息 + $this->fields['_type'] = $type; + Cache::set(md5($this->trueTableName),$this->fields); + $fields = $this->fields; + }else{ + $this->fields = $fields; + } + unset($fields['_pk'],$fields['_type']); + return $fields; + } + } + + /** + * SQL查询 + * @access public + * @param string $sql SQL指令 + * @param array $bind 参数绑定 + * @return mixed + */ + public function query($sql,$bind=[]) { + $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); + return $this->db->query($sql,$bind); + } + + /** + * 执行SQL语句 + * @access public + * @param string $sql SQL指令 + * @param array $bind 参数绑定 + * @return false | integer + */ + public function execute($sql,$bind=[]) { + $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); + return $this->db->execute($sql,$bind); + } + + /** + * 设置数据对象值 + * @access public + * @param mixed $data 数据 + * @return Model + */ + public function data($data=''){ + if('' === $data && !empty($this->data)) { + return $this->data; + } + if(is_object($data)){ + $data = get_object_vars($data); + }elseif(is_string($data)){ + parse_str($data,$data); + }elseif(!is_array($data)){ + E(L('_DATA_TYPE_INVALID_')); + } + $this->data = $data; + return $this; + } + + /** + * 查询SQL组装 join + * @access public + * @param mixed $join + * @return Model + */ + public function join($join) { + if(is_array($join)) { + $this->options['join'] = $join; + }elseif(!empty($join)) { + $this->options['join'][] = $join; + } + return $this; + } + + /** + * 查询SQL组装 union + * @access public + * @param mixed $union + * @param boolean $all + * @return Model + */ + public function union($union,$all=false) { + if(empty($union)) return $this; + if($all) { + $this->options['union']['_all'] = true; + } + if(is_object($union)) { + $union = get_object_vars($union); + } + // 转换union表达式 + if(is_string($union) ) { + $options = $union; + }elseif(is_array($union)){ + if(isset($union[0])) { + $this->options['union'] = array_merge($this->options['union'],$union); + return $this; + }else{ + $options = $union; + } + }else{ + E(L('_DATA_TYPE_INVALID_')); + } + $this->options['union'][] = $options; + return $this; + } + + /** + * 查询缓存 + * @access public + * @param mixed $key + * @param integer $expire + * @param string $type + * @return Model + */ + public function cache($key=true,$expire=null,$type=''){ + if(false !== $key) + $this->options['cache'] = ['key'=>$key,'expire'=>$expire,'type'=>$type]; + return $this; + } + + /** + * 指定查询字段 支持字段排除 + * @access public + * @param mixed $field + * @param boolean $except 是否排除 + * @return Model + */ + public function field($field,$except=false){ + if(true === $field) {// 获取全部字段 + $fields = $this->getDbFields(); + $field = $fields?$fields:'*'; + }elseif($except) {// 字段排除 + if(is_string($field)) { + $field = explode(',',$field); + } + $fields = $this->getDbFields(); + $field = $fields?array_diff($fields,$field):$field; + } + $this->options['field'] = $field; + return $this; + } + + /** + * 调用命名范围 + * @access public + * @param mixed $scope 命名范围名称 支持多个 和直接定义 + * @param array $args 参数 + * @return Model + */ + public function scope($scope='',$args=NULL){ + if('' === $scope) { + if(isset($this->scope['default'])) { + // 默认的命名范围 + $options = $this->scope['default']; + }else{ + return $this; + } + }elseif(is_string($scope)){ // 支持多个命名范围调用 用逗号分割 + $scopes = explode(',',$scope); + $options = []; + foreach ($scopes as $name){ + if(!isset($this->scope[$name])) continue; + $options = array_merge($options,$this->scope[$name]); + } + if(!empty($args) && is_array($args)) { + $options = array_merge($options,$args); + } + }elseif(is_array($scope)){ // 直接传入命名范围定义 + $options = $scope; + } + + if(is_array($options) && !empty($options)){ + $this->options = array_merge($this->options,array_change_key_case($options)); + } + return $this; + } + + /** + * 指定查询条件 支持安全过滤 + * @access public + * @param mixed $where 条件表达式 + * @param mixed $parse 预处理参数 + * @return Model + */ + public function where($where,$parse=null){ + if(!is_null($parse) && is_string($where)) { + if(!is_array($parse)) { + $parse = func_get_args(); + array_shift($parse); + } + $parse = array_map([$this->db,'escapeString'],$parse); + $where = vsprintf($where,$parse); + }elseif(is_object($where)){ + $where = get_object_vars($where); + } + if(is_string($where) && '' != $where){ + $map = []; + $map['_string'] = $where; + $where = $map; + } + if(isset($this->options['where'])){ + $this->options['where'] = array_merge($this->options['where'],$where); + }else{ + $this->options['where'] = $where; + } + return $this; + } + + /** + * 指定查询数量 + * @access public + * @param mixed $offset 起始位置 + * @param mixed $length 查询数量 + * @return Model + */ + public function limit($offset,$length=null){ + $this->options['limit'] = is_null($length)?$offset:$offset.','.$length; + return $this; + } + + /** + * 指定分页 + * @access public + * @param mixed $page 页数 + * @param mixed $listRows 每页数量 + * @return Model + */ + public function page($page,$listRows=null){ + $this->options['page'] = is_null($listRows)?$page:$page.','.$listRows; + return $this; + } + + /** + * 指定数据表 + * @access public + * @param string $table 表名 + * @return Model + */ + public function table($table){ + $this->options['table'] = $table; + return $this; + } + + /** + * 指定排序 + * @access public + * @param string $order 排序 + * @return Model + */ + public function order($order){ + $this->options['order'] = $order; + return $this; + } + + /** + * 指定group查询 + * @access public + * @param string $group GROUP + * @return Model + */ + public function group($group){ + $this->options['group'] = $group; + return $this; + } + + /** + * 指定having查询 + * @access public + * @param string $having having + * @return Model + */ + public function having($table){ + $this->options['having'] = $having; + return $this; + } + + /** + * 指定查询lock + * @access public + * @param boolean $lock 是否lock + * @return Model + */ + public function lock($lock=false){ + $this->options['lock'] = $lock; + return $this; + } + + /** + * 指定distinct查询 + * @access public + * @param string $distinct 是否唯一 + * @return Model + */ + public function distinct($distinct){ + $this->options['distinct'] = $distinct; + return $this; + } + + /** + * 指定数据表别名 + * @access public + * @param string $alias 数据表别名 + * @return Model + */ + public function alias($alias){ + $this->options['alias'] = $alias; + return $this; + } + + /** + * 指定写入过滤方法 + * @access public + * @param string $filter 指定过滤方法 + * @return Model + */ + public function filter($filter){ + $this->options['filter'] = $filter; + return $this; + } + + /** + * 指定参数绑定 + * @access public + * @param array $bind 指定参数绑定 + * @return Model + */ + public function bind($bind){ + $this->options['bind'] = $bind; + return $this; + } + + /** + * 查询注释 + * @access public + * @param string $comment 注释 + * @return Model + */ + public function comment($comment){ + $this->options['comment'] = $comment; + return $this; + } + + /** + * 设置字段映射 + * @access public + * @param array $map 映射 + * @return Model + */ + public function map($map){ + $this->map = $map; + return $this; + } +} \ No newline at end of file diff --git a/Library/Think/Model/ExtendModel.php b/Library/Think/Model/ExtendModel.php new file mode 100644 index 00000000..dc878991 --- /dev/null +++ b/Library/Think/Model/ExtendModel.php @@ -0,0 +1,18 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Model; +use Traits\Think\Model\Extend,Traits\Think\Model\Query; +T('Think/Model/Extend'); +T('Think/Model/Query'); +class ExtendModel extends \Think\Model { + use Extend,Query; +} \ No newline at end of file diff --git a/Library/Think/Model/MongoModel.php b/Library/Think/Model/MongoModel.php new file mode 100644 index 00000000..a3858e87 --- /dev/null +++ b/Library/Think/Model/MongoModel.php @@ -0,0 +1,274 @@ + +// +---------------------------------------------------------------------- +namespace Think\Model; +/** + * MongoModel模型类 + * 实现了ODM和ActiveRecords模式 + */ +class MongoModel extends \Think\Model{ + // 主键类型 + const TYPE_OBJECT = 1; + const TYPE_INT = 2; + const TYPE_STRING = 3; + + // 主键名称 + protected $pk = '_id'; + // _id 类型 1 Object 采用MongoId对象 2 Int 整形 支持自动增长 3 String 字符串Hash + protected $_idType = self::TYPE_OBJECT; + // 主键是否自动增长 支持Int型主键 + protected $_autoInc = false; + // Mongo默认关闭字段检测 可以动态追加字段 + protected $autoCheckFields = false; + + /** + * 利用__call方法实现一些特殊的Model方法 + * @access public + * @param string $method 方法名称 + * @param array $args 调用参数 + * @return mixed + */ + public function __call($method,$args) { + if(strtolower(substr($method,0,5))=='getby') { + // 根据某个字段获取记录 + $field = parse_name(substr($method,5)); + $where[$field] =$args[0]; + return $this->where($where)->find(); + }elseif(strtolower(substr($method,0,10))=='getfieldby') { + // 根据某个字段获取记录的某个值 + $name = parse_name(substr($method,10)); + $where[$name] =$args[0]; + return $this->where($where)->getField($args[1]); + }else{ + throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); + return; + } + } + + // 写入数据前的回调方法 包括新增和更新 + protected function _before_write(&$data) { + $pk = $this->getPk(); + // 根据主键类型处理主键数据 + if(isset($data[$pk]) && $this->_idType == self::TYPE_OBJECT) { + $data[$pk] = new MongoId($data[$pk]); + } + } + + /** + * count统计 配合where连贯操作 + * @access public + * @return integer + */ + public function count(){ + // 分析表达式 + $options = $this->_parseOptions(); + return $this->db->count($options); + } + + /** + * 获取下一ID 用于自动增长型 + * @access public + * @param string $pk 字段名 默认为主键 + * @return mixed + */ + public function getMongoNextId($pk=''){ + if(empty($pk)) { + $pk = $this->getPk(); + } + return $this->db->getMongoNextId($pk); + } + + // 插入数据前的回调方法 + protected function _before_insert(&$data,$options) { + // 写入数据到数据库 + if($this->_autoInc && $this->_idType== self::TYPE_INT) { // 主键自动增长 + $pk = $this->getPk(); + if(!isset($data[$pk])) { + $data[$pk] = $this->db->mongo_next_id($pk); + } + } + } + + public function clear(){ + return $this->db->clear(); + } + + // 查询成功后的回调方法 + protected function _after_select(&$resultSet,$options) { + array_walk($resultSet,array($this,'checkMongoId')); + } + + /** + * 获取MongoId + * @access protected + * @param array $result 返回数据 + * @return array + */ + protected function checkMongoId(&$result){ + if(is_object($result['_id'])) { + $result['_id'] = $result['_id']->__toString(); + } + return $result; + } + + // 表达式过滤回调方法 + protected function _options_filter(&$options) { + $id = $this->getPk(); + if(isset($options['where'][$id]) && is_scalar($options['where'][$id]) && $this->_idType== self::TYPE_OBJECT) { + $options['where'][$id] = new MongoId($options['where'][$id]); + } + } + + /** + * 查询数据 + * @access public + * @param mixed $options 表达式参数 + * @return mixed + */ + public function find($options=array()) { + if( is_numeric($options) || is_string($options)) { + $id = $this->getPk(); + $where[$id] = $options; + $options = array(); + $options['where'] = $where; + } + // 分析表达式 + $options = $this->_parseOptions($options); + $result = $this->db->find($options); + if(false === $result) { + return false; + } + if(empty($result)) {// 查询结果为空 + return null; + }else{ + $this->checkMongoId($result); + } + $this->data = $result; + $this->_after_find($this->data,$options); + return $this->data; + } + + /** + * 字段值增长 + * @access public + * @param string $field 字段名 + * @param integer $step 增长值 + * @return boolean + */ + public function setInc($field,$step=1) { + return $this->setField($field,array('inc',$step)); + } + + /** + * 字段值减少 + * @access public + * @param string $field 字段名 + * @param integer $step 减少值 + * @return boolean + */ + public function setDec($field,$step=1) { + return $this->setField($field,array('inc','-'.$step)); + } + + /** + * 获取一条记录的某个字段值 + * @access public + * @param string $field 字段名 + * @param string $spea 字段数据间隔符号 + * @return mixed + */ + public function getField($field,$sepa=null) { + $options['field'] = $field; + $options = $this->_parseOptions($options); + if(strpos($field,',')) { // 多字段 + if(is_numeric($sepa)) {// 限定数量 + $options['limit'] = $sepa; + $sepa = null;// 重置为null 返回数组 + } + $resultSet = $this->db->select($options); + if(!empty($resultSet)) { + $_field = explode(',', $field); + $field = array_keys($resultSet[0]); + $key = array_shift($field); + $key2 = array_shift($field); + $cols = array(); + $count = count($_field); + foreach ($resultSet as $result){ + $name = $result[$key]; + if(2==$count) { + $cols[$name] = $result[$key2]; + }else{ + $cols[$name] = is_null($sepa)?$result:implode($sepa,$result); + } + } + return $cols; + } + }else{ + // 返回数据个数 + if(true !== $sepa) {// 当sepa指定为true的时候 返回所有数据 + $options['limit'] = is_numeric($sepa)?$sepa:1; + } // 查找一条记录 + $result = $this->db->find($options); + if(!empty($result)) { + if(1==$options['limit']) return reset($result[0]); + foreach ($result as $val){ + $array[] = $val[$field]; + } + return $array; + } + } + return null; + } + + /** + * 执行Mongo指令 + * @access public + * @param array $command 指令 + * @return mixed + */ + public function command($command) { + return $this->db->command($command); + } + + /** + * 执行MongoCode + * @access public + * @param string $code MongoCode + * @param array $args 参数 + * @return mixed + */ + public function mongoCode($code,$args=array()) { + return $this->db->execute($code,$args); + } + + // 数据库切换后回调方法 + protected function _after_db() { + // 切换Collection + $this->db->switchCollection($this->getTableName(),$this->dbName); + } + + /** + * 得到完整的数据表名 Mongo表名不带dbName + * @access public + * @return string + */ + public function getTableName() { + if(empty($this->trueTableName)) { + $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; + if(!empty($this->tableName)) { + $tableName .= $this->tableName; + }else{ + $tableName .= parse_name($this->name); + } + $this->trueTableName = strtolower($tableName); + } + return $this->trueTableName; + } +} \ No newline at end of file diff --git a/Library/Think/Model/RelationModel.php b/Library/Think/Model/RelationModel.php new file mode 100644 index 00000000..4989bee3 --- /dev/null +++ b/Library/Think/Model/RelationModel.php @@ -0,0 +1,16 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Model; +T('Think/Model/Relation'); +class RelationModel extends \Think\Model { + use \Traits\Think\Model\Relation; +} \ No newline at end of file diff --git a/Library/Think/Model/ViewModel.php b/Library/Think/Model/ViewModel.php new file mode 100644 index 00000000..44faee86 --- /dev/null +++ b/Library/Think/Model/ViewModel.php @@ -0,0 +1,16 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Model; +T('Think/Model/View'); +class ViewModel extends \Think\Model { + use \Traits\Think\Model\View; +} \ No newline at end of file diff --git a/Library/Think/Oauth.php b/Library/Think/Oauth.php new file mode 100644 index 00000000..1a42de6c --- /dev/null +++ b/Library/Think/Oauth.php @@ -0,0 +1,71 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +// oauth登录接口 +// +// Oauth::connect('qq',['app_key'=>'','app_secret'=>'','callback'=>'','authorize'=>'']); // 链接QQ登录 +// Oauth::login(); // 跳转到授权登录页面 或者 Oauth::login($callbackUrl); +// Oauth::call('api','params'); // 调用API接口 +// +class Oauth { + + /** + * 操作句柄 + * @var object + * @access protected + */ + static protected $handler = null; + + /** + * 连接oauth + * @access public + * @param string $type Oauth类型 + * @param array $options 配置数组 + * @return object + */ + static public function connect($type,$options=[]) { + $class = 'Think\\Oauth\\Driver\\'.ucwords($type); + self::$handler = new $class($options); + return self::$handler; + } + + // 跳转到授权登录页面 + static public function login($callback=''){ + self::$handler->login($callback); + } + + // 获取access_token + static public function getAccessToken($code){ + self::$handler->getAccessToken($code); + } + + // 设置保存过的token信息 + static public function setToken($token){ + self::$handler->setToken($token); + } + + // 获取oauth用户信息 + static public function getOauthInfo(){ + return self::$handler->getOauthInfo(); + } + + // 获取openid信息 + static public function getOpenId(){ + return self::$handler->getOpenId(); + } + + // 调用oauth接口API + static public function call($api,$param='',$method='GET'){ + return self::$handler->call($api,$param,$method); + } +} diff --git a/Library/Think/Oauth/Driver.php b/Library/Think/Oauth/Driver.php new file mode 100644 index 00000000..cfb8938f --- /dev/null +++ b/Library/Think/Oauth/Driver.php @@ -0,0 +1,233 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth; +abstract class Driver { + + /** + * oauth版本 + * @var string + */ + protected $version = '2.0'; + + /** + * 申请应用时分配的app_key + * @var string + */ + protected $appKey = ''; + + /** + * 申请应用时分配的 app_secret + * @var string + */ + protected $appSecret = ''; + + /** + * 授权类型 response_type 目前只能为code + * @var string + */ + protected $responseType = 'code'; + + /** + * grant_type 目前只能为 authorization_code + * @var string + */ + protected $grantType = 'authorization_code'; + + /** + * 获取request_code请求的URL + * @var string + */ + protected $getRequestCodeURL = ''; + + /** + * 获取access_token请求的URL + * @var string + */ + protected $getAccessTokenURL = ''; + + /** + * API根路径 + * @var string + */ + protected $apiBase = ''; + + /** + * 授权后获取到的TOKEN信息 + * @var array + */ + protected $token = null; + + /** + * 回调页面URL 可以通过配置文件配置 + * @var string + */ + protected $callback = ''; + + /** + * 构造方法,配置应用信息 + * @param array $config + */ + public function __construct($config = []){ + $this->appKey = $config['app_key']; + $this->appSecret = $config['app_secret']; + $this->authorize = isset($config['authorize']) ? $config['authorize'] : ''; + $this->callback = isset($config['callback']) ? $config['callback'] : ''; + } + + // 跳转到授权登录页面 + public function login($callback = ''){ + if($callback) { + $this->callback = $callback; + } + //跳转到授权页面 + header('Location: ' . $this->getRequestCodeURL()); + exit; + } + + /** + * 请求code + */ + public function getRequestCodeURL(){ + //Oauth 标准参数 + $params = array( + 'client_id' => $this->appKey, + 'redirect_uri' => $this->callback, + 'response_type' => $this->responseType, + ); + + //获取额外参数 + if($this->authorize){ + parse_str($this->authorize, $_param); + if(is_array($_param)){ + $params = array_merge($params, $_param); + } else { + throw new \Exception('AUTHORIZE配置不正确!'); + } + } + return $this->getRequestCodeURL . '?' . http_build_query($params); + } + + /** + * 获取access_token + * @param string $code 授权登录成功后得到的code信息 + */ + public function getAccessToken($code){ + $params = array( + 'client_id' => $this->appKey, + 'client_secret' => $this->appSecret, + 'grant_type' => $this->grantType, + 'redirect_uri' => $this->callback, + 'code' => $code, + ); + // 获取token信息 + $data = $this->http($this->getAccessTokenURL, $params, 'POST'); + // 解析token + $this->token = $this->parseToken($data); + return $this->token; + } + + /** + * 设置access_token + * @param string $token + */ + public function setToken($token){ + $this->token = $token; + } + + /** + * 合并默认参数和额外参数 + * @param array $params 默认参数 + * @param array/string $param 额外参数 + * @return array: + */ + protected function param($params, $param){ + if(is_string($param)) + parse_str($param, $param); + return array_merge($params, $param); + } + + /** + * 获取指定API请求的URL + * @param string $api API名称 + * @param string $fix api后缀 + * @return string 请求的完整URL + */ + protected function url($api, $fix = ''){ + return $this->apiBase . $api . $fix; + } + + /** + * 发送HTTP请求方法,目前只支持CURL发送请求 + * @param string $url 请求URL + * @param array $params 请求参数 + * @param string $method 请求方法GET/POST + * @return array $data 响应数据 + */ + protected function http($url, $params, $method = 'GET', $header = [], $multi = false){ + $opts = array( + CURLOPT_TIMEOUT => 30, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_HTTPHEADER => $header + ); + + /* 根据请求类型设置特定参数 */ + switch(strtoupper($method)){ + case 'GET': + $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); + break; + case 'POST': + //判断是否传输文件 ++ $params = $multi ? $params : http_build_query($params); + $opts[CURLOPT_URL] = $url; + $opts[CURLOPT_POST] = 1; + $opts[CURLOPT_POSTFIELDS] = $params; + break; + default: + throw new \Exception('不支持的请求方式!'); + } + + /* 初始化并执行curl请求 */ + $ch = curl_init(); + curl_setopt_array($ch, $opts); + $data = curl_exec($ch); + $error = curl_error($ch); + curl_close($ch); + if($error) throw new \Exception('请求发生错误:' . $error); + return $data; + } + + /** + * 抽象方法,在SNSSDK中实现 + * 组装接口调用参数 并调用接口 + */ + abstract protected function call($api, $param = '', $method = 'GET', $multi = false); + + /** + * 抽象方法,在SNSSDK中实现 + * 解析access_token方法请求后的返回值 + */ + abstract protected function parseToken($result); + + /** + * 抽象方法,在SNSSDK中实现 + * 获取当前授权用户的SNS标识 + */ + abstract public function getOpenId(); + + /** + * 抽象方法 + * 获取当前授权用户的用户信息 + */ + abstract public function getOauthInfo(); +} diff --git a/Library/Think/Oauth/Driver/Baidu.php b/Library/Think/Oauth/Driver/Baidu.php new file mode 100644 index 00000000..0555af54 --- /dev/null +++ b/Library/Think/Oauth/Driver/Baidu.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Baidu extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://openapi.baidu.com/oauth/2.0/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://openapi.baidu.com/oauth/2.0/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://openapi.baidu.com/rest/2.0/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 百度API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 百度调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ + $data['openid'] = $this->openid(); + return $data; + } else + throw new \Exception("获取百度ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + $data = $this->call('passport/users/getLoggedInUser'); + return !empty($data['uid'])?$data['uid']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('passport/users/getLoggedInUser'); + + if(!empty($data['uid'])){ + $userInfo['type'] = 'BAIDU'; + $userInfo['name'] = $data['uid']; + $userInfo['nick'] = $data['uname']; + $userInfo['avatar'] = "http://tb.himg.baidu.com/sys/portrait/item/{$data['portrait']}"; + return $userInfo; + } else { + throw new \Exception("获取百度用户信息失败:{$data['error_msg']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Diandian.php b/Library/Think/Oauth/Driver/Diandian.php new file mode 100644 index 00000000..ecb467dc --- /dev/null +++ b/Library/Think/Oauth/Driver/Diandian.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Diandian extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://api.diandian.com/oauth/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://api.diandian.com/oauth/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.diandian.com/v1/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 点点网API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 点点网调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['token_type'] && $data['uid']){ + $data['openid'] = $data['uid']; + unset($data['uid']); + return $data; + } else + throw new \Exception("获取点点网ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('user/info'); + + if(!empty($data['meta']['status']) && $data['meta']['status'] == 200){ + $userInfo['type'] = 'DIANDIAN'; + $userInfo['name'] = $data['response']['name']; + $userInfo['nick'] = $data['response']['name']; + $userInfo['avatar'] = "https://api.diandian.com/v1/blog/{$data['response']['blogs'][0]['blogUuid']}/avatar/144"; + return $userInfo; + } else { + E("获取点点用户信息失败:{$data}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Douban.php b/Library/Think/Oauth/Driver/Douban.php new file mode 100644 index 00000000..47bb663c --- /dev/null +++ b/Library/Think/Oauth/Driver/Douban.php @@ -0,0 +1,91 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Douban extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://www.douban.com/service/auth2/auth'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://www.douban.com/service/auth2/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.douban.com/v2/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 豆瓣调用公共参数 */ + $params = []; + $header = array("Authorization: Bearer {$this->token['access_token']}"); + $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['douban_user_id']){ + $data['openid'] = $data['douban_user_id']; + unset($data['douban_user_id']); + return $data; + } else + throw new \Exception("获取豆瓣ACCESS_TOKEN出错:{$data['msg']}"); + } + + /** + * 获取当前授权应用的openid + * @return string|null + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('user/~me'); + + if(empty($data['code'])){ + $userInfo['type'] = 'DOUBAN'; + $userInfo['name'] = $data['name']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = $data['avatar']; + return $userInfo; + } else { + E("获取豆瓣用户信息失败:{$data['msg']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Github.php b/Library/Think/Oauth/Driver/Github.php new file mode 100644 index 00000000..55d06342 --- /dev/null +++ b/Library/Think/Oauth/Driver/Github.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Github extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://github.com/login/oauth/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://github.com/login/oauth/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.github.com/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* Github 调用公共参数 */ + $params = []; + $header = array("Authorization: bearer {$this->token['access_token']}"); + + $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + parse_str($result, $data); + if($data['access_token'] && $data['token_type']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取 Github ACCESS_TOKEN出错:未知错误"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + + $data = $this->call('user'); + return !empty($data['id'])?$data['id']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('user'); + + if(empty($data['code'])){ + $userInfo['type'] = 'GITHUB'; + $userInfo['name'] = $data['login']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = $data['avatar_url']; + return $userInfo; + } else { + E("获取Github用户信息失败:{$data}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Google.php b/Library/Think/Oauth/Driver/Google.php new file mode 100644 index 00000000..23ac7edb --- /dev/null +++ b/Library/Think/Oauth/Driver/Google.php @@ -0,0 +1,99 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Google extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://accounts.google.com/o/oauth2/auth'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://accounts.google.com/o/oauth2/token'; + + /** + * 获取request_code的额外参数 URL查询字符串格式 + * @var srting + */ + protected $authorize = 'scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://www.googleapis.com/oauth2/v1/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* Google 调用公共参数 */ + $params = []; + $header = array("Authorization: Bearer {$this->token['access_token']}"); + + $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['token_type'] && $data['expires_in']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取 Google ACCESS_TOKEN出错:未知错误"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + + $data = $this->call('userinfo'); + return !empty($data['id'])?$data['id']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('userinfo'); + + if(!empty($data['id'])){ + $userInfo['type'] = 'GOOGLE'; + $userInfo['name'] = $data['name']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = $data['picture']; + return $userInfo; + } else { + E("获取Google用户信息失败:{$data}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Kaixin.php b/Library/Think/Oauth/Driver/Kaixin.php new file mode 100644 index 00000000..7b140bfa --- /dev/null +++ b/Library/Think/Oauth/Driver/Kaixin.php @@ -0,0 +1,94 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Kaixin extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'http://api.kaixin001.com/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://api.kaixin001.com/oauth2/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.kaixin001.com/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 开心网API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 开心网调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取开心网ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + + $data = $this->call('users/me'); + return !empty($data['uid'])?$data['uid']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('users/me'); + + if(!empty($data['uid'])){ + $userInfo['type'] = 'KAIXIN'; + $userInfo['name'] = $data['uid']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = $data['logo50']; + return $userInfo; + } else { + E("获取开心网用户信息失败:{$data['error']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Msn.php b/Library/Think/Oauth/Driver/Msn.php new file mode 100644 index 00000000..18b49ff0 --- /dev/null +++ b/Library/Think/Oauth/Driver/Msn.php @@ -0,0 +1,100 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Msn extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://login.live.com/oauth20_authorize.srf'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://login.live.com/oauth20_token.srf'; + + /** + * 获取request_code的额外参数 URL查询字符串格式 + * @var srting + */ + protected $authorize = 'scope=wl.basic wl.offline_access wl.signin wl.emails wl.photos'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://apis.live.net/v5.0/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* MSN 调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['token_type'] && $data['expires_in']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取 MSN ACCESS_TOKEN出错:未知错误"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + + $data = $this->call('me'); + return !empty($data['id'])?$data['id']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('me'); + + if(!empty($data['id'])){ + $userInfo['type'] = 'MSN'; + $userInfo['name'] = $data['name']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = '微软暂未提供头像URL,请通过 me/picture 接口下载'; + return $userInfo; + } else { + E("获取msn用户信息失败:{$data}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Qq.php b/Library/Think/Oauth/Driver/Qq.php new file mode 100644 index 00000000..57eab290 --- /dev/null +++ b/Library/Think/Oauth/Driver/Qq.php @@ -0,0 +1,102 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Qq extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://graph.qq.com/oauth2.0/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://graph.qq.com/oauth2.0/token'; + + /** + * 获取request_code的额外参数,可在配置中修改 URL查询字符串格式 + * @var srting + */ + protected $authorize = 'scope=get_user_info,add_share'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://graph.qq.com/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 腾讯QQ调用公共参数 */ + $params = array( + 'oauth_consumer_key' => $this->AppKey, + 'access_token' => $this->token['access_token'], + 'openid' => $this->openid(), + 'format' => 'json' + ); + + $data = $this->http($this->url($api), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + parse_str($result, $data); + if($data['access_token'] && $data['expires_in']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取腾讯QQ ACCESS_TOKEN 出错:{$result}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + if($data['access_token']){ + $data = $this->http($this->url('oauth2.0/me'), array('access_token' => $data['access_token'])); + $data = json_decode(trim(substr($data, 9), " );\n"), true); + if(isset($data['openid'])) + return $data['openid']; + } + return NULL; + } + + public function getOauthInfo(){ + $data = $this->call('user/get_user_info'); + + if($data['ret'] == 0){ + $userInfo['type'] = 'QQ'; + $userInfo['name'] = $data['nickname']; + $userInfo['nick'] = $data['nickname']; + $userInfo['avatar'] = $data['figureurl_2']; + return $userInfo; + } else { + E("获取腾讯QQ用户信息失败:{$data['msg']}"); + } + } +} diff --git a/Library/Think/Oauth/Driver/Renren.php b/Library/Think/Oauth/Driver/Renren.php new file mode 100644 index 00000000..0981f142 --- /dev/null +++ b/Library/Think/Oauth/Driver/Renren.php @@ -0,0 +1,116 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Renren extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://graph.renren.com/oauth/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://graph.renren.com/oauth/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'http://api.renren.com/restserver.do'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'POST'){ + /* 人人网调用公共参数 */ + $params = array( + 'method' => $api, + 'access_token' => $this->token['access_token'], + 'v' => '1.0', + 'format' => 'json', + ); + + $data = $this->http($this->url(''), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 合并默认参数和额外参数 + * @param array $params 默认参数 + * @param array/string $param 额外参数 + * @return array: + */ + protected function param($params, $param){ + $params = parent::param($params, $param); + + /* 签名 */ + ksort($params); + $param = []; + foreach ($params as $key => $value){ + $param[] = "{$key}={$value}"; + } + $sign = implode('', $param).$this->AppSecret; + $params['sig'] = md5($sign); + + return $params; + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['user']['id']){ + $data['openid'] = $data['user']['id']; + unset($data['user']); + return $data; + } else + throw new \Exception("获取人人网ACCESS_TOKEN出错:{$data['error_description']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('users.getInfo'); + + if(!isset($data['error_code'])){ + $userInfo['type'] = 'RENREN'; + $userInfo['name'] = $data[0]['name']; + $userInfo['nick'] = $data[0]['name']; + $userInfo['avatar'] = $data[0]['headurl']; + return $userInfo; + } else { + E("获取人人网用户信息失败:{$data['error_msg']}"); + } + } +} diff --git a/Library/Think/Oauth/Driver/Sina.php b/Library/Think/Oauth/Driver/Sina.php new file mode 100644 index 00000000..0f52615c --- /dev/null +++ b/Library/Think/Oauth/Driver/Sina.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Sina extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://api.weibo.com/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://api.weibo.com/oauth2/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.weibo.com/2/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET', $multi = false){ + /* 新浪微博调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method, $multi); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['remind_in'] && $data['uid']){ + $data['openid'] = $data['uid']; + unset($data['uid']); + return $data; + } else + throw new \Exception("获取新浪微博ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('users.getInfo'); + + if(!isset($data['error_code'])){ + $userInfo['type'] = 'RENREN'; + $userInfo['name'] = $data[0]['name']; + $userInfo['nick'] = $data[0]['name']; + $userInfo['avatar'] = $data[0]['headurl']; + return $userInfo; + } else { + E("获取人人网用户信息失败:{$data['error_msg']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Sohu.php b/Library/Think/Oauth/Driver/Sohu.php new file mode 100644 index 00000000..bdf8eb37 --- /dev/null +++ b/Library/Think/Oauth/Driver/Sohu.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Sohu extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://api.sohu.com/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://api.sohu.com/oauth2/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.sohu.com/rest/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 搜狐API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 搜狐调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['open_id']){ + $data['openid'] = $data['open_id']; + unset($data['open_id']); + return $data; + } else + throw new \Exception("获取搜狐ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('i/prv/1/user/get-basic-info'); + + if('success' == $data['message'] && !empty($data['data'])){ + $userInfo['type'] = 'SOHU'; + $userInfo['name'] = $data['data']['open_id']; + $userInfo['nick'] = $data['data']['nick']; + $userInfo['avatar'] = $data['data']['icon']; + return $userInfo; + } else { + E("获取搜狐用户信息失败:{$data['message']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/T163.php b/Library/Think/Oauth/Driver/T163.php new file mode 100644 index 00000000..f2703fc8 --- /dev/null +++ b/Library/Think/Oauth/Driver/T163.php @@ -0,0 +1,95 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class T163 extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://api.t.163.com/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://api.t.163.com/oauth2/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://api.t.163.com/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 新浪微博调用公共参数 */ + $params = array( + 'oauth_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['uid'] && $data['access_token'] && $data['expires_in'] && $data['refresh_token']){ + $data['openid'] = $data['uid']; + unset($data['uid']); + return $data; + } else + throw new \Exception("获取网易微博ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + + $data = $this->call('users/show'); + return !empty($data['id'])?$data['id']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('users/show'); + + if($data['error_code'] == 0){ + $userInfo['type'] = 'T163'; + $userInfo['name'] = $data['name']; + $userInfo['nick'] = $data['screen_name']; + $userInfo['avatar'] = str_replace('w=48&h=48', 'w=180&h=180', $data['profile_image_url']); + return $userInfo; + } else { + E("获取网易微博用户信息失败:{$data['error']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Taobao.php b/Library/Think/Oauth/Driver/Taobao.php new file mode 100644 index 00000000..2525868f --- /dev/null +++ b/Library/Think/Oauth/Driver/Taobao.php @@ -0,0 +1,97 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Taobao extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://oauth.taobao.com/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://oauth.taobao.com/token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://eco.taobao.com/router/rest'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 淘宝网调用公共参数 */ + $params = array( + 'method' => $api, + 'access_token' => $this->token['access_token'], + 'format' => 'json', + 'v' => '2.0', + ); + $data = $this->http($this->url(''), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['taobao_user_id']){ + $data['openid'] = $data['taobao_user_id']; + unset($data['taobao_user_id']); + return $data; + } else + throw new \Exception("获取淘宝网ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $fields = 'user_id,nick,sex,buyer_credit,avatar,has_shop,vip_info'; + $data = $this->call('taobao.user.buyer.get', "fields={$fields}"); + + if(!empty($data['user_buyer_get_response']['user'])){ + $user = $data['user_buyer_get_response']['user']; + $userInfo['type'] = 'TAOBAO'; + $userInfo['name'] = $user['user_id']; + $userInfo['nick'] = $user['nick']; + $userInfo['avatar'] = $user['avatar']; + return $userInfo; + } else { + E("获取淘宝网用户信息失败:{$data['error_response']['msg']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/Tencent.php b/Library/Think/Oauth/Driver/Tencent.php new file mode 100644 index 00000000..3ad40c5d --- /dev/null +++ b/Library/Think/Oauth/Driver/Tencent.php @@ -0,0 +1,98 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class Tencent extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://open.t.qq.com/cgi-bin/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://open.t.qq.com/cgi-bin/oauth2/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://open.t.qq.com/api/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 微博API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET', $multi = false){ + /* 腾讯微博调用公共参数 */ + $params = array( + 'oauth_consumer_key' => $this->AppKey, + 'access_token' => $this->token['access_token'], + 'openid' => $this->openid(), + 'clientip' => get_client_ip(), + 'oauth_version' => '2.a', + 'scope' => 'all', + 'format' => 'json' + ); + + $data = $this->http($this->url($api), $this->param($params, $param), $method, $multi); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + parse_str($result, $data); + $data = array_merge($data, ['openid' => $_GET['openid'], 'openkey' => $_GET['openkey']]); + if($data['access_token'] && $data['expires_in'] && $data['openid']) + return $data; + else + throw new \Exception("获取腾讯微博 ACCESS_TOKEN 出错:{$result}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + return NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('users.getInfo'); + + if(!isset($data['error_code'])){ + $userInfo['type'] = 'RENREN'; + $userInfo['name'] = $data[0]['name']; + $userInfo['nick'] = $data[0]['name']; + $userInfo['avatar'] = $data[0]['headurl']; + return $userInfo; + } else { + E("获取人人网用户信息失败:{$data['error_msg']}"); + } + } + +} diff --git a/Library/Think/Oauth/Driver/X360.php b/Library/Think/Oauth/Driver/X360.php new file mode 100644 index 00000000..7058e45f --- /dev/null +++ b/Library/Think/Oauth/Driver/X360.php @@ -0,0 +1,93 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Oauth\Driver; +use Think\Oauth\Driver; + +class X360 extends Driver{ + /** + * 获取requestCode的api接口 + * @var string + */ + protected $getRequestCodeURL = 'https://openapi.360.cn/oauth2/authorize'; + + /** + * 获取access_token的api接口 + * @var string + */ + protected $getAccessTokenURL = 'https://openapi.360.cn/oauth2/access_token'; + + /** + * API根路径 + * @var string + */ + protected $apiBase = 'https://openapi.360.cn/'; + + /** + * 组装接口调用参数 并调用接口 + * @param string $api 360开放平台API + * @param string $param 调用API的额外参数 + * @param string $method HTTP请求方法 默认为GET + * @return json + */ + public function call($api, $param = '', $method = 'GET'){ + /* 360开放平台调用公共参数 */ + $params = array( + 'access_token' => $this->token['access_token'], + ); + + $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); + return json_decode($data, true); + } + + /** + * 解析access_token方法请求后的返回值 + * @param string $result 获取access_token的方法的返回值 + */ + protected function parseToken($result){ + $data = json_decode($result, true); + if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ + $data['openid'] = $this->getOpenId(); + return $data; + } else + throw new \Exception("获取360开放平台ACCESS_TOKEN出错:{$data['error']}"); + } + + /** + * 获取当前授权应用的openid + * @return string + */ + public function getOpenId(){ + if(!empty($this->token['openid'])) + return $this->token['openid']; + $data = $this->call('user/me'); + return !empty($data['id'])?$data['id']:NULL; + } + + /** + * 获取当前登录的用户信息 + * @return array + */ + public function getOauthInfo(){ + $data = $this->call('user/me'); + + if($data['error_code'] == 0){ + $userInfo['type'] = 'X360'; + $userInfo['name'] = $data['name']; + $userInfo['nick'] = $data['name']; + $userInfo['avatar'] = $data['avatar']; + return $userInfo; + } else { + E("获取360用户信息失败:{$data['error']}"); + } + } + +} diff --git a/Library/Think/Parser.php b/Library/Think/Parser.php new file mode 100644 index 00000000..d7d8d07e --- /dev/null +++ b/Library/Think/Parser.php @@ -0,0 +1,32 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +// 内容解析类 +class Parser { + + static private $handler = []; + + // 解析内容 + static public function parse($content,$type){ + if(!isset(self::$handler[$type])) { + $class = '\\Think\\Parser\\Driver\\'.ucwords($type); + self::$handler[$type] = new $class(); + } + return self::$handler[$type]->parse($content); + } + + // 调用驱动类的方法 + static public function __callStatic($method, $params){ + return self::parse($params[0],$method); + } +} diff --git a/Library/Think/Parser/Driver/Markdown.php b/Library/Think/Parser/Driver/Markdown.php new file mode 100644 index 00000000..334f7a60 --- /dev/null +++ b/Library/Think/Parser/Driver/Markdown.php @@ -0,0 +1,1534 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# + +# 应用到ThinkPHP中,因而修改为ThinkPHP规范的命名空间 +# namespace Michelf; +namespace Think\Parser\Driver; + +# +# The following two constants are deprecated: avoid using them, they'll +# disappear when the Lib branch becomes the only one to be updated. +# +# You can get the parser's version using the constant inside of the parser +# class: \Michelf\Markdown::MARKDOWNLIB_VERSION. +# + +const MARKDOWN_VERSION = "1.0.1p"; # Sun 13 Jan 2013 +const MARKDOWNEXTRA_VERSION = "1.2.6"; # Sun 13 Jan 2013 + +# +# Markdown Parser Class +# + +class Markdown { + + ### Version ### + + const MARKDOWNLIB_VERSION = "1.3-beta4"; + + ### Simple Function Interface ### + + public static function defaultTransform($text) { + # + # Initialize the parser and return the result of its transform method. + # This will work fine for derived classes too. + # + # Take parser class on which this function was called. + $parser_class = \get_called_class(); + + # try to take parser from the static parser list + static $parser_list; + $parser =& $parser_list[$parser_class]; + + # create the parser it not already set + if (!$parser) + $parser = new $parser_class; + + # Transform text using parser. + return $parser->transform($text); + } + + ### Configuration Variables ### + + # Change to ">" for HTML output. + public $empty_element_suffix = " />"; + public $tab_width = 4; + + # Change to `true` to disallow markup or entities. + public $no_markup = false; + public $no_entities = false; + + # Predefined urls and titles for reference links and images. + public $predef_urls = array(); + public $predef_titles = array(); + + + ### Parser Implementation ### + + # Regex to match balanced [brackets]. + # Needed to insert a maximum bracked depth while converting to PHP. + protected $nested_brackets_depth = 6; + protected $nested_brackets_re; + + protected $nested_url_parenthesis_depth = 4; + protected $nested_url_parenthesis_re; + + # Table of hash values for escaped characters: + protected $escape_chars = '\`*_{}[]()>#+-.!'; + protected $escape_chars_re; + + + public function __construct() { + # + # Constructor function. Initialize appropriate member variables. + # + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + # Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + # Internal hashes used during transformation. + protected $urls = array(); + protected $titles = array(); + protected $html_hashes = array(); + + # Status flag to avoid invalid nesting. + protected $in_anchor = false; + + + protected function setup() { + # + # Called before the transformation process starts to setup parser + # states. + # + # Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + + $this->in_anchor = false; + } + + protected function teardown() { + # + # Called after the transformation process to clear any variable + # which may be taking up memory unnecessarly. + # + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + /** + * 提供给ThinkPHP外部调用的方法,麦当苗儿为ThinkPHP添加 + * @author + * @param string $content 需要解析的Markdown字符串 + * @return string 解析后的HTML字符串 + */ + public function parse($content){ + return $this->transform($content); + } + + protected function transform($text) { + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + protected $document_gamut = array( + # Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + + "runBasicBlockGamut" => 30, + ); + + + protected function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + protected function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; # String that will replace the block + } + + + protected function hashHTMLBlocks($text) { + if ($this->no_markup) return $text; + + $less_than_tab = $this->tab_width - 1; + + # Hashify HTML blocks: + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + # + # * List "a" is made of tags which can be both inline or block-level. + # These will be treated block-level when the start tag is alone on + # its line, otherwise they're not matched here and will be taken as + # inline later. + # * List "b" is made of tags which are always block-level; + # + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|form|fieldset|iframe|math|svg|'. + 'article|section|nav|aside|hgroup|header|footer|'. + 'figure'; + + # Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). # end of opening tag + '.*?'. # last level nested tag content + str_repeat(' + # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + # First, look for nested blocks, e.g.: + #

+ #
+ # tags for inner block must be indented. + #
+ #
+ # + # The outermost tags must start at the left margin for this to match, and + # the inner nested divs must be indented. + # We need to do this before the next, more liberal match, because the next + # match will start at the first `
` and stop at the first `
`. + $text = preg_replace_callback('{(?> + (?> + (?<=\n\n) # Starting after a blank line + | # or + \A\n? # the beginning of the doc + ) + ( # save in $1 + + # Match from `\n` to `\n`, handling nested tags + # in between. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_b_re.')# start tag = $2 + '.$attr.'> # attributes followed by > and \n + '.$content.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special version for tags of group a. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_a_re.')# start tag = $3 + '.$attr.'>[ ]*\n # attributes followed by > + '.$content2.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special case just for
. It was easier to make a special + # case than to make the other regex more complicated. + + [ ]{0,'.$less_than_tab.'} + <(hr) # start tag = $2 + '.$attr.' # attributes + /?> # the matching end tag + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # Special case for standalone HTML comments: + + [ ]{0,'.$less_than_tab.'} + (?s: + + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # PHP and ASP-style processor instructions ( + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + ) + )}Sxmi', + array(&$this, '_hashHTMLBlocks_callback'), + $text); + + return $text; + } + protected function _hashHTMLBlocks_callback($matches) { + $text = $matches[1]; + $key = $this->hashBlock($text); + return "\n\n$key\n\n"; + } + + + protected function hashPart($text, $boundary = 'X') { + # + # Called whenever a tag must be hashed when a function insert an atomic + # element in the text stream. Passing $text to through this function gives + # a unique text-token which will be reverted back when calling unhash. + # + # The $boundary argument specify what character should be used to surround + # the token. By convension, "B" is used for block elements that needs not + # to be wrapped into paragraph tags at the end, ":" is used for elements + # that are word separators and "X" is used in the general case. + # + # Swap back any tag hash found in $text so we do not have to `unhash` + # multiple times at the end. + $text = $this->unhash($text); + + # Then hash the block. + static $i = 0; + $key = "$boundary\x1A" . ++$i . $boundary; + $this->html_hashes[$key] = $text; + return $key; # String that will replace the tag. + } + + + protected function hashBlock($text) { + # + # Shortcut function for hashPart with block-level boundaries. + # + return $this->hashPart($text, 'B'); + } + + + protected $block_gamut = array( + # + # These are all the transformations that form block-level + # tags like paragraphs, headers, and list items. + # + "doHeaders" => 10, + "doHorizontalRules" => 20, + + "doLists" => 40, + "doCodeBlocks" => 50, + "doBlockQuotes" => 60, + ); + + protected function runBlockGamut($text) { + # + # Run block gamut tranformations. + # + # We need to escape raw HTML in Markdown source before doing anything + # else. This need to be done for each block, and not only at the + # begining in the Markdown function since hashed blocks can be part of + # list items and could have been indented. Indented blocks would have + # been seen as a code block in a previous pass of hashHTMLBlocks. + $text = $this->hashHTMLBlocks($text); + + return $this->runBasicBlockGamut($text); + } + + protected function runBasicBlockGamut($text) { + # + # Run block gamut tranformations, without hashing HTML blocks. This is + # useful when HTML blocks are known to be already hashed, like in the first + # whole-document pass. + # + foreach ($this->block_gamut as $method => $priority) { + $text = $this->$method($text); + } + + # Finally form paragraph and restore hashed blocks. + $text = $this->formParagraphs($text); + + return $text; + } + + + protected function doHorizontalRules($text) { + # Do Horizontal Rules: + return preg_replace( + '{ + ^[ ]{0,3} # Leading space + ([-*_]) # $1: First marker + (?> # Repeated marker group + [ ]{0,2} # Zero, one, or two spaces. + \1 # Marker character + ){2,} # Group repeated at least twice + [ ]* # Tailing spaces + $ # End of line. + }mx', + "\n".$this->hashBlock("empty_element_suffix")."\n", + $text); + } + + + protected $span_gamut = array( + # + # These are all the transformations that occur *within* block-level + # tags like paragraphs, headers, and list items. + # + # Process character escapes, code spans, and inline HTML + # in one shot. + "parseSpan" => -30, + + # Process anchor and image tags. Images must come first, + # because ![foo][f] looks like an anchor. + "doImages" => 10, + "doAnchors" => 20, + + # Make links out of things like `` + # Must come after doAnchors, because you can use < and > + # delimiters in inline links like [this](). + "doAutoLinks" => 30, + "encodeAmpsAndAngles" => 40, + + "doItalicsAndBold" => 50, + "doHardBreaks" => 60, + ); + + protected function runSpanGamut($text) { + # + # Run span gamut tranformations. + # + foreach ($this->span_gamut as $method => $priority) { + $text = $this->$method($text); + } + + return $text; + } + + + protected function doHardBreaks($text) { + # Do hard breaks: + return preg_replace_callback('/ {2,}\n/', + array(&$this, '_doHardBreaks_callback'), $text); + } + protected function _doHardBreaks_callback($matches) { + return $this->hashPart("empty_element_suffix\n"); + } + + + protected function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + protected function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + protected function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + protected function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + protected function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + protected function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + protected function doHeaders($text) { + # Setext-style headers: + # Header 1 + # ======== + # + # Header 2 + # -------- + # + $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 + # ## Header 2 + # ## Header 2 with closing hashes ## + # ... + # ###### Header 6 + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + protected function _doHeaders_callback_setext($matches) { + # Terrible hack to check we haven't found an empty list item. + if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) + return $matches[0]; + + $level = $matches[2]{0} == '=' ? 1 : 2; + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + protected function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + protected function doLists($text) { + # + # Form HTML ordered (numbered) and unordered (bulleted) lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $markers_relist = array( + $marker_ul_re => $marker_ol_re, + $marker_ol_re => $marker_ul_re, + ); + + foreach ($markers_relist as $marker_re => $other_marker_re) { + # Re-usable pattern to match any entirel ul or ol list: + $whole_list_re = ' + ( # $1 = whole list + ( # $2 + ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces + ('.$marker_re.') # $4 = first list item marker + [ ]+ + ) + (?s:.+?) + ( # $5 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another list item marker + [ ]* + '.$marker_re.'[ ]+ + ) + | + (?= # Lookahead for another kind of list + \n + \3 # Must have the same indentation + '.$other_marker_re.'[ ]+ + ) + ) + ) + '; // mx + + # We use a different prefix before nested lists than top-level lists. + # See extended comment in _ProcessListItems(). + + if ($this->list_level) { + $text = preg_replace_callback('{ + ^ + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + else { + $text = preg_replace_callback('{ + (?:(?<=\n)\n|\A\n?) # Must eat the newline + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + } + + return $text; + } + protected function _doLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $list = $matches[1]; + $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; + + $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); + + $list .= "\n"; + $result = $this->processListItems($list, $marker_any_re); + + $result = $this->hashBlock("<$list_type>\n" . $result . ""); + return "\n". $result ."\n\n"; + } + + protected $list_level = 0; + + protected function processListItems($list_str, $marker_any_re) { + # + # Process the contents of a single ordered or unordered list, splitting it + # into individual list items. + # + # The $this->list_level global keeps track of when we're inside a list. + # Each time we enter a list, we increment it; when we leave a list, + # we decrement. If it's zero, we're not in a list anymore. + # + # We do this because when we're not inside a list, we want to treat + # something like this: + # + # I recommend upgrading to version + # 8. Oops, now this line is treated + # as a sub-list. + # + # As a single paragraph, despite the fact that the second line starts + # with a digit-period-space sequence. + # + # Whereas when we're inside a list (or sub-list), that line will be + # treated as the start of a sub-list. What a kludge, huh? This is + # an aspect of Markdown's syntax that's hard to parse perfectly + # without resorting to mind-reading. Perhaps the solution is to + # change the syntax rules such that sub-lists must start with a + # starting cardinal number; e.g. "1." or "a.". + + $this->list_level++; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + $list_str = preg_replace_callback('{ + (\n)? # leading line = $1 + (^[ ]*) # leading whitespace = $2 + ('.$marker_any_re.' # list marker and space = $3 + (?:[ ]+|(?=\n)) # space only required if item is not empty + ) + ((?s:.*?)) # list item text = $4 + (?:(\n+(?=\n))|\n) # tailing blank line = $5 + (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) + }xm', + array(&$this, '_processListItems_callback'), $list_str); + + $this->list_level--; + return $list_str; + } + protected function _processListItems_callback($matches) { + $item = $matches[4]; + $leading_line =& $matches[1]; + $leading_space =& $matches[2]; + $marker_space = $matches[3]; + $tailing_blank_line =& $matches[5]; + + if ($leading_line || $tailing_blank_line || + preg_match('/\n{2,}/', $item)) + { + # Replace marker with the appropriate whitespace indentation + $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; + $item = $this->runBlockGamut($this->outdent($item)."\n"); + } + else { + # Recursion for sub-lists: + $item = $this->doLists($this->outdent($item)); + $item = preg_replace('/\n+$/', '', $item); + $item = $this->runSpanGamut($item); + } + + return "
  • " . $item . "
  • \n"; + } + + + protected function doCodeBlocks($text) { + # + # Process Markdown `
    ` blocks.
    +	#
    +		$text = preg_replace_callback('{
    +				(?:\n\n|\A\n?)
    +				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    +				  (?>
    +					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    +					.*\n+
    +				  )+
    +				)
    +				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    +			}xm',
    +			array(&$this, '_doCodeBlocks_callback'), $text);
    +
    +		return $text;
    +	}
    +	protected function _doCodeBlocks_callback($matches) {
    +		$codeblock = $matches[1];
    +
    +		$codeblock = $this->outdent($codeblock);
    +		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    +
    +		# trim leading newlines and trailing newlines
    +		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    +
    +		$codeblock = "
    $codeblock\n
    "; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + + + protected function makeCodeSpan($code) { + # + # Create a code span markup for $code. Called from handleSpanToken. + # + $code = htmlspecialchars(trim($code), ENT_NOQUOTES); + return $this->hashPart("$code"); + } + + + protected $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { + foreach ($this->strong_relist as $strong => $strong_re) { + # Construct list of allowed token expressions. + $token_relist = array(); + if (isset($this->em_strong_relist["$em$strong"])) { + $token_relist[] = $this->em_strong_relist["$em$strong"]; + } + $token_relist[] = $em_re; + $token_relist[] = $strong_re; + + # Construct master expression from list. + $token_re = '{('. implode('|', $token_relist) .')}'; + $this->em_strong_prepared_relist["$em$strong"] = $token_re; + } + } + } + + protected function doItalicsAndBold($text) { + $token_stack = array(''); + $text_stack = array(''); + $em = ''; + $strong = ''; + $tree_char_em = false; + + while (1) { + # + # Get prepared regular expression for seraching emphasis tokens + # in current context. + # + $token_re = $this->em_strong_prepared_relist["$em$strong"]; + + # + # Each loop iteration search for the next emphasis token. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + $text_stack[0] .= $parts[0]; + $token =& $parts[1]; + $text =& $parts[2]; + + if (empty($token)) { + # Reached end of text span: empty stack without emitting. + # any more emphasis. + while ($token_stack[0]) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + break; + } + + $token_len = strlen($token); + if ($tree_char_em) { + # Reached closing marker while inside a three-char emphasis. + if ($token_len == 3) { + # Three-char closing marker, close em and strong. + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + $strong = ''; + } else { + # Other closing marker: close one em or strong and + # change current token state to match the other + $token_stack[0] = str_repeat($token{0}, 3-$token_len); + $tag = $token_len == 2 ? "strong" : "em"; + $span = $text_stack[0]; + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] = $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + $tree_char_em = false; + } else if ($token_len == 3) { + if ($em) { + # Reached closing marker for both em and strong. + # Closing strong marker: + for ($i = 0; $i < 2; ++$i) { + $shifted_token = array_shift($token_stack); + $tag = strlen($shifted_token) == 2 ? "strong" : "em"; + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] .= $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + } else { + # Reached opening three-char emphasis marker. Push on token + # stack; will be handled by the special condition above. + $em = $token{0}; + $strong = "$em$em"; + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $tree_char_em = true; + } + } else if ($token_len == 2) { + if ($strong) { + # Unwind any dangling emphasis marker: + if (strlen($token_stack[0]) == 1) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + # Closing strong marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $strong = ''; + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $strong = $token; + } + } else { + # Here $token_len == 1 + if ($em) { + if (strlen($token_stack[0]) == 1) { + # Closing emphasis marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + } else { + $text_stack[0] .= $token; + } + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $em = $token; + } + } + } + return $text_stack[0]; + } + + + protected function doBlockQuotes($text) { + $text = preg_replace_callback('/ + ( # Wrap whole match in $1 + (?> + ^[ ]*>[ ]? # ">" at the start of a line + .+\n # rest of the first line + (.+\n)* # subsequent consecutive lines + \n* # blanks + )+ + ) + /xm', + array(&$this, '_doBlockQuotes_callback'), $text); + + return $text; + } + protected function _doBlockQuotes_callback($matches) { + $bq = $matches[1]; + # trim one level of quoting - trim whitespace-only lines + $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); + $bq = $this->runBlockGamut($bq); # recurse + + $bq = preg_replace('/^/m', " ", $bq); + # These leading spaces cause problem with
     content, 
    +		# so we need to fix that:
    +		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', + array(&$this, '_doBlockQuotes_callback2'), $bq); + + return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; + } + protected function _doBlockQuotes_callback2($matches) { + $pre = $matches[1]; + $pre = preg_replace('/^ /m', '', $pre); + return $pre; + } + + + protected function formParagraphs($text) { + # + # Params: + # $text - string to process with html

    tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { + # Is a paragraph. + $value = $this->runSpanGamut($value); + $value = preg_replace('/^([ ]*)/', "

    ", $value); + $value .= "

    "; + $grafs[$key] = $this->unhash($value); + } + else { + # Is a block. + # Modify elements of @grafs in-place... + $graf = $value; + $block = $this->html_hashes[$graf]; + $graf = $block; +// if (preg_match('{ +// \A +// ( # $1 =
    tag +//
    ]* +// \b +// markdown\s*=\s* ([\'"]) # $2 = attr quote char +// 1 +// \2 +// [^>]* +// > +// ) +// ( # $3 = contents +// .* +// ) +// (
    ) # $4 = closing tag +// \z +// }xs', $block, $matches)) +// { +// list(, $div_open, , $div_content, $div_close) = $matches; +// +// # We can't call Markdown(), because that resets the hash; +// # that initialization code should be pulled into its own sub, though. +// $div_content = $this->hashHTMLBlocks($div_content); +// +// # Run document gamut methods on the content. +// foreach ($this->document_gamut as $method => $priority) { +// $div_content = $this->$method($div_content); +// } +// +// $div_open = preg_replace( +// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); +// +// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; +// } + $grafs[$key] = $graf; + } + } + + return implode("\n\n", $grafs); + } + + + protected function encodeAttribute($text) { + # + # Encode text for a double-quoted HTML attribute. This function + # is *not* suitable for attributes enclosed in single quotes. + # + $text = $this->encodeAmpsAndAngles($text); + $text = str_replace('"', '"', $text); + return $text; + } + + + protected function encodeAmpsAndAngles($text) { + # + # Smart processing for ampersands and angle brackets that need to + # be encoded. Valid character entities are left alone unless the + # no-entities mode is set. + # + if ($this->no_entities) { + $text = str_replace('&', '&', $text); + } else { + # Ampersand-encoding based entirely on Nat Irons's Amputator + # MT plugin: + $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', + '&', $text);; + } + # Encode remaining <'s + $text = str_replace('<', '<', $text); + + return $text; + } + + + protected function doAutoLinks($text) { + $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', + array(&$this, '_doAutoLinks_url_callback'), $text); + + # Email addresses: + $text = preg_replace_callback('{ + < + (?:mailto:)? + ( + (?: + [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ + | + ".*?" + ) + \@ + (?: + [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ + | + \[[\d.a-fA-F:]+\] # IPv4 & IPv6 + ) + ) + > + }xi', + array(&$this, '_doAutoLinks_email_callback'), $text); + + return $text; + } + protected function _doAutoLinks_url_callback($matches) { + $url = $this->encodeAttribute($matches[1]); + $link = "$url"; + return $this->hashPart($link); + } + protected function _doAutoLinks_email_callback($matches) { + $address = $matches[1]; + $link = $this->encodeEmailAddress($address); + return $this->hashPart($link); + } + + + protected function encodeEmailAddress($addr) { + # + # Input: an email address, e.g. "foo@example.com" + # + # Output: the email address as a mailto link, with each character + # of the address encoded as either a decimal or hex entity, in + # the hopes of foiling most address harvesting spam bots. E.g.: + # + #

    foo@exampl + # e.com

    + # + # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. + # With some optimizations by Milian Wolff. + # + $addr = "mailto:" . $addr; + $chars = preg_split('/(? $char) { + $ord = ord($char); + # Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. + # roughly 10% raw, 45% hex, 45% dec + # '@' *must* be encoded. I insist. + if ($r > 90 && $char != '@') /* do nothing */; + else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; + else $chars[$key] = '&#'.$ord.';'; + } + } + + $addr = implode('', $chars); + $text = implode('', array_slice($chars, 7)); # text without `mailto:` + $addr = "$text"; + + return $addr; + } + + + protected function parseSpan($str) { + # + # Take the string $str and parse it into tokens, hashing embeded HTML, + # escaped characters and handling code spans. + # + $output = ''; + + $span_re = '{ + ( + \\\\'.$this->escape_chars_re.' + | + (?no_markup ? '' : ' + | + # comment + | + <\?.*?\?> | <%.*?%> # processing instruction + | + <[!$]?[-a-zA-Z0-9:_]+ # regular tags + (?> + \s + (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* + )? + > + | + <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag + | + # closing tag + ').' + ) + }xs'; + + while (1) { + # + # Each loop iteration seach for either the next tag, the next + # openning code span marker, or the next escaped character. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); + + # Create token from text preceding tag. + if ($parts[0] != "") { + $output .= $parts[0]; + } + + # Check if we reach the end. + if (isset($parts[1])) { + $output .= $this->handleSpanToken($parts[1], $parts[2]); + $str = $parts[2]; + } + else { + break; + } + } + + return $output; + } + + + protected function handleSpanToken($token, &$str) { + # + # Handle $token provided by parseSpan by determining its nature and + # returning the corresponding value that should replace it. + # + switch ($token{0}) { + case "\\": + return $this->hashPart("&#". ord($token{1}). ";"); + case "`": + # Search for end marker in remaining text. + if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', + $str, $matches)) + { + $str = $matches[2]; + $codespan = $this->makeCodeSpan($matches[1]); + return $this->hashPart($codespan); + } + return $token; // return as text since no ending marker found. + default: + return $this->hashPart($token); + } + } + + + protected function outdent($text) { + # + # Remove one level of line-leading tabs or spaces + # + return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); + } + + + # String length function for detab. `_initDetab` will create a function to + # hanlde UTF-8 if the default function does not exist. + protected $utf8_strlen = 'mb_strlen'; + + protected function detab($text) { + # + # Replace tabs with the appropriate amount of space. + # + # For each line we separate the line in blocks delemited by + # tab characters. Then we reconstruct every line by adding the + # appropriate number of space between each blocks. + + $text = preg_replace_callback('/^.*\t.*$/m', + array(&$this, '_detab_callback'), $text); + + return $text; + } + protected function _detab_callback($matches) { + $line = $matches[0]; + $strlen = $this->utf8_strlen; # strlen function for UTF-8. + + # Split in blocks. + $blocks = explode("\t", $line); + # Add each blocks to the line. + $line = $blocks[0]; + unset($blocks[0]); # Do not add first block twice. + foreach ($blocks as $block) { + # Calculate amount of space, insert spaces, insert block. + $amount = $this->tab_width - + $strlen($line, 'UTF-8') % $this->tab_width; + $line .= str_repeat(" ", $amount) . $block; + } + return $line; + } + protected function _initDetab() { + # + # Check for the availability of the function in the `utf8_strlen` property + # (initially `mb_strlen`). If the function is not available, create a + # function that will loosely count the number of UTF-8 characters with a + # regular expression. + # + if (function_exists($this->utf8_strlen)) return; + $this->utf8_strlen = create_function('$text', 'return preg_match_all( + "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", + $text, $m);'); + } + + + protected function unhash($text) { + # + # Swap back in all the tags hashed by _HashHTMLBlocks. + # + return preg_replace_callback('/(.)\x1A[0-9]+\1/', + array(&$this, '_unhash_callback'), $text); + } + protected function _unhash_callback($matches) { + return $this->html_hashes[$matches[0]]; + } + +} diff --git a/Library/Think/Parser/Driver/Ubb.php b/Library/Think/Parser/Driver/Ubb.php new file mode 100644 index 00000000..525549ce --- /dev/null +++ b/Library/Think/Parser/Driver/Ubb.php @@ -0,0 +1,290 @@ + +// +---------------------------------------------------------------------- +// | Ubb.php 2013-04-03 +// +---------------------------------------------------------------------- + +namespace Think\Parser\Driver; + +class Ubb{ + /** + * UBB标签匹配规则 + * @var array + */ + private $ubb = [ + ['table' , '\[table(?:=([\d%]*))?\]', '\[\/table\]', 'width'], + ['tr' , '\[tr\]', '\[\/tr\]', 'tag'], + ['th' , '\[th(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/th\]', 'widthAndHeight'], + ['td' , '\[td(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/td\]', 'widthAndHeight'], + ['img' , '\[img(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/img\]', 'imgWidthAndHeight'], + ['img' , '\[img=(.*?)(?:,([\d%]*)(?:,([\d%]*))?)?\/\]', 'img'], + ['a' , '\[url(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/url\]', 'urlClass'], + ['a' , '\[a(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/a\]', 'urlClass'], + ['a' , '\[url=(.*?)(?:,([\w\-]*))?\/\]', 'url'], + ['a' , '\[a=(.*?)(?:,([\w\-]*))?\/\]', 'url'], + ['a' , '\[email(?:=([\w\-]*))?\]', '\[\/email\]', 'emailClass'], + ['ul' , '\[ul(?:=([\w\-]*))?\]', '\[\/ul\]', 'class'], + ['ol' , '\[ol(?:=([\w\-]*))?\]', '\[\/ol\]', 'class'], + ['li' , '\[li(?:=([\w\-]*))?\]', '\[\/li\]', 'class'], + ['span' , '\[span(?:=([\w\-]*))?\]', '\[\/span\]', 'class'], + ['div' , '\[div(?:=([\w\-]*))?\]', '\[\/div\]', 'class'], + ['p' , '\[p(?:=([\w\-]*))?\]', '\[\/p\]', 'class'], + ['strong' , '\[b\]', '\[\/b\]', 'tag'], + ['strong' , '\[strong\]', '\[\/strong\]', 'tag'], + ['i' , '\[i\]', '\[\/i\]', 'tag'], + ['em' , '\[em\]', '\[\/em\]', 'tag'], + ['sub' , '\[sub\]', '\[\/sub\]', 'tag'], + ['sup' , '\[sup\]', '\[\/sup\]', 'tag'], + ['pre' , '\[code(?:=([a-z#\+\/]*))?\]', '\[\/code\]', 'code'], + ['code' , '\[line(?:=([a-z#\+\/]*))?\]', '\[\/line\]', 'code'], + ]; + + /** + * 解析UBB代码为HTML + * @param string $content 要解析的UBB代码 + * @return string 解析后的HTML代码 + */ + public function parse($content = ''){ + if(empty($content)) return ''; + + for($i = 0, $count = count($this->ubb); $i < $count; $i++){ + if(count($this->ubb[$i]) == 4){ //解析闭合标签 + $content = $this->closeTag($content, $this->ubb[$i]); + } else { + $content = $this->onceTag($content, $this->ubb[$i]); + } + } + + return nl2br($content); + } + + /** + * 解析闭合标签,支持嵌套 + * @param string $data 要解析的数据 + * @param array $rule 解析规则 + * @return string 解析后的内容 + */ + private function closeTag($data, $rule = ''){ + static $tag, $reg, $func, $count = 0; + if(is_string($data)){ + list($tag, $reg[0], $reg[1], $func) = $rule; + do{ + $data = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", + [$this, 'closeTag'], $data); + } while ($count && $count--); //递归解析,直到嵌套解析完毕 + return $data; + } elseif(is_array($data)){ + $num = count($data); + if(preg_match("/{$reg[0]}/is", $data[$num-2])){ //存在嵌套,进一步解析 + $count = 1; + $data[$num-2] = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", + [$this, 'closeTag'], $data[$num-2] . $data[$num-1]); + return $data[1] . $data[$num-2]; + } else { //不存在嵌套,直接解析内容 + $parse = '_' . $func; + $data[$num-2] = trim($data[$num-2], "\r\n"); //去掉标签内容两端的换行符 + return $this->$parse($tag, $data); + } + } + } + + /** + * 解析单标签 + * @param string $data 要解析的数据 + * @param array $rule 解析规则 + * @return string 解析后的内容 + */ + private function onceTag($data, $rule = ''){ + list($tag, $reg, $func) = $rule; + return preg_replace_callback("/{$reg}/is", [$this, '_' . $func], $data); + } + + /** + * 解析img单标签 + * @param array $data 解析数据 + * @return string 解析后的标签 + */ + private function _img($data){ + $data[4] = $data[1]; + return $this->_imgWidthAndHeight('', $data); + } + + /** + * 解析url单标签 + * @param array $data 解析数据 + * @return string 解析后的标签 + */ + private function _url($data){ + $data[3] = $data[2]; + $data[4] = $data[2] = $data[1]; + return $this->_urlClass('', $data); + } + + /** + * 解析没有属性的标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - 标签内容 + * @return string 解析后的标签 + */ + private function _tag($name, $data){ + return "<{$name}>{$data[2]}"; + } + + /** + * 解析代码 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - 语言类型,[3] - 代码内容 + * @return string 解析后的标签 + */ + private function _code($name, $data){ + $fix = ($name == 'pre') ? ['
    ', '
    '] : ['', '']; + if(empty($data[2])){ + $data = "{$fix[0]}{$data[3]}{$fix[1]}"; + } else { + $data = "{$fix[0]}{$data[3]}{$fix[1]}"; + } + return $data; + } + + /** + * 解析含有width属性的标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - width, [3] - 标签内容 + * @return string 解析后的标签 + */ + private function _width($name, $data){ + if(empty($data[2])){ + $data = "<{$name}>{$data[3]}"; + } else { + $data = "<{$name} width=\"{$data[2]}\">{$data[3]}"; + } + return $data; + } + + /** + * 解析含有width和height属性的标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - width, [3] - height, [4] - 标签内容 + * @return string 解析后的标签 + */ + private function _widthAndHeight($name, $data){ + if(empty($data[2]) && empty($data[3])){ + $data = "<{$name}>{$data[4]}"; + } elseif(!empty($data[2]) && empty($data[3])) { + $data = "<{$name} width=\"{$data[2]}\">{$data[4]}"; + } elseif(empty($data[2]) && !empty($data[3])) { + $data = "<{$name} height=\"{$data[3]}\">{$data[4]}"; + } else { + $data = "<{$name} width=\"{$data[2]}\" height=\"{$data[3]}\">{$data[4]}"; + } + return $data; + } + + /** + * 解析含有width和height属性的图片标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - width, [3] - height, [4] - 图片URL + * @return string 解析后的标签 + */ + private function _imgWidthAndHeight($name, $data){ + if(empty($data[2]) && empty($data[3])){ + $data = ""; + } elseif(!empty($data[2]) && empty($data[3])) { + $data = ""; + } elseif(empty($data[2]) && !empty($data[3])) { + $data = ""; + } else { + $data = ""; + } + return $data; + } + + /** + * 解析含有class属性的标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - class, [3] - 标签内容 + * @return string 解析后的标签 + */ + private function _class($name, $data){ + if(empty($data[2])){ + $data = "<{$name}>{$data[3]}"; + } else { + $data = "<{$name} class=\"{$data[2]}\">{$data[3]}"; + } + return $data; + } + + /** + * 解析含有class属性的url标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - url, [3] - text + * @return string 解析后的标签 + */ + private function _urlClass($name, $data){ + empty($data[2]) && $data[2] = $data[4]; + if(empty($data[3])){ + $data = "{$data[4]}"; + } else { + $data = "{$data[4]}"; + } + return $data; + } + + /** + * 解析含有class属性的email标签 + * @param string $name 标签名 + * @param array $data 解析数据 [2] - class, [3] - email地址 + * @return string 解析后的标签 + */ + private function _emailClass($name, $data){ + //不是正确的EMAIL则不解析 + if(preg_match('/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', $data[3])) + return $data[0]; + + //编码email地址,防治被采集 + $email = $this->encodeEmailAddress($data[3]); + + if(empty($data[2])){ + $data = "{$email[1]}"; + } else { + $data = "{$email[1]}"; + } + return $data; + } + + /** + * 编码EMAIL地址,可以防治部分采集软件 + * @param string $addr EMAIL地址 + * @return array 编码后的EMAIL地址 [0] - 带mailto, [1] - 不带mailto + */ + private function encodeEmailAddress($addr) { + $addr = "mailto:" . $addr; + $chars = preg_split('/(? $char) { + $ord = ord($char); + # Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. + # roughly 10% raw, 45% hex, 45% dec + # '@' *must* be encoded. I insist. + if ($r > 90 && $char != '@') /* do nothing */; + else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; + else $chars[$key] = '&#'.$ord.';'; + } + } + + $addr = implode('', $chars); + $text = implode('', array_slice($chars, 7)); # text without `mailto:` + + return [$addr, $text]; + } +} diff --git a/Library/Think/Route.php b/Library/Think/Route.php new file mode 100644 index 00000000..6f5e4ce8 --- /dev/null +++ b/Library/Think/Route.php @@ -0,0 +1,439 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Route { + // 路由规则 + static private $rules = [ + 'GET' => [], + 'POST' => [], + 'PUT' => [], + 'DELETE' => [], + '*' => [], + ]; + // URL映射规则 + static private $map = []; + // 子域名部署规则 + static private $domain = []; + + // 添加URL映射规则 + static public function map($map, $route = ''){ + if(is_array($map)) { + self::$map = array_merge(self::$map, $map); + }else{ + self::$map[$map] = $route; + } + } + + // 添加子域名部署规则 + static public function domain($domain, $rule = ''){ + if(is_array($domain)) { + self::$domain = array_merge(self::$domain,$domain); + }else{ + self::$domain[$domain] = $rule; + } + } + + // 注册路由规则 + static public function register($rule, $route = '', $type = 'GET', $option = []){ + if(strpos($type, '|')) { + foreach (explode('|', $type) as $val){ + self::register($rule, $route, $val, $option); + } + }else{ + if(is_array($rule)) { + foreach ($rule as $key => $val){ + self::$rules[$type][$key] = ['route' => $val, 'option' => $option]; + } + }else{ + self::$rules[$type][$rule] = ['route' => $route, 'option' => $option]; + } + } + } + + // 注册任意请求的路由规则 + static public function any($rule, $route = '', $option = []){ + self::register($rule, $route, '*', $option); + } + + // 注册get请求的路由规则 + static public function get($rule, $route = '', $option = []){ + self::register($rule, $route, 'GET', $option); + } + + // 注册post请求的路由规则 + static public function post($rule, $route = '', $option = []){ + self::register($rule, $route, 'POST', $option); + } + + // 注册put请求的路由规则 + static public function put($rule, $route = '', $option = []){ + self::register($rule, $route, 'PUT', $option); + } + + // 注册delete请求的路由规则 + static public function delete($rule, $route = '', $option = []){ + self::register($rule, $route, 'DELETE', $option); + } + + // 检测子域名部署 + static public function checkDomain(){ + // 开启子域名部署 支持二级和三级域名 + if(!empty(self::$domain)) { + $rules = self::$domain; + if(isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置 + $rule = $rules[$_SERVER['HTTP_HOST']]; + }else{// 子域名配置 + $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2); + if(!empty($domain)) { + $subDomain = implode('.', $domain); + $domain2 = array_pop($domain); // 二级域名 + if($domain) { // 存在三级域名 + $domain3 = array_pop($domain); + } + if($subDomain && isset($rules[$subDomain])) { // 子域名配置 + $rule = $rules[$subDomain]; + }elseif(isset($rules['*.' . $domain2]) && !empty($domain3)){ // 泛三级域名 + $rule = $rules['*.' . $domain2]; + $panDomain = $domain3; + }elseif(isset($rules['*']) && !empty($domain2)){ // 泛二级域名 + if('www' != $domain2 ) { + $rule = $rules['*']; + $panDomain = $domain2; + } + } + } + } + if(!empty($rule)) { + // 子域名部署规则 + // '子域名'=>'模块名' + // '子域名'=>['模块名','var1=a&var2=b&var3=*']; + if($rule instanceof \Closure) { + // 执行闭包并中止 + self::invokeRule($rule); + exit; + } + if(is_array($rule)) { + $_GET[Config::get('var_module')] = $rule[0]; + if(isset($rule[1])) { // 传入参数 + parse_str($rule[1], $parms); + if(isset($panDomain)) { + $pos = array_search('*', $parms); + if(false !== $pos) { + // 泛域名作为参数 + $parms[$pos] = $panDomain; + } + } + $_GET = array_merge($_GET,$parms); + } + }else{ + $_GET[Config::get('var_module')] = $rule; + } + } + } + } + + // 检测URL路由 + static public function check($regx) { + // 优先检测是否存在PATH_INFO + if(empty($regx)) $regx = '/' ; + // 分隔符替换 确保路由定义使用统一的分隔符 + $regx = str_replace(Config::get('pathinfo_depr'), '/', $regx); + if(isset(self::$map[$regx])) { // URL映射 + return self::parseUrl(self::$map[$regx]); + } + // 获取当前请求类型的路由规则 + $rules = self::$rules[REQUEST_METHOD]; + if(!empty(self::$rules['*'])) { // 合并任意请求的路由规则 + $rules = array_merge(self::$rules['*'], $rules); + } + // 路由规则检测 + if(!empty($rules)) { + foreach ($rules as $rule=>$val){ + $route = $val['route']; + $option = $val['option']; + + // 伪静态后缀检测 + if(isset($option['ext']) && __EXT__ != $option['ext']) { + continue; + } + // https检测 + if(!empty($option['https']) && !self::isSsl()) { + continue; + } + // 自定义检测 + if(!empty($option['callback']) && is_callable($option['callback'])) { + if(false === call_user_func($option['callback'])) { + continue; + } + } + if(0 === strpos($rule, '/') && preg_match($rule, $regx, $matches)) { // 正则路由 + if(!empty($option['file'])){ + // 调度到某个文件中执行 + include $route; + exit; + } + if($route instanceof \Closure) { + // 执行闭包并中止 + self::invokeRegx($route, $matches); + exit; + } + return self::parseRegex($matches, $route, $regx); + }else{ // 规则路由 + $len1 = substr_count($regx, '/'); + $len2 = substr_count($rule, '/'); + if($len1 >= $len2) { + if('$' == substr($rule, -1, 1)) {// 完整匹配 + if($len1 != $len2) { + continue; + }else{ + $rule = substr($rule, 0, -1); + } + } + if(false !== $var = self::match($regx, $rule)){ + if(!empty($option['file'])){ + // 调度到某个文件中执行 + include $route; + exit; + } + if($route instanceof \Closure) { + // 执行闭包并中止 + self::invokeRule($route, $var); + exit; + } + return self::parseRule($rule, $route, $regx); + } + } + } + } + } + return self::parseUrl($regx); + } + + /** + * 判断是否SSL协议 + * @return boolean + */ + static public function isSsl() { + if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){ + return true; + }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) { + return true; + } + return false; + } + + // 执行正则匹配下的闭包方法 支持参数调用 + static private function invokeRegx($closure, $var = []) { + $reflect = new \ReflectionFunction($closure); + $params = $reflect->getParameters(); + $args = []; + array_shift($var); + foreach ($params as $param){ + $name = $param->getName(); + if(!empty($var)) { + $args[] = array_shift($var); + }elseif($param->isDefaultValueAvailable()){ + $args[] = $param->getDefaultValue(); + } + } + $reflect->invokeArgs($args); + } + + // 执行规则匹配下的闭包方法 支持参数调用 + static private function invokeRule($closure, $var = []) { + $reflect = new \ReflectionFunction($closure); + $params = $reflect->getParameters(); + $args = []; + foreach ($params as $param){ + $name = $param->getName(); + if(isset($var[$name])) { + $args[] = $var[$name]; + }elseif($param->isDefaultValueAvailable()){ + $args[] = $param->getDefaultValue(); + } + } + $reflect->invokeArgs($args); + } + + // 解析模块的URL地址 + static private function parseUrl($url) { + if('/' == $url) { + return ; + } + $paths = explode('/', $url); + $var_g = Config::get('var_group'); + $var_c = Config::get('var_controller'); + $var_a = Config::get('var_action'); + if(Config::get('require_group') && !isset($_GET[$var_g])) { + $_GET[$var_g] = array_shift($paths); + } + if(Config::get('require_controller') && !isset($_GET[$var_c])) { + $_GET[$var_c] = array_shift($paths); + } + if(!isset($_GET[$var_a])) { + $_GET[$var_a] = array_shift($paths); + } + // 解析剩余的URL参数 + $var = []; + preg_replace('@(\w+)\/([^\/]+)@e', '$var[\'\\1\']=strip_tags(\'\\2\');', implode('/', $paths)); + $_GET = array_merge($var, $_GET); + } + + // 解析规范的路由地址 + // 地址格式 [控制器/操作?]参数1=值1&参数2=值2... + static private function parseRoute($url) { + $var = []; + if(false !== strpos($url, '?')) { // [控制器/操作?]参数1=值1&参数2=值2... + $info = parse_url($url); + $path = explode('/', $info['path']); + parse_str($info['query'], $var); + }elseif(strpos($url, '/')){ // [控制器/操作] + $path = explode('/', $url); + }else{ // 参数1=值1&参数2=值2... + parse_str($url, $var); + } + if(isset($path)) { + $action = array_pop($path); + $_GET[Config::get('var_action')] = '[rest]'==$action? REQUEST_METHOD : $action; + if(!empty($path)) { + $_GET[Config::get('var_controller')] = array_pop($path); + } + } + return $var; + } + + // 检测URL和规则路由是否匹配 + static private function match($regx, $rule) { + $m1 = explode('/', $regx); + $m2 = explode('/', $rule); + $var = []; + foreach ($m2 as $key=>$val){ + if(0 === strpos($val, ':')) {// 动态变量 + if(strpos($val, '\\')) { + $type = substr($val, -1); + if('d' == $type && !is_numeric($m1[$key])) { + return false; + } + $name = substr($val, 1, -2); + }elseif($pos = strpos($val, '^')){ + $array = explode('|', substr(strstr($val, '^'), 1)); + if(in_array($m1[$key], $array)) { + return false; + } + $name = substr($val, 1, $pos - 1); + }else{ + $name = substr($val, 1); + } + $var[$name] = $m1[$key]; + }elseif(0 !== strcasecmp($val, $m1[$key])){ + return false; + } + } + // 成功匹配后返回URL中的动态变量数组 + return $var; + } + + // 解析规则路由 + // '路由规则'=>'[控制器/操作]?额外参数1=值1&额外参数2=值2...' + // '路由规则'=>array('[控制器/操作]','额外参数1=值1&额外参数2=值2...') + // '路由规则'=>'外部地址' + // '路由规则'=>array('外部地址','重定向代码') + // 路由规则中 :开头 表示动态变量 + // 外部地址中可以用动态变量 采用 :1 :2 的方式 + // 'news/:month/:day/:id'=>array('News/read?cate=1','status=1'), + // 'new/:id'=>array('/new.php?id=:1',301), 重定向 + static private function parseRule($rule, $route, $regx) { + // 获取路由地址规则 + $url = is_array($route) ? $route[0] : $route; + // 获取URL地址中的参数 + $paths = explode('/', $regx); + // 解析路由规则 + $matches = []; + $rule = explode('/', $rule); + foreach ($rule as $item){ + if(0 === strpos($item, ':')) { // 动态变量获取 + if($pos = strpos($item, '^') ) { + $var = substr($item, 1, $pos - 1); + }elseif(strpos($item, '\\')){ + $var = substr($item, 1, -2); + }else{ + $var = substr($item, 1); + } + $matches[$var] = array_shift($paths); + }else{ // 过滤URL中的静态变量 + array_shift($paths); + } + } + if(0 === strpos($url, '/') || 0 === strpos($url, 'http')) { // 路由重定向跳转 + if(strpos($url, ':')) { // 传递动态参数 + $values = array_values($matches); + $url = preg_replace('/:(\d+)/e', '$values[\\1-1]', $url); + } + header("Location: $url", true, (is_array($route) && isset($route[1])) ? $route[1] : 301); + exit; + }else{ + // 解析路由地址 + $var = self::parseRoute($url); + // 解析路由地址里面的动态参数 + $values = array_values($matches); + foreach ($var as $key => $val){ + if(0 === strpos($val, ':')) { + $var[$key] = $values[substr($val, 1) - 1]; + } + } + $var = array_merge($matches, $var); + // 解析剩余的URL参数 + if($paths) { + preg_replace('@(\w+)\/([^\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', implode('/', $paths)); + } + // 解析路由自动传人参数 + if(is_array($route) && isset($route[1])) { + parse_str($route[1], $params); + $var = array_merge($var, $params); + } + $_GET = array_merge($var, $_GET); + } + } + + // 解析正则路由 + // '路由正则'=>'[控制器/操作]?参数1=值1&参数2=值2...' + // '路由正则'=>array('[控制器/操作]?参数1=值1&参数2=值2...','额外参数1=值1&额外参数2=值2...') + // '路由正则'=>'外部地址' + // '路由正则'=>array('外部地址','重定向代码') + // 参数值和外部地址中可以用动态变量 采用 :1 :2 的方式 + // '/new\/(\d+)\/(\d+)/'=>array('News/read?id=:1&page=:2&cate=1','status=1'), + // '/new\/(\d+)/'=>array('/new.php?id=:1&page=:2&status=1','301'), 重定向 + static private function parseRegex($matches, $route, $regx) { + // 获取路由地址规则 + $url = is_array($route) ? $route[0] : $route; + $url = preg_replace('/:(\d+)/e', '$matches[\\1]', $url); + if(0 === strpos($url, '/') || 0 === strpos($url, 'http')) { // 路由重定向跳转 + header("Location: $url", true, (is_array($route) && isset($route[1])) ? $route[1] : 301); + exit; + }else{ + // 解析路由地址 + $var = self::parseRoute($url); + // 解析剩余的URL参数 + $regx = substr_replace($regx, '', 0, strlen($matches[0])); + if($regx) { + preg_replace('@(\w+)\/([^,\/]+)@e', '$var[strtolower(\'\\1\')]=strip_tags(\'\\2\');', $regx); + } + // 解析路由自动传人参数 + if(is_array($route) && isset($route[1])) { + parse_str($route[1], $params); + $var = array_merge($var, $params); + } + $_GET = array_merge($var, $_GET); + } + } +} diff --git a/Library/Think/Seesion/Driver.php b/Library/Think/Seesion/Driver.php new file mode 100644 index 00000000..06e0a38e --- /dev/null +++ b/Library/Think/Seesion/Driver.php @@ -0,0 +1,22 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Session\Driver; +use SessionHandler; + +class Driver extends SessionHandler { + protected $config = []; + + public function __construct($config=[]){ + $this->config = array_merge($this->config,$config); + } + +} diff --git a/Library/Think/Session.php b/Library/Think/Session.php new file mode 100644 index 00000000..b0bacf3d --- /dev/null +++ b/Library/Think/Session.php @@ -0,0 +1,160 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Session { + static protected $prefix = ''; + + /** + * 设置或者获取session作用域(前缀) + * @param string $prefix + * @return string|void + */ + static public function prefix($prefix=''){ + if(empty($prefix)) { + return self::$config['prefix']; + }else{ + self::$config['prefix'] = $prefix; + } + } + + /** + * session初始化 + * @param array $config + * @return void + */ + static public function init($config=[]) { + if(isset($config['prefix'])) self::$prefix = $config['prefix']; + if(isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])){ + session_id($_REQUEST[$config['var_session_id']]); + }elseif(isset($config['id'])) { + session_id($config['id']); + } + ini_set('session.auto_start', 0); + if(isset($config['name'])) session_name($config['name']); + if(isset($config['path'])) session_save_path($config['path']); + if(isset($config['domain'])) ini_set('session.cookie_domain', $config['domain']); + if(isset($config['expire'])) ini_set('session.gc_maxlifetime', $config['expire']); + if(isset($config['use_trans_sid'])) ini_set('session.use_trans_sid', $config['use_trans_sid']?1:0); + if(isset($config['use_cookies'])) ini_set('session.use_cookies', $config['use_cookies']?1:0); + if(isset($config['cache_limiter'])) session_cache_limiter($config['cache_limiter']); + if(isset($config['cache_expire'])) session_cache_expire($config['cache_expire']); + if(!empty($config['type'])) { // 读取session驱动 + $class = 'Think\\Session\\Driver\\'. ucwords(strtolower($config['type'])); + // 检查驱动类 + session_set_save_handler(new $class()); + } + // 启动session + if($config['auto_start']) session_start(); + } + + /** + * session设置 + * @param string $name session名称 + * @param mixed $value session值 + * @param string $prefix 作用域(前缀) + * @return void + */ + static public function set($name,$value='',$prefix='') { + $prefix = $prefix?$prefix:self::$prefix; + if($prefix){ + if (!is_array($_SESSION[$prefix])) { + $_SESSION[$prefix] = []; + } + $_SESSION[$prefix][$name] = $value; + }else{ + $_SESSION[$name] = $value; + } + } + + /** + * session获取 + * @param string $name session名称 + * @param string $prefix 作用域(前缀) + * @return mixed + */ + static public function get($name,$prefix='') { + $prefix = $prefix?$prefix:self::$prefix; + if($prefix){ // 获取session + return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null; + }else{ + return isset($_SESSION[$name])?$_SESSION[$name]:null; + } + } + + /** + * 删除session数据 + * @param string $name session名称 + * @param string $prefix 作用域(前缀) + * @return void + */ + static public function delete($name,$prefix='') { + $prefix = $prefix?$prefix:$this->prefix; + if($prefix){ + unset($_SESSION[$prefix][$name]); + }else{ + unset($_SESSION[$name]); + } + } + + /** + * 清空session数据 + * @param string $prefix 作用域(前缀) + * @return void + */ + static public function clear($prefix='') { + $prefix = $prefix?$prefix:self::$prefix; + if($prefix) { + unset($_SESSION[$prefix]); + }else{ + $_SESSION = []; + } + } + + /** + * 判断session数据 + * @param string $name session名称 + * @param mixed $value session值 + * @return boolean + */ + static public function has($name,$prefix='') { + $prefix = $prefix?$prefix:self::$prefix; + if($prefix){ + return isset($_SESSION[$prefix][$name]); + }else{ + return isset($_SESSION[$name]); + } + } + + /** + * session管理 + * @param string $name session操作名称 + * @return void + */ + static public function operate($name) { + if('pause'==$name){ // 暂停session + session_write_close(); + }elseif('start'==$name){ // 启动session + session_start(); + }elseif('destroy'==$name){ // 销毁session + $_SESSION = []; + session_unset(); + session_destroy(); + }elseif('regenerate'==$name){ // 重新生成id + session_regenerate_id(); + } + } + + static public function __callStatic($name,$args) { + self::operate($name); + } +} diff --git a/Library/Think/Tag.php b/Library/Think/Tag.php new file mode 100644 index 00000000..36d0b4ed --- /dev/null +++ b/Library/Think/Tag.php @@ -0,0 +1,84 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Tag { + + static private $tags = []; + + /** + * 动态添加行为扩展到某个标签 + * @param string $tag 标签名称 + * @param mixed $behavior 行为名称 + * @return void + */ + static public function add($tag,$behavior) { + if(is_array($behavior)) { + self::$tags[$tag] = array_merge(self::$tags[$tag],$behavior); + }else{ + self::$tags[$tag][] = $behavior; + } + } + + /** + * 批量导入行为 + * @param array $tags 标签行为 + * @return void + */ + static public function import($tags) { + self::$tags = array_merge(self::$tags,$tags); + } + + /** + * 监听标签的行为 + * @param string $tag 标签名称 + * @param mixed $params 传入参数 + * @return void + */ + static public function listen($tag, &$params=NULL) { + if(isset(self::$tags[$tag])) { + foreach (self::$tags[$tag] as $val) { + Debug::remark('behavior_start','time'); + $result = self::exec($val, $params); + Debug::remark('behavior_end','time'); + Log::record('Run '.$val.' Behavior [ RunTime:'.Debug::getUseTime('behavior_start','behavior_end').'s ]','INFO'); + if(false === $result) { + // 如果返回false 则中断行为执行 + return ; + } + } + } + return; + } + + /** + * 执行某个行为 + * @param string $name 行为名称 + * @param Mixed $params 传人的参数 + * @return void + */ + static public function exec($name, &$params=NULL) { + if($name instanceof \Closure) { + return $name($params); + } + if(false === strpos($name,'\\')) { + $class = '\\'.ucwords(MODULE_NAME).'\\Behavior\\'.$name; + }else{ + $class = $name; + } + if(class_exists($class)) { + $behavior = new $class(); + return $behavior->run($params); + } + return ; + } +} diff --git a/Library/Think/Template.php b/Library/Think/Template.php new file mode 100644 index 00000000..63ae6aa7 --- /dev/null +++ b/Library/Think/Template.php @@ -0,0 +1,733 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +/** + * ThinkPHP分离出来的模板引擎 + * 支持XML标签和普通标签的模板解析 + * 编译型模板引擎 支持动态缓存 + */ +class Template { + protected $tVar = []; // 模板变量 + protected $config = [ // 引擎配置 + 'tpl_path' => '', + 'tpl_suffix' => '.html', // 默认模板文件后缀 + 'cache_suffix' => '.php', // 默认模板缓存后缀 + 'tpl_deny_func_list' => 'echo,exit', // 模板引擎禁用函数 + 'tpl_deny_php' => false, // 默认模板引擎是否禁用PHP原生代码 + 'tpl_begin' => '{', // 模板引擎普通标签开始标记 + 'tpl_end' => '}', // 模板引擎普通标签结束标记 + 'strip_space' => false, // 是否去除模板文件里面的html空格与换行 + 'tpl_cache' => true, // 是否开启模板编译缓存,设为false则每次都会重新编译 + 'compile_type' => 'file', + 'cache_path' => '', + 'cache_prefix' => '', // 模板缓存前缀标识,可以动态改变 + 'cache_time' => 0, // 模板缓存有效期 0 为永久,(以数字为值,单位:秒) + 'layout_item' => '{__CONTENT__}', // 布局模板的内容替换标识 + 'taglib_begin' => '<', // 标签库标签开始标记 + 'taglib_end' => '>', // 标签库标签结束标记 + 'taglib_load' => true, // 是否使用内置标签库之外的其它标签库,默认自动检测 + 'taglib_build_in' => 'cx', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序 + 'taglib_pre_load' => '', // 需要额外加载的标签库(须指定标签库名称),多个以逗号分隔 + 'display_cache' => false, + ]; + + private $literal = []; + private $block = []; + protected $storage = null; + + /** + * 架构函数 + * @access public + */ + public function __construct($config=[]){ + if(!empty($config)) { + $this->config = array_merge($this->config,$config); + } + $this->config['taglib_begin'] = $this->stripPreg($this->config['taglib_begin']); + $this->config['taglib_end'] = $this->stripPreg($this->config['taglib_end']); + $this->config['tpl_begin'] = $this->stripPreg($this->config['tpl_begin']); + $this->config['tpl_end'] = $this->stripPreg($this->config['tpl_end']); + + // 初始化模板编译存储器 + $type = $this->config['compile_type']?$this->config['compile_type']:'File'; + $class = '\Think\Template\Driver\\'.ucwords($type); + $this->storage = new $class(); + } + + /** + * 字符串替换 避免正则混淆 + * @access private + * @param string $str + */ + private function stripPreg($str) { + return str_replace( + ['{','}','(',')','|','[',']','-','+','*','.','^','?'], + ['\{','\}','\(','\)','\|','\[','\]','\-','\+','\*','\.','\^','\?'], + $str); + } + + /** + * 模板变量赋值 + * @access public + * @param mixed $name + * @param mixed $value + */ + public function assign($name,$value=''){ + if(is_array($name)) { + $this->tVar = array_merge($this->tVar,$name); + }else { + $this->tVar[$name] = $value; + } + } + + /** + * 模板引擎参数赋值 + * @access public + * @param mixed $name + * @param mixed $value + */ + public function __set($name,$value){ + $this->config[$name] = $value; + } + + public function config($config){ + $this->config = array_merge($this->config,$config); + } + + public function get($name){ + return $this->tVar[$name]; + } + + /** + * 渲染模板文件 + * @access public + * @param string $template 模板文件 + * @param array $vars 模板变量 + * @param array $config 模板参数 + * @return void + */ + public function display($template,$vars=[],$config=[]) { + if($vars){ + $this->tVar = $vars; + } + if($config){ + $this->config($config); + } + $template = $this->parseTemplateFile($template); + $cacheFile = $this->config['cache_path'].$this->config['cache_prefix'].md5($template).$this->config['cache_suffix']; + if(!$this->checkCache($template,$cacheFile)) { // 缓存无效 + // 模板编译 + $this->compiler(file_get_contents($template),$cacheFile); + } + // 页面缓存 + ob_start(); + ob_implicit_flush(0); + // 读取编译存储 + $this->storage->read($cacheFile,$this->tVar); + // 获取并清空缓存 + $content = ob_get_clean(); + if($this->config['cache_id'] && $this->config['display_cache']) { + // 缓存页面输出 + Cache::set($this->config['cache_id'],$content,$this->config['cache_time']); + } + echo $content; + } + + /** + * 渲染模板内容 + * @access public + * @param string $content 模板内容 + * @param array $vars 模板变量 + * @return void + */ + public function fetch($content,$vars=[]) { + if($vars){ + $this->tVar = $vars; + } + $cacheFile = $this->config['cache_path'].$this->config['cache_prefix'].md5($content).$this->config['cache_suffix']; + if(!$this->checkCache($content,$cacheFile)) { // 缓存无效 + // 模板编译 + $this->compiler($content,$cacheFile); + } + // 读取编译存储 + $this->storage->read($cacheFile,$this->tVar); + } + + /** + * 检查编译缓存是否有效 + * 如果无效则需要重新编译 + * @access private + * @param string $template 模板文件名 + * @param string $cacheFile 缓存文件名 + * @return boolen + */ + private function checkCache($template,$cacheFile) { + if (!$this->config['tpl_cache']) // 优先对配置设定检测 + return false; + // 检查编译存储是否有效 + return $this->storage->check($template,$cacheFile,$this->config['cache_time']); + } + + public function isCache($cacheId){ + if($cacheId && $this->config['display_cache']) { + // 缓存页面输出 + return Cache::get($cacheId)?true:false; + } + return null; + } + + /** + * 编译模板文件内容 + * @access private + * @param string $content 模板内容 + * @param string $cacheFile 缓存文件名 + * @return void + */ + private function compiler($content,$cacheFile) { + // 模板解析 + $content = $this->parse($content); + // 还原被替换的Literal标签 + $content = preg_replace('//eis',"\$this->restoreLiteral('\\1')",$content); + // 添加安全代码 + $content = ''.$content; + if($this->config['strip_space']) { + /* 去除html空格与换行 */ + $find = ['~>\s+<~','~>(\s+\n|\r)~']; + $replace = ['><','>']; + $content = preg_replace($find, $replace, $content); + } + // 优化生成的php代码 + $content = str_replace('?>storage->write($cacheFile,$content); + return ; + } + + /** + * 模板解析入口 + * 支持普通标签和TagLib解析 支持自定义标签库 + * @access public + * @param string $content 要解析的模板内容 + * @return string + */ + public function parse($content) { + // 内容为空不解析 + if(empty($content)) return ''; + $begin = $this->config['taglib_begin']; + $end = $this->config['taglib_end']; + // 检查include语法 + $content = $this->parseInclude($content); + // 检查PHP语法 + $content = $this->parsePhp($content); + // 首先替换literal标签内容 + $content = preg_replace('/'.$begin.'literal'.$end.'(.*?)'.$begin.'\/literal'.$end.'/eis',"\$this->parseLiteral('\\1')",$content); + + // 获取需要引入的标签库列表 + // 标签库只需要定义一次,允许引入多个一次 + // 一般放在文件的最前面 + // 格式: + // 当TAGLIB_LOAD配置为true时才会进行检测 + if($this->config['taglib_load']) { + $tagLibs = $this->getIncludeTagLib($content); + if(!empty($tagLibs)) { + // 对导入的TagLib进行解析 + foreach($tagLibs as $tagLibName) { + $this->parseTagLib($tagLibName,$content); + } + } + } + // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀 + if($this->config['taglib_pre_load']) { + $tagLibs = explode(',',$this->config['taglib_pre_load']); + foreach ($tagLibs as $tag){ + $this->parseTagLib($tag,$content); + } + } + // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀 + $tagLibs = explode(',',$this->config['taglib_build_in']); + foreach ($tagLibs as $tag){ + $this->parseTagLib($tag,$content,true); + } + // 解析普通模板标签 {tagName} + $content = preg_replace('/('.$this->config['tpl_begin'].')([^\d\s'.$this->config['tpl_begin'].$this->config['tpl_end'].'].+?)('.$this->config['tpl_end'].')/eis',"\$this->parseTag('\\2','\\0')",$content); + return $content; + } + + // 检查PHP语法 + private function parsePhp($content) { + if(ini_get('short_open_tag')){ + // 开启短标签的情况要将'."\n", $content ); + } + // PHP语法检查 + if($this->config['tpl_deny_php'] && false !== strpos($content,'parseExtend($content); + // 解析布局 + $content = $this->parseLayout($content); + // 读取模板中的include标签 + $find = preg_match_all('/'.$this->config['taglib_begin'].'include\s(.+?)\s*?\/'.$this->config['taglib_end'].'/is',$content,$matches); + if($find) { + for($i=0;$i<$find;$i++) { + $include = $matches[1][$i]; + $array = $this->parseXmlAttrs($include); + $file = $array['file']; + unset($array['file']); + $content = str_replace($matches[0][$i],$this->parseIncludeItem($file,$array),$content); + } + } + return $content; + } + + // 解析模板中的布局标签 + private function parseLayout($content) { + // 读取模板中的布局标签 + $find = preg_match('/'.$this->config['taglib_begin'].'layout\s(.+?)\s*?\/'.$this->config['taglib_end'].'/is',$content,$matches); + if($find) { + //替换Layout标签 + $content = str_replace($matches[0],'',$content); + //解析Layout标签 + $array = $this->parseXmlAttrs($matches[1]); + // 读取布局模板 + $layoutFile = $this->config['tpl_path'].$array['name'].$this->config['tpl_suffix']; + $replace = isset($array['replace'])?$array['replace']:$this->config['layout_item']; + // 替换布局的主体内容 + $content = str_replace($replace,$content,file_get_contents($layoutFile)); + }else{ + $content = str_replace('{__NOLAYOUT__}','',$content); + } + return $content; + } + + // 解析模板中的extend标签 + private function parseExtend($content) { + $begin = $this->config['taglib_begin']; + $end = $this->config['taglib_end']; + // 读取模板中的继承标签 + $find = preg_match('/'.$begin.'extend\s(.+?)\s*?\/'.$end.'/is',$content,$matches); + if($find) { + //替换extend标签 + $content = str_replace($matches[0],'',$content); + // 记录页面中的block标签 + preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"\$this->parseBlock('\\1','\\2')",$content); + // 读取继承模板 + $array = $this->parseXmlAttrs($matches[1]); + $content = $this->parseTemplateName($array['name']); + // 替换block标签 + $content = preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"\$this->replaceBlock('\\1','\\2')",$content); + }else{ + $content = preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"stripslashes('\\2')",$content); + } + return $content; + } + + /** + * 分析XML属性 + * @access private + * @param string $attrs XML属性字符串 + * @return array + */ + private function parseXmlAttrs($attrs) { + $xml = ''; + $xml = simplexml_load_string($xml); + if(!$xml) + exit('_XML_TAG_ERROR_'); + $xml = (array)($xml->tag->attributes()); + $array = array_change_key_case($xml['@attributes']); + return $array; + } + + /** + * 替换页面中的literal标签 + * @access private + * @param string $content 模板内容 + * @return string + */ + private function parseLiteral($content) { + if(trim($content)=='') return ''; + $content = stripslashes($content); + $i = count($this->literal); + $parseStr = ""; + $this->literal[$i] = $content; + return $parseStr; + } + + /** + * 还原被替换的literal标签 + * @access private + * @param string $tag literal标签序号 + * @return string + */ + private function restoreLiteral($tag) { + // 还原literal标签 + $parseStr = $this->literal[$tag]; + // 销毁literal记录 + unset($this->literal[$tag]); + return $parseStr; + } + + /** + * 记录当前页面中的block标签 + * @access private + * @param string $name block名称 + * @param string $content 模板内容 + * @return string + */ + private function parseBlock($name,$content) { + $this->block[$name] = $content; + return ''; + } + + /** + * 替换继承模板中的block标签 + * @access private + * @param string $name block名称 + * @param string $content 模板内容 + * @return string + */ + private function replaceBlock($name,$content) { + // 替换block标签 没有重新定义则使用原来的 + $replace = isset($this->block[$name])? $this->block[$name] : $content; + return stripslashes($replace); + } + + /** + * 搜索模板页面中包含的TagLib库 + * 并返回列表 + * @access private + * @param string $content 模板内容 + * @return array + */ + private function getIncludeTagLib(& $content) { + //搜索是否有TagLib标签 + $find = preg_match('/'.$this->config['taglib_begin'].'taglib\s(.+?)(\s*?)\/'.$this->config['taglib_end'].'\W/is',$content,$matches); + if($find) { + //替换TagLib标签 + $content = str_replace($matches[0],'',$content); + //解析TagLib标签 + $array = $this->parseXmlAttrs($matches[1]); + return explode(',',$array['name']); + } + return []; + } + + /** + * TagLib库解析 + * @access private + * @param string $tagLib 要解析的标签库 + * @param string $content 要解析的模板内容 + * @param boolen $hide 是否隐藏标签库前缀 + * @return void + */ + protected function parseTagLib($tagLib,&$content,$hide=false) { + $begin = $this->config['taglib_begin']; + $end = $this->config['taglib_end']; + $className = '\\Think\\Template\\TagLib\\'.ucwords($tagLib); + $tLib = new $className($this); + foreach ($tLib->getTags() as $name=>$val){ + $tags = [$name]; + if(isset($val['alias'])) {// 别名设置 + $tags = explode(',',$val['alias']); + $tags[] = $name; + } + $level = isset($val['level'])?$val['level']:1; + $closeTag = isset($val['close'])?$val['close']:true; + foreach ($tags as $tag){ + $parseTag = !$hide? $tagLib.':'.$tag: $tag;// 实际要解析的标签名称 + if(!method_exists($tLib,'_'.$tag)) { + // 别名可以无需定义解析方法 + $tag = $name; + } + $n1 = empty($val['attr'])?'(\s*?)':'\s([^'.$end.']*)'; + if (!$closeTag){ + $patterns = '/'.$begin.$parseTag.$n1.'\/(\s*?)'.$end.'/eis'; + $replacement = "\$this->parseXmlTag(\$tLib,'$tagLib','$tag','$1','')"; + $content = preg_replace($patterns, $replacement,$content); + }else{ + $patterns = '/'.$begin.$parseTag.$n1.$end.'(.*?)'.$begin.'\/'.$parseTag.'(\s*?)'.$end.'/eis'; + $replacement = "\$this->parseXmlTag(\$tLib,'$tagLib','$tag','$1','$2')"; + for($i=0;$i<$level;$i++) + $content=preg_replace($patterns,$replacement,$content); + } + } + } + } + + /** + * 解析标签库的标签 + * 需要调用对应的标签库文件解析类 + * @access private + * @param object $tLib 模板引擎实例 + * @param string $tagLib 标签库名称 + * @param string $tag 标签名 + * @param string $attr 标签属性 + * @param string $content 标签内容 + * @return string + */ + private function parseXmlTag($tLib,$tagLib,$tag,$attr,$content) { + $attr = stripslashes($attr); + $content= stripslashes($content); + if(ini_get('magic_quotes_sybase')) + $attr = str_replace('\"','\'',$attr); + $parse = '_'.$tag; + $content = trim($content); + $tags = $tLib->parseXmlAttr($attr,$tag); + $tLib->tpl = $this; + return $tLib->$parse($tags,$content); + } + + /** + * 模板标签解析 + * 格式: {TagName:args [|content] } + * @access private + * @param string $tagStr 标签内容 + * @param string $content 原始内容 + * @return string + */ + private function parseTag($tagStr,$content){ + $tagStr = stripslashes($tagStr); + + //还原非模板标签 + if(!preg_match('/^[\s|\d]/is',$tagStr)){ + $flag = substr($tagStr,0,1); + $flag2 = substr($tagStr,1,1); + $name = substr($tagStr,1); + if('$' == $flag && '.' != $flag2 && '(' != $flag2){ //解析模板变量 格式 {$varName} + return $this->parseVar($name); + }elseif('-' == $flag || '+'== $flag){ // 输出计算 + return ''; + }elseif(':' == $flag){ // 输出某个函数的结果 + return ''; + }elseif('~' == $flag){ // 执行某个函数 + return ''; + }elseif(substr($tagStr,0,2)=='//' || (substr($tagStr,0,2)=='/*' && substr($tagStr,-2)=='*/')){ + //注释标签 + return ''; + } + } + // 非法标签直接返回 + return $content; + } + + /** + * 模板变量解析,支持使用函数 + * 格式: {$varname|function1|function2=arg1,arg2} + * @access private + * @param string $varStr 变量数据 + * @return string + */ + private function parseVar($varStr){ + $varStr = trim($varStr); + static $_varParseList = []; + //如果已经解析过该变量字串,则直接返回变量值 + if(isset($_varParseList[$varStr])) return $_varParseList[$varStr]; + $parseStr = ''; + if(!empty($varStr)){ + $varArray = explode('|',$varStr); + //取得变量名称 + $var = array_shift($varArray); + if('Think.' == substr($var,0,6)){ + // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出 + $name = $this->parseThinkVar($var); + }elseif( false !== strpos($var,'.')) { + //支持 {$var.property} + $vars = explode('.',$var); + $var = array_shift($vars); + $name = '$'.$var; + foreach ($vars as $key=>$val) + $name .= '["'.$val.'"]'; + }elseif(false !== strpos($var,'[')) { + //支持 {$var['key']} 方式输出数组 + $name = "$".$var; + }elseif(false !==strpos($var,':') && false ===strpos($var,'(') && false ===strpos($var,'::') && false ===strpos($var,'?')){ + //支持 {$var:property} 方式输出对象的属性 + $vars = explode(':',$var); + $var = str_replace(':','->',$var); + $name = "$".$var; + }else { + $name = "$$var"; + } + //对变量使用函数 + if(count($varArray)>0) + $name = $this->parseVarFunction($name,$varArray); + $parseStr = ''; + } + $_varParseList[$varStr] = $parseStr; + return $parseStr; + } + + /** + * 对模板变量使用函数 + * 格式 {$varname|function1|function2=arg1,arg2} + * @access private + * @param string $name 变量名 + * @param array $varArray 函数列表 + * @return string + */ + private function parseVarFunction($name,$varArray){ + //对变量使用函数 + $length = count($varArray); + //取得模板禁止使用函数列表 + $template_deny_funs = explode(',',$this->config['tpl_deny_func_list']); + for($i=0;$i<$length ;$i++ ){ + $args = explode('=',$varArray[$i],2); + //模板函数过滤 + $fun = strtolower(trim($args[0])); + switch($fun) { + case 'default': // 特殊模板函数 + $name = '('.$name.')?('.$name.'):'.$args[1]; + break; + default: // 通用模板函数 + if(!in_array($fun,$template_deny_funs)){ + if(isset($args[1])){ + if(strstr($args[1],'###')){ + $args[1] = str_replace('###',$name,$args[1]); + $name = "$fun($args[1])"; + }else{ + $name = "$fun($name,$args[1])"; + } + }else if(!empty($args[0])){ + $name = "$fun($name)"; + } + } + } + } + return $name; + } + + /** + * 特殊模板变量解析 + * 格式 以 $Think. 打头的变量属于特殊模板变量 + * @access private + * @param string $varStr 变量字符串 + * @return string + */ + private function parseThinkVar($varStr){ + $vars = explode('.',$varStr); + $vars[1] = strtoupper(trim($vars[1])); + $parseStr = ''; + if(count($vars)>=3){ + $vars[2] = trim($vars[2]); + switch($vars[1]){ + case 'SERVER': + $parseStr = '$_SERVER[\''.strtoupper($vars[2]).'\']';break; + case 'GET': + $parseStr = '$_GET[\''.$vars[2].'\']';break; + case 'POST': + $parseStr = '$_POST[\''.$vars[2].'\']';break; + case 'COOKIE': + if(isset($vars[3])) { + $parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']'; + }else{ + $parseStr = 'cookie(\''.$vars[2].'\')'; + } + break; + case 'SESSION': + if(isset($vars[3])) { + $parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']'; + }else{ + $parseStr = 'session(\''.$vars[2].'\')'; + } + break; + case 'ENV': + $parseStr = '$_ENV[\''.strtoupper($vars[2]).'\']';break; + case 'REQUEST': + $parseStr = '$_REQUEST[\''.$vars[2].'\']';break; + case 'CONST': + $parseStr = strtoupper($vars[2]);break; + case 'LANG': + $parseStr = 'L("'.$vars[2].'")';break; + case 'CONFIG': + if(isset($vars[3])) { + $vars[2] .= '.'.$vars[3]; + } + $parseStr = 'C("'.$vars[2].'")';break; + default:break; + } + }else if(count($vars)==2){ + switch($vars[1]){ + case 'NOW': + $parseStr = "date('Y-m-d g:i a',time())"; + break; + case 'VERSION': + $parseStr = 'THINK_TEMPLATE_VERSION'; + break; + case 'LDELIM': + $parseStr = $this->config['tpl_begin']; + break; + case 'RDELIM': + $parseStr = $this->config['tpl_end']; + break; + default: + if(defined($vars[1])) + $parseStr = $vars[1]; + } + } + return $parseStr; + } + + /** + * 加载公共模板并缓存 和当前模板在同一路径,否则使用相对路径 + * @access private + * @param string $tmplPublicName 公共模板文件名 + * @param array $vars 要传递的变量列表 + * @return string + */ + private function parseIncludeItem($tmplPublicName,$vars=[]){ + // 分析模板文件名并读取内容 + $parseStr = $this->parseTemplateName($tmplPublicName); + // 替换变量 + foreach ($vars as $key=>$val) { + if(strpos($val,'['.$key.']')) { + $parseStr = str_replace('['.$key.']',$val,$parseStr); + } + } + // 再次对包含文件进行模板分析 + return $this->parseInclude($parseStr); + } + + /** + * 分析加载的模板文件并读取内容 支持多个模板文件读取 + * @access private + * @param string $tmplPublicName 模板文件名 + * @return string + */ + private function parseTemplateName($templateName){ + if(substr($templateName,0,1)=='$') + //支持加载变量文件名 + $templateName = $this->get(substr($templateName,1)); + $array = explode(',',$templateName); + $parseStr = ''; + foreach ($array as $templateName){ + $template = $this->parseTemplateFile($templateName); + // 获取模板文件内容 + $parseStr .= file_get_contents($template); + } + return $parseStr; + } + + private function parseTemplateFile($template) { + if(false === strpos($template,'.')) { + return $this->config['tpl_path'].$template.$this->config['tpl_suffix']; + }else{ + return $template; + } + } +} diff --git a/Library/Think/Template/Driver/File.php b/Library/Think/Template/Driver/File.php new file mode 100644 index 00000000..c2091e02 --- /dev/null +++ b/Library/Think/Template/Driver/File.php @@ -0,0 +1,45 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Template\Driver; + +class File { + // 写入编译缓存 + public function write($cacheFile,$content){ + // 检测模板目录 + $dir = dirname($cacheFile); + if(!is_dir($dir)) + mkdir($dir,0755,true); + // 生成模板缓存文件 + if( false === file_put_contents($cacheFile,$content)) + E('_CACHE_WRITE_ERROR_:'.$cacheFile); + } + + // 读取编译编译 + public function read($cacheFile,$vars){ + // 模板阵列变量分解成为独立变量 + extract($vars, EXTR_OVERWRITE); + //载入模版缓存文件 + include $cacheFile; + } + + // 检查编译缓存是否有效 + public function check($template,$cacheFile,$cacheTime){ + if(!is_file($cacheFile)|| (is_file($template) && filemtime($template) > filemtime($cacheFile))) { + // 模板文件如果有更新则缓存需要更新 + return false; + }elseif ($cacheTime != 0 && time() > filemtime($cacheFile)+$cacheTime) { + // 缓存是否在有效期 + return false; + } + return true; + } +} diff --git a/Library/Think/Template/TagLib.php b/Library/Think/Template/TagLib.php new file mode 100644 index 00000000..d6bf9a6e --- /dev/null +++ b/Library/Think/Template/TagLib.php @@ -0,0 +1,248 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Template; + +/** + * ThinkPHP标签库TagLib解析基类 + * @category Think + * @package Think + * @subpackage Template + * @author liu21st + */ +class TagLib { + + /** + * 标签库定义XML文件 + * @var string + * @access protected + */ + protected $xml = ''; + protected $tags = [];// 标签定义 + /** + * 标签库名称 + * @var string + * @access protected + */ + protected $tagLib =''; + + /** + * 标签库标签列表 + * @var string + * @access protected + */ + protected $tagList = []; + + /** + * 标签库分析数组 + * @var string + * @access protected + */ + protected $parse = []; + + /** + * 标签库是否有效 + * @var string + * @access protected + */ + protected $valid = false; + + /** + * 当前模板对象 + * @var object + * @access protected + */ + protected $tpl; + + protected $comparison = [' nheq '=>' !== ',' heq '=>' === ',' neq '=>' != ',' eq '=>' == ',' egt '=>' >= ',' gt '=>' > ',' elt '=>' <= ',' lt '=>' < ']; + + public function __construct($template){ + $this->tpl = $template; + } + + /** + * TagLib标签属性分析 返回标签属性数组 + * @access public + * @param string $tagStr 标签内容 + * @return array + */ + public function parseXmlAttr($attr,$tag) { + if(''== trim($attr)) { + return []; + } + //XML解析安全过滤 + $attr = str_replace('&','___', $attr); + $xml = ''; + $xml = simplexml_load_string($xml); + if(!$xml) { + exit('_XML_TAG_ERROR_ : '.$attr); + } + $xml = (array)($xml->tag->attributes()); + $array = array_change_key_case($xml['@attributes']); + if($array) { + $tag = strtolower($tag); + if(isset($this->tags[$tag]['attr'])) { + $attrs = explode(',',$this->tags[$tag]['attr']); + if(isset($this->tags[strtolower($tag)]['must'])){ + $must = explode(',',$this->tags[$tag]['must']); + }else{ + $must = []; + } + foreach($attrs as $name) { + if( isset($array[$name])) { + $array[$name] = str_replace('___','&',$array[$name]); + }elseif(false !== array_search($name,$must)){ + exit('_PARAM_ERROR_:'.$name); + } + } + } + return $array; + } + } + + /** + * 解析条件表达式 + * @access public + * @param string $condition 表达式标签内容 + * @return array + */ + public function parseCondition($condition) { + $condition = str_ireplace(array_keys($this->comparison),array_values($this->comparison),$condition); + $condition = preg_replace('/\$(\w+):(\w+)\s/is','$\\1->\\2 ',$condition); + $condition = preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1["\\2"] ',$condition); + + if(false !== strpos($condition, '$Think')) + $condition = preg_replace('/(\$Think.*?)\s/ies',"\$this->parseThinkVar('\\1');" , $condition); + return $condition; + } + + /** + * 自动识别构建变量 + * @access public + * @param string $name 变量描述 + * @return string + */ + public function autoBuildVar($name) { + if('Think.' == substr($name,0,6)){ + // 特殊变量 + return $this->parseThinkVar($name); + }elseif(strpos($name,'.')) { + $vars = explode('.',$name); + $var = array_shift($vars); + $name = '$'.$var; + foreach ($vars as $key=>$val){ + if(0===strpos($val,'$')) { + $name .= '["{'.$val.'}"]'; + }else{ + $name .= '["'.$val.'"]'; + } + } + }elseif(strpos($name,':')){ + // 额外的对象方式支持 + $name = '$'.str_replace(':','->',$name); + }elseif(!defined($name)) { + $name = '$'.$name; + } + return $name; + } + + /** + * 用于标签属性里面的特殊模板变量解析 + * 格式 以 Think. 打头的变量属于特殊模板变量 + * @access public + * @param string $varStr 变量字符串 + * @return string + */ + public function parseThinkVar($varStr){ + $vars = explode('.',$varStr); + $vars[1] = strtoupper(trim($vars[1])); + $parseStr = ''; + if(count($vars)>=3){ + $vars[2] = trim($vars[2]); + switch($vars[1]){ + case 'SERVER': $parseStr = '$_SERVER[\''.$vars[2].'\']';break; + case 'GET': $parseStr = '$_GET[\''.$vars[2].'\']';break; + case 'POST': $parseStr = '$_POST[\''.$vars[2].'\']';break; + case 'COOKIE': + if(isset($vars[3])) { + $parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']'; + }else{ + $parseStr = '$_COOKIE[\''.$vars[2].'\']'; + } + break; + case 'SESSION': + if(isset($vars[3])) { + $parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']'; + }else{ + $parseStr = '$_SESSION[\''.$vars[2].'\']'; + } + break; + case 'ENV': $parseStr = '$_ENV[\''.$vars[2].'\']';break; + case 'REQUEST': $parseStr = '$_REQUEST[\''.$vars[2].'\']';break; + case 'CONST': $parseStr = strtoupper($vars[2]);break; + case 'LANG': + $parseStr = 'L("'.$vars[2].'")';break; + case 'CONFIG': + if(isset($vars[3])) { + $vars[2] .= '.'.$vars[3]; + } + $parseStr = 'C("'.$vars[2].'")';break; + } + }else if(count($vars)==2){ + switch($vars[1]){ + case 'NOW': $parseStr = "date('Y-m-d g:i a',time())";break; + case 'VERSION': $parseStr = 'THINK_VERSION';break; + default: if(defined($vars[1])) $parseStr = $vars[1]; + } + } + return $parseStr; + } + + /** + * 对模板变量使用函数 + * 格式 {$varname|function1|function2=arg1,arg2} + * @access protected + * @param string $name 变量名 + * @param array $varArray 函数列表 + * @return string + */ + protected function parseVarFunction($name,$varArray){ + //对变量使用函数 + $length = count($varArray); + for($i=0;$i<$length ;$i++ ){ + $args = explode('=',$varArray[$i],2); + //模板函数过滤 + $fun = strtolower(trim($args[0])); + switch($fun) { + case 'default': // 特殊模板函数 + $name = '('.$name.')?('.$name.'):'.$args[1]; + break; + default: // 通用模板函数 + if(isset($args[1])){ + if(strstr($args[1],'###')){ + $args[1] = str_replace('###',$name,$args[1]); + $name = "$fun($args[1])"; + }else{ + $name = "$fun($name,$args[1])"; + } + }else if(!empty($args[0])){ + $name = "$fun($name)"; + } + } + } + return $name; + } + + // 获取标签定义 + public function getTags(){ + return $this->tags; + } +} diff --git a/Library/Think/Template/TagLib/Cx.php b/Library/Think/Template/TagLib/Cx.php new file mode 100644 index 00000000..d97be139 --- /dev/null +++ b/Library/Think/Template/TagLib/Cx.php @@ -0,0 +1,614 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Template\TagLib; +use Think\Template\TagLib; + +/** + * CX标签库解析类 + * @category Think + * @package Think + * @subpackage Driver.Taglib + * @author liu21st + */ +class Cx extends TagLib { + + // 标签定义 + protected $tags = [ + // 标签定义: attr 属性列表 close 是否闭合(0 或者1 默认1) alias 标签别名 level 嵌套层次 + 'php' => [], + 'volist' => ['attr'=>'name,id,offset,length,key,mod','level'=>3,'alias'=>'iterate'], + 'foreach' => ['attr'=>'name,item,key','level'=>3], + 'if' => ['attr'=>'condition','level'=>2], + 'elseif' => ['attr'=>'condition','close'=>0], + 'else' => ['attr'=>'','close'=>0], + 'switch' => ['attr'=>'name','level'=>2], + 'case' => ['attr'=>'value,break'], + 'default' => ['attr'=>'','close'=>0], + 'compare' => ['attr'=>'name,value,type','level'=>3,'alias'=>'eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq'], + 'range' => ['attr'=>'name,value,type','level'=>3,'alias'=>'in,notin,between,notbetween'], + 'empty' => ['attr'=>'name','level'=>3], + 'notempty' => ['attr'=>'name','level'=>3], + 'present' => ['attr'=>'name','level'=>3], + 'notpresent'=> ['attr'=>'name','level'=>3], + 'defined' => ['attr'=>'name','level'=>3], + 'notdefined'=> ['attr'=>'name','level'=>3], + 'import' => ['attr'=>'file,href,type,value,basepath','close'=>0,'alias'=>'load,css,js'], + 'assign' => ['attr'=>'name,value','close'=>0], + 'define' => ['attr'=>'name,value','close'=>0], + 'for' => ['attr'=>'start,end,name,comparison,step', 'level'=>3], + ]; + + /** + * php标签解析 + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _php($tag,$content) { + $parseStr = ''; + return $parseStr; + } + + /** + * volist标签解析 循环输出数据集 + * 格式: + * + * {user.username} + * {user.email} + * + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string|void + */ + public function _volist($tag,$content) { + $name = $tag['name']; + $id = $tag['id']; + $empty = isset($tag['empty'])?$tag['empty']:''; + $key = !empty($tag['key'])?$tag['key']:'i'; + $mod = isset($tag['mod'])?$tag['mod']:'2'; + // 允许使用函数设定数据集 {$vo.name} + $parseStr = 'autoBuildVar($name); + } + $parseStr .= 'if(is_array('.$name.')): $'.$key.' = 0;'; + if(isset($tag['length']) && '' !=$tag['length'] ) { + $parseStr .= ' $__LIST__ = array_slice('.$name.','.$tag['offset'].','.$tag['length'].',true);'; + }elseif(isset($tag['offset']) && '' !=$tag['offset']){ + $parseStr .= ' $__LIST__ = array_slice('.$name.','.$tag['offset'].',null,true);'; + }else{ + $parseStr .= ' $__LIST__ = '.$name.';'; + } + $parseStr .= 'if( count($__LIST__)==0 ) : echo "'.$empty.'" ;'; + $parseStr .= 'else: '; + $parseStr .= 'foreach($__LIST__ as $key=>$'.$id.'): '; + $parseStr .= '$mod = ($'.$key.' % '.$mod.' );'; + $parseStr .= '++$'.$key.';?>'; + $parseStr .= ($content); + $parseStr .= ''; + + if(!empty($parseStr)) { + return $parseStr; + } + return ; + } + + /** + * foreach标签解析 循环输出数据集 + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string|void + */ + public function _foreach($tag,$content) { + $name = $tag['name']; + $item = $tag['item']; + $key = !empty($tag['key'])?$tag['key']:'key'; + $name = $this->autoBuildVar($name); + $parseStr = '$'.$item.'): ?>'; + $parseStr .= ($content); + $parseStr .= ''; + if(!empty($parseStr)) { + return $parseStr; + } + return ; + } + + /** + * if标签解析 + * 格式: + * + * + * + * + * 表达式支持 eq neq gt egt lt elt == > >= < <= or and || && + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _if($tag,$content) { + $condition = $this->parseCondition($tag['condition']); + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * else标签解析 + * 格式:见if标签 + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _elseif($tag,$content) { + $condition = $this->parseCondition($tag['condition']); + $parseStr = ''; + return $parseStr; + } + + /** + * else标签解析 + * @access public + * @param array $tag 标签属性 + * @return string + */ + public function _else($tag) { + $parseStr = ''; + return $parseStr; + } + + /** + * switch标签解析 + * 格式: + * + * 1 + * 2 + * other + * + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _switch($tag,$content) { + $name = $tag['name']; + $varArray = explode('|',$name); + $name = array_shift($varArray); + $name = $this->autoBuildVar($name); + if(count($varArray)>0) + $name = $this->parseVarFunction($name,$varArray); + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * case标签解析 需要配合switch才有效 + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _case($tag,$content) { + $value = $tag['value']; + if('$' == substr($value,0,1)) { + $varArray = explode('|',$value); + $value = array_shift($varArray); + $value = $this->autoBuildVar(substr($value,1)); + if(count($varArray)>0) + $value = $this->parseVarFunction($value,$varArray); + $value = 'case '.$value.': '; + }elseif(strpos($value,'|')){ + $values = explode('|',$value); + $value = ''; + foreach ($values as $val){ + $value .= 'case "'.addslashes($val).'": '; + } + }else{ + $value = 'case "'.$value.'": '; + } + $parseStr = ''.$content; + $isBreak = isset($tag['break']) ? $tag['break'] : ''; + if('' ==$isBreak || $isBreak) { + $parseStr .= ''; + } + return $parseStr; + } + + /** + * default标签解析 需要配合switch才有效 + * 使用: ddfdf + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _default($tag) { + $parseStr = ''; + return $parseStr; + } + + /** + * compare标签解析 + * 用于值的比较 支持 eq neq gt lt egt elt heq nheq 默认是eq + * 格式: content + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _compare($tag,$content,$type='eq') { + $name = $tag['name']; + $value = $tag['value']; + $type = isset($tag['type'])?$tag['type']:$type; + $type = $this->parseCondition(' '.$type.' '); + $varArray = explode('|',$name); + $name = array_shift($varArray); + $name = $this->autoBuildVar($name); + if(count($varArray)>0) + $name = $this->parseVarFunction($name,$varArray); + if('$' == substr($value,0,1)) { + $value = $this->autoBuildVar(substr($value,1)); + }else { + $value = '"'.$value.'"'; + } + $parseStr = ''.$content.''; + return $parseStr; + } + + public function _eq($tag,$content) { + return $this->_compare($tag,$content,'eq'); + } + + public function _equal($tag,$content) { + return $this->_compare($tag,$content,'eq'); + } + + public function _neq($tag,$content) { + return $this->_compare($tag,$content,'neq'); + } + + public function _notequal($tag,$content) { + return $this->_compare($tag,$content,'neq'); + } + + public function _gt($tag,$content) { + return $this->_compare($tag,$content,'gt'); + } + + public function _lt($tag,$content) { + return $this->_compare($tag,$content,'lt'); + } + + public function _egt($tag,$content) { + return $this->_compare($tag,$content,'egt'); + } + + public function _elt($tag,$content) { + return $this->_compare($tag,$content,'elt'); + } + + public function _heq($tag,$content) { + return $this->_compare($tag,$content,'heq'); + } + + public function _nheq($tag,$content) { + return $this->_compare($tag,$content,'nheq'); + } + + /** + * range标签解析 + * 如果某个变量存在于某个范围 则输出内容 type= in 表示在范围内 否则表示在范围外 + * 格式: content + * example: content + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @param string $type 比较类型 + * @return string + */ + public function _range($tag,$content,$type='in') { + $name = $tag['name']; + $value = $tag['value']; + $varArray = explode('|',$name); + $name = array_shift($varArray); + $name = $this->autoBuildVar($name); + if(count($varArray)>0) + $name = $this->parseVarFunction($name,$varArray); + + $type = isset($tag['type'])?$tag['type']:$type; + + if('$' == substr($value,0,1)) { + $value = $this->autoBuildVar(substr($value,1)); + $str = 'is_array('.$value.')?'.$value.':explode(\',\','.$value.')'; + }else{ + $value = '"'.$value.'"'; + $str = 'explode(\',\','.$value.')'; + } + if($type=='between') { + $parseStr = '= $_RANGE_VAR_[0] && '.$name.'<= $_RANGE_VAR_[1]):?>'.$content.''; + }elseif($type=='notbetween'){ + $parseStr = '$_RANGE_VAR_[1]):?>'.$content.''; + }else{ + $fun = ($type == 'in')? 'in_array' : '!in_array'; + $parseStr = ''.$content.''; + } + return $parseStr; + } + + // range标签的别名 用于in判断 + public function _in($tag,$content) { + return $this->_range($tag,$content,'in'); + } + + // range标签的别名 用于notin判断 + public function _notin($tag,$content) { + return $this->_range($tag,$content,'notin'); + } + + public function _between($tag,$content){ + return $this->_range($tag,$content,'between'); + } + + public function _notbetween($tag,$content){ + return $this->_range($tag,$content,'notbetween'); + } + + /** + * present标签解析 + * 如果某个变量已经设置 则输出内容 + * 格式: content + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _present($tag,$content) { + $name = $tag['name']; + $name = $this->autoBuildVar($name); + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * notpresent标签解析 + * 如果某个变量没有设置,则输出内容 + * 格式: content + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _notpresent($tag,$content) { + $name = $tag['name']; + $name = $this->autoBuildVar($name); + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * empty标签解析 + * 如果某个变量为empty 则输出内容 + * 格式: content + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _empty($tag,$content) { + $name = $tag['name']; + $name = $this->autoBuildVar($name); + $parseStr = ''.$content.''; + return $parseStr; + } + + public function _notempty($tag,$content) { + $name = $tag['name']; + $name = $this->autoBuildVar($name); + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * 判断是否已经定义了该常量 + * 已定义 + * @param $tag + * @param $content + * @return string + */ + public function _defined($tag,$content) { + $name = $tag['name']; + $parseStr = ''.$content.''; + return $parseStr; + } + + public function _notdefined($tag,$content) { + $name = $tag['name']; + $parseStr = ''.$content.''; + return $parseStr; + } + + /** + * import 标签解析 + * + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @param boolean $isFile 是否文件方式 + * @param string $type 类型 + * @return string + */ + public function _import($tag,$content,$isFile=false,$type='') { + $file = isset($tag['file'])?$tag['file']:$tag['href']; + $parseStr = ''; + $endStr = ''; + // 判断是否存在加载条件 允许使用函数判断(默认为isset) + if (isset($tag['value'])) { + $varArray = explode('|',$tag['value']); + $name = array_shift($varArray); + $name = $this->autoBuildVar($name); + if (!empty($varArray)) + $name = $this->parseVarFunction($name,$varArray); + else + $name = 'isset('.$name.')'; + $parseStr .= ''; + $endStr = ''; + } + if($isFile) { + // 根据文件名后缀自动识别 + $type = $type?$type:(!empty($tag['type'])?strtolower($tag['type']):null); + // 文件方式导入 + $array = explode(',',$file); + foreach ($array as $val){ + if (!$type || isset($reset)) { + $type = $reset = strtolower(substr(strrchr($val, '.'),1)); + } + switch($type) { + case 'js': + $parseStr .= ''; + break; + case 'css': + $parseStr .= ''; + break; + case 'php': + $parseStr .= ''; + break; + } + } + }else{ + // 命名空间导入模式 默认是js + $type = $type?$type:(!empty($tag['type'])?strtolower($tag['type']):'js'); + $basepath = !empty($tag['basepath'])?$tag['basepath']:__ROOT__.'/Public'; + // 命名空间方式导入外部文件 + $array = explode(',',$file); + foreach ($array as $val){ + list($val,$version) = explode('?',$val); + switch($type) { + case 'js': + $parseStr .= ''; + break; + case 'css': + $parseStr .= ''; + break; + case 'php': + $parseStr .= ''; + break; + } + } + } + return $parseStr.$endStr; + } + + // import别名 采用文件方式加载(要使用命名空间必须用import) 例如 + public function _load($tag,$content) { + return $this->_import($tag,$content,true); + } + + // import别名使用 导入css文件 + public function _css($tag,$content) { + return $this->_import($tag,$content,true,'css'); + } + + // import别名使用 导入js文件 + public function _js($tag,$content) { + return $this->_import($tag,$content,true,'js'); + } + + /** + * assign标签解析 + * 在模板中给某个变量赋值 支持变量赋值 + * 格式: + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _assign($tag,$content) { + $name = $this->autoBuildVar($tag['name']); + if('$'==substr($tag['value'],0,1)) { + $value = $this->autoBuildVar(substr($tag['value'],1)); + }else{ + $value = '\''.$tag['value']. '\''; + } + $parseStr = ''; + return $parseStr; + } + + /** + * define标签解析 + * 在模板中定义常量 支持变量赋值 + * 格式: + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _define($tag,$content) { + $name = '\''.$tag['name']. '\''; + if('$'==substr($tag['value'],0,1)) { + $value = $this->autoBuildVar(substr($tag['value'],1)); + }else{ + $value = '\''.$tag['value']. '\''; + } + $parseStr = ''; + return $parseStr; + } + + /** + * for标签解析 + * 格式: + * @access public + * @param array $tag 标签属性 + * @param string $content 标签内容 + * @return string + */ + public function _for($tag, $content){ + //设置默认值 + $start = 0; + $end = 0; + $step = 1; + $comparison = 'lt'; + $name = 'i'; + $rand = rand(); //添加随机数,防止嵌套变量冲突 + //获取属性 + foreach ($tag as $key => $value){ + $value = trim($value); + if(':'==substr($value,0,1)) + $value = substr($value,1); + elseif('$'==substr($value,0,1)) + $value = $this->autoBuildVar(substr($value,1)); + switch ($key){ + case 'start': + $start = $value; break; + case 'end' : + $end = $value; break; + case 'step': + $step = $value; break; + case 'comparison': + $comparison = $value; break; + case 'name': + $name = $value; break; + } + } + + $parseStr = 'parseCondition('$'.$name.' '.$comparison.' $__FOR_END_'.$rand.'__').';$'.$name.'+='.$step.'){ ?>'; + $parseStr .= $content; + $parseStr .= ''; + return $parseStr; + } +} diff --git a/Library/Think/Transform.php b/Library/Think/Transform.php new file mode 100644 index 00000000..fb234023 --- /dev/null +++ b/Library/Think/Transform.php @@ -0,0 +1,81 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +// 内容解析类 +class Transform { + static private $handler = []; + + /** + * 初始化解析驱动 + * @static + * @access private + * @param string $type 驱动类型 + */ + static private function init($type){ + if(!isset(self::$handler[$type])) { + $class = '\\Think\\Transform\\Driver\\' . ucwords($type); + self::$handler[$type] = new $class(); + } + } + + /** + * 编码内容 + * @static + * @access public + * @param mixed $content 要编码的数据 + * @param string $type 数据类型 + * @param array $config XML配置参数,JSON格式生成无此参数 + * @return string 编码后的数据 + */ + static public function encode($content, $type, array $config = []){ + self::init($type); + return self::$handler[$type]->encode($content, $config); + } + + /** + * 解码数据 + * @param string $content 要解码的数据 + * @param string $type 数据类型 + * @param boolean $assoc 是否返回数组 + * @param array $config XML配置参数,JSON格式解码无此参数 + * @return mixed 解码后的数据 + */ + static public function decode($content, $type, $assoc = true, array $config = []){ + self::init($type); + return self::$handler[$type]->decode($content, $assoc, $config); + } + + // 调用驱动类的方法 + // Transform::xmlEncode('abc') + // Transform::jsonDecode('abc', true); + static public function __callStatic($method, $params){ + if(empty($params[0])){ + return ''; + } + + //获取类型 + $type = substr($method, 0, strlen($method) - 6); + + switch (strtolower(substr($method, -6))) { + case 'encode': + $config = empty($params[1]) ? [] : $params[1]; + return self::encode($params[0], $type, $config); + case 'decode': + $assoc = empty($params[1]) ? true : $params[1]; + $config = empty($params[2]) ? [] : $params[2]; + return self::decode($params[0], $type, $assoc, $config); + default: + throw new Exception("call to undefined method {$method}"); + } + } +} diff --git a/Library/Think/Transform/Driver/Json.php b/Library/Think/Transform/Driver/Json.php new file mode 100644 index 00000000..6a4f0b84 --- /dev/null +++ b/Library/Think/Transform/Driver/Json.php @@ -0,0 +1,22 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Transform\Driver; + +class Json{ + public function encode($data){ + return json_encode($data); + } + + public function decode($data, $assoc = true){ + return json_decode($data, $assoc); + } +} \ No newline at end of file diff --git a/Library/Think/Transform/Driver/Xml.php b/Library/Think/Transform/Driver/Xml.php new file mode 100644 index 00000000..0e0d20f7 --- /dev/null +++ b/Library/Think/Transform/Driver/Xml.php @@ -0,0 +1,119 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Transform\Driver; + +class Xml{ + /** + * XML数据默认配置项 + * @var array + */ + private $config = [ + 'root_name' => 'think', //根节点名称 + 'root_attr' => [], //根节点属性 + 'item_name' => 'item', //数字节点转换的名称 + 'item_key' => 'id', //数字节点转换的属性名 + ]; + + /** + * 编码XML数据 + * @param mixed $data 被编码的数据 + * @param array $config 数据配置项 + * @return string 编码后的XML数据 + */ + public function encode($data, array $config = []) { + //初始化配置 + $config = array_merge($this->config, $config); + + //创建XML对象 + $xml = new \SimpleXMLElement("<{$config['root_name']}>"); + self::data2xml($xml, $data, $config['item_name'], $config['item_key']); + return $xml->asXML(); + } + + /** + * 解码XML数据 + * @param string $str XML字符串 + * @param boolean $assoc 是否转换为数组 + * @param array $config 数据配置项 + * @return string 解码后的XML数据 + */ + public function decode($str, $assoc = true, array $config = []){ + //初始化配置 + $config = array_merge($this->config, $config); + + //创建XML对象 + $xml = new \SimpleXMLElement($str); + if($assoc){ + self::xml2data($xml, $data, $config['item_name'], $config['item_key']); + return $data; + } + + return $xml; + } + + /** + * 数据XML编码 + * @static + * @access public + * @param mixed $data 数据 + * @param string $item 数字索引时的节点名称 + * @param string $id 数字索引key转换为的属性名 + * @return string + */ + static public function data2xml(SimpleXMLElement $xml, $data, $item = 'item', $id = 'id') { + foreach ($data as $key => $value) { + //指定默认的数字key + if(is_numeric($key)){ + $id && $val = $key; + $key = $item; + } + + //添加子元素 + if(is_array($value) || is_object($value)){ + $child = $xml->addChild($key); + self::data2xml($child, $value, $item, $id); + } else { + $child = $xml->addChild($key, $value); + } + + //记录原来的key + isset($val) && $child->addAttribute($id, $val); + } + } + + /** + * 数据XML解码 + * @static + * @access public + * @param SimpleXMLElement $xml xml对象 + * @param array $data 解码后的数据 + * @param string $item 数字索引时的节点名称 + * @param string $id 数字索引key转换为的属性名 + */ + static public function xml2data(SimpleXMLElement $xml, &$data, $item = 'item', $id = 'id'){ + foreach ($xml->children() as $items) { + $key = $items->getName(); + $attr = $items->attributes(); + if($key == $item && isset($attr[$id])){ + $key = strval($attr[$id]); + } + + if($items->count()){ + self::xml2data($items, $val); + } else { + $val = strval($items); + } + + $data[$key] = $val; + } + } +} diff --git a/Library/Think/Upload.php b/Library/Think/Upload.php new file mode 100644 index 00000000..31941de7 --- /dev/null +++ b/Library/Think/Upload.php @@ -0,0 +1,514 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Upload { + protected $config = [ + 'max_size' => -1, // 上传文件的最大值 + 'support_multi' => true, // 是否支持多文件上传 + 'allow_exts' => [], // 允许上传的文件后缀 留空不作后缀检查 + 'allow_types' => [], // 允许上传的文件类型 留空不做检查 + 'thumb' => false, // 使用对上传图片进行缩略图处理 + 'thumb_max_width' => '',// 缩略图最大宽度 + 'thumb_max_height' => '',// 缩略图最大高度 + 'thumb_prefix' => 'thumb_',// 缩略图前缀 + 'thumb_suffix' => '', + 'thumb_path' => '',// 缩略图保存路径 + 'thumb_file' => '',// 缩略图文件名 + 'thumb_ext' => '',// 缩略图扩展名 + 'thumb_remove_origin' => false,// 是否移除原图 + 'zip_images' => false,// 压缩图片文件上传 + 'auto_sub' => false,// 启用子目录保存文件 + 'sub_type' => 'hash',// 子目录创建方式 可以使用hash date custom + 'sub_dir' => '', // 子目录名称 subType为custom方式后有效 + 'date_format' => 'Ymd', + 'hash_level' => 1, // hash的目录层次 + 'save_path' => '',// 上传文件保存路径 + 'auto_check' => true, // 是否自动检查附件 + 'upload_replace' => false,// 存在同名是否覆盖 + 'save_rule' => 'uniqid',// 上传文件命名规则 + 'hash_type' => 'md5_file',// 上传文件Hash规则函数名 + ]; + + // 错误信息 + private $error = ''; + // 上传成功的文件信息 + private $uploadFileInfo ; + + public function __get($name){ + if(isset($this->config[$name])) { + return $this->config[$name]; + } + return null; + } + + public function __set($name,$value){ + if(isset($this->config[$name])) { + $this->config[$name] = $value; + } + } + + public function __isset($name){ + return isset($this->config[$name]); + } + + /** + * 架构函数 + * @access public + * @param array $config 上传参数 + */ + public function __construct($config=[]) { + if(is_array($config)) { + $this->config = array_merge($this->config,$config); + } + } + + /** + * 上传一个文件 + * @access protected + * @param mixed $name 数据 + * @param string $value 数据表名 + * @return string + */ + protected function save($file) { + $filename = $file['save_path'].$file['savename']; + if(!$this->upload_replace && is_file($filename)) { + // 不覆盖同名文件 + $this->error = '文件已经存在!'.$filename; + return false; + } + // 如果是图像文件 检测文件格式 + if( in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png','swf'])) { + $info = getimagesize($file['tmp_name']); + if(false === $info || ('gif' == strtolower($file['extension']) && empty($info['bits']))){ + $this->error = '非法图像文件'; + return false; + } + } + if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) { + $this->error = '文件上传保存错误!'; + return false; + } + if($this->thumb && in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png'])) { + $image = getimagesize($filename); + if(false !== $image) { + //是图像文件生成缩略图 + $thumbWidth = explode(',',$this->thumb_max_width); + $thumbHeight = explode(',',$this->thumb_max_height); + $thumb_prefix = explode(',',$this->thumb_prefix); + $thumb_suffix = explode(',',$this->thumb_suffix); + $thumb_file = explode(',',$this->thumb_file); + $thumb_path = $this->thumb_path?$this->thumb_path:dirname($filename).'/'; + $thumb_ext = $this->thumb_ext ? $this->thumb_ext : $file['extension']; //自定义缩略图扩展名 + // 生成图像缩略图 + for($i=0,$len=count($thumbWidth); $i<$len; $i++) { + if(!empty($thumb_file[$i])) { + $thumbname = $thumb_file[$i]; + }else{ + $prefix = isset($thumb_prefix[$i])?$thumb_prefix[$i]:$thumb_prefix[0]; + $suffix = isset($thumb_suffix[$i])?$thumb_suffix[$i]:$thumb_suffix[0]; + $thumbname = $prefix.basename($filename,'.'.$file['extension']).$suffix; + } + Image::thumb($filename,$thumb_path.$thumbname.'.'.$thumb_ext,'',$thumbWidth[$i],$thumbHeight[$i],true); + } + if($this->thumb_remove_origin) { + // 生成缩略图之后删除原图 + unlink($filename); + } + } + } + if($this->zipImags) { + // TODO 对图片压缩包在线解压 + + } + return true; + } + + /** + * 上传所有文件 + * @access public + * @param string $savePath 上传文件保存路径 + * @return string + */ + public function upload($savePath ='') { + //如果不指定保存文件名,则由系统默认 + if(empty($savePath)) + $savePath = $this->save_path; + // 检查上传目录 + if(!is_dir($savePath)) { + // 检查目录是否编码后的 + if(is_dir(base64_decode($savePath))) { + $savePath = base64_decode($savePath); + }else{ + // 尝试创建目录 + if(!mkdir($savePath)){ + $this->error = '上传目录'.$savePath.'不存在'; + return false; + } + } + }else { + if(!is_writeable($savePath)) { + $this->error = '上传目录'.$savePath.'不可写'; + return false; + } + } + $fileInfo = []; + $isUpload = false; + + // 获取上传的文件信息 + // 对$_FILES数组信息处理 + $files = $this->dealFiles($_FILES); + foreach($files as $key => $file) { + //过滤无效的上传 + if(!empty($file['name'])) { + //登记上传文件的扩展信息 + if(!isset($file['key'])) $file['key'] = $key; + $file['extension'] = $this->getExt($file['name']); + $file['savepath'] = $savePath; + $file['savename'] = $this->getSaveName($file); + + // 自动检查附件 + if($this->auto_check) { + if(!$this->check($file)) + return false; + } + + //保存上传文件 + if(!$this->save($file)) return false; + if(function_exists($this->hash_type)) { + $fun = $this->hash_type; + $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); + } + //上传成功后保存文件信息,供其他地方调用 + unset($file['tmp_name'],$file['error']); + $fileInfo[] = $file; + $isUpload = true; + } + } + if($isUpload) { + $this->uploadFileInfo = $fileInfo; + return true; + }else { + $this->error = '没有选择上传文件'; + return false; + } + } + + /** + * 上传单个上传字段中的文件 支持多附件 + * @access public + * @param array $file 上传文件信息 + * @param string $savePath 上传文件保存路径 + * @return string + */ + public function uploadOne($file,$savePath=''){ + //如果不指定保存文件名,则由系统默认 + if(empty($savePath)) + $savePath = $this->save_path; + // 检查上传目录 + if(!is_dir($savePath)) { + // 尝试创建目录 + if(!mkdir($savePath,0777,true)){ + $this->error = '上传目录'.$savePath.'不存在'; + return false; + } + }else { + if(!is_writeable($savePath)) { + $this->error = '上传目录'.$savePath.'不可写'; + return false; + } + } + //过滤无效的上传 + if(!empty($file['name'])) { + $fileArray = []; + if(is_array($file['name'])) { + $keys = array_keys($file); + $count = count($file['name']); + for ($i=0; $i<$count; $i++) { + foreach ($keys as $key) + $fileArray[$i][$key] = $file[$key][$i]; + } + }else{ + $fileArray[] = $file; + } + $info = []; + foreach ($fileArray as $key=>$file){ + //登记上传文件的扩展信息 + $file['extension'] = $this->getExt($file['name']); + $file['savepath'] = $savePath; + $file['savename'] = $this->getSaveName($file); + // 自动检查附件 + if($this->auto_check) { + if(!$this->check($file)) + return false; + } + //保存上传文件 + if(!$this->save($file)) return false; + if(function_exists($this->hash_type)) { + $fun = $this->hash_type; + $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); + } + unset($file['tmp_name'],$file['error']); + $info[] = $file; + } + // 返回上传的文件信息 + return $info; + }else { + $this->error = '没有选择上传文件'; + return false; + } + } + + /** + * 转换上传文件数组变量为正确的方式 + * @access protected + * @param array $files 上传的文件变量 + * @return array + */ + protected function dealFiles($files) { + $fileArray = []; + $n = 0; + foreach ($files as $key=>$file){ + if(is_array($file['name'])) { + $keys = array_keys($file); + $count = count($file['name']); + for ($i=0; $i<$count; $i++) { + $fileArray[$n]['key'] = $key; + foreach ($keys as $_key){ + $fileArray[$n][$_key] = $file[$_key][$i]; + } + $n++; + } + }else{ + $fileArray[$key] = $file; + } + } + return $fileArray; + } + + /** + * 获取错误代码信息 + * @access public + * @param string $errorNo 错误号码 + * @return void + */ + protected function error($errorNo) { + switch($errorNo) { + case 1: + $this->error = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值'; + break; + case 2: + $this->error = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值'; + break; + case 3: + $this->error = '文件只有部分被上传'; + break; + case 4: + $this->error = '没有文件被上传'; + break; + case 6: + $this->error = '找不到临时文件夹'; + break; + case 7: + $this->error = '文件写入失败'; + break; + default: + $this->error = '未知上传错误!'; + } + return ; + } + + /** + * 根据上传文件命名规则取得保存文件名 + * @access protected + * @param string $filename 数据 + * @return string + */ + protected function getSaveName($filename) { + $rule = $this->save_rule; + if(empty($rule)) {//没有定义命名规则,则保持文件名不变 + $saveName = $filename['name']; + }else { + if(function_exists($rule)) { + //使用函数生成一个唯一文件标识号 + $saveName = $rule().".".$filename['extension']; + }else { + //使用给定的文件名作为标识号 + $saveName = $rule.".".$filename['extension']; + } + } + if($this->auto_sub) { + // 使用子目录保存文件 + $filename['savename'] = $saveName; + $saveName = $this->getSubName($filename).$saveName; + } + return $saveName; + } + + /** + * 获取子目录的名称 + * @access protected + * @param array $file 上传的文件信息 + * @return string + */ + protected function getSubName($file) { + switch($this->sub_type) { + case 'custom': + $dir = $this->sub_dir; + break; + case 'date': + $dir = date($this->date_format,time()).'/'; + break; + case 'hash': + default: + $name = md5($file['savename']); + $dir = ''; + for($i=0;$i<$this->hash_level;$i++) { + $dir .= $name{$i}.'/'; + } + break; + } + if(!is_dir($file['savepath'].$dir)) { + mkdir($file['savepath'].$dir,0777,true); + } + return $dir; + } + + /** + * 检查上传的文件 + * @access protected + * @param array $file 文件信息 + * @return boolean + */ + protected function check($file) { + if($file['error']!== 0) { + //文件上传失败 + //捕获错误代码 + $this->error($file['error']); + return false; + } + //文件上传成功,进行自定义规则检查 + //检查文件大小 + if(!$this->checkSize($file['size'])) { + $this->error = '上传文件大小不符!'; + return false; + } + + //检查文件Mime类型 + if(!$this->checkType($file['type'])) { + $this->error = '上传文件MIME类型不允许!'; + return false; + } + //检查文件类型 + if(!$this->checkExt($file['extension'])) { + $this->error ='上传文件类型不允许'; + return false; + } + + //检查是否合法上传 + if(!$this->checkUpload($file['tmp_name'])) { + $this->error = '非法上传文件!'; + return false; + } + return true; + } + + // 自动转换字符集 支持数组转换 + protected function autoCharset($fContents, $from='gbk', $to='utf-8') { + $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from; + $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to; + if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) { + //如果编码相同或者非字符串标量则不转换 + return $fContents; + } + if (function_exists('mb_convert_encoding')) { + return mb_convert_encoding($fContents, $to, $from); + } elseif (function_exists('iconv')) { + return iconv($from, $to, $fContents); + } else { + return $fContents; + } + } + + /** + * 检查上传的文件类型是否合法 + * @access protected + * @param string $type 数据 + * @return boolean + */ + protected function checkType($type) { + if(!empty($this->allow_types)) + return in_array(strtolower($type),$this->allow_types); + return true; + } + + + /** + * 检查上传的文件后缀是否合法 + * @access protected + * @param string $ext 后缀名 + * @return boolean + */ + protected function checkExt($ext) { + if(!empty($this->allow_exts)) + return in_array(strtolower($ext),$this->allow_exts,true); + return true; + } + + /** + * 检查文件大小是否合法 + * @access protected + * @param integer $size 数据 + * @return boolean + */ + protected function checkSize($size) { + return !($size > $this->max_size) || (-1 == $this->max_size); + } + + /** + * 检查文件是否非法提交 + * @access protected + * @param string $filename 文件名 + * @return boolean + */ + protected function checkUpload($filename) { + return is_uploaded_file($filename); + } + + /** + * 取得上传文件的后缀 + * @access protected + * @param string $filename 文件名 + * @return boolean + */ + protected function getExt($filename) { + return pathinfo($filename,PATHINFO_EXTENSION); + } + + /** + * 取得上传文件的信息 + * @access public + * @return array + */ + public function getUploadFileInfo() { + return $this->uploadFileInfo; + } + + /** + * 取得最后一次错误信息 + * @access public + * @return string + */ + public function getErrorMsg() { + return $this->error; + } +} diff --git a/Library/Think/Url.php b/Library/Think/Url.php new file mode 100644 index 00000000..2bb463ae --- /dev/null +++ b/Library/Think/Url.php @@ -0,0 +1,151 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Url { + + static public function param($num,$default=''){ + $paths = explode(Config::get('url_pathinfo_depr'),trim($_SERVER['PATH_INFO'],'/')); + return isset($paths[$num])?$paths[$num]:$default; + } + + static public function route($route){ + } + + /** + * URL组装 支持不同URL模式 + * @param string $url URL表达式,格式:'[分组/模块/操作#锚点@域名]?参数1=值1&参数2=值2...' + * @param string|array $vars 传入的参数,支持数组和字符串 + * @param string $suffix 伪静态后缀,默认为true表示获取配置值 + * @param boolean $domain 是否显示域名 + * @return string + */ + static public function build($url='',$vars='',$suffix=true,$domain=false) { + // 解析URL + $info = parse_url($url); + $url = !empty($info['path'])?$info['path']:ACTION_NAME; + if(isset($info['fragment'])) { // 解析锚点 + $anchor = $info['fragment']; + if(false !== strpos($anchor,'?')) { // 解析参数 + list($anchor,$info['query']) = explode('?',$anchor,2); + } + if(false !== strpos($anchor,'@')) { // 解析域名 + list($anchor,$host) = explode('@',$anchor, 2); + } + }elseif(false !== strpos($url,'@')) { // 解析域名 + list($url,$host) = explode('@',$info['path'], 2); + } + // 解析子域名 + if(isset($host)) { + $domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.')); + }elseif($domain===true){ + $domain = $_SERVER['HTTP_HOST']; + if(Config::get('app_sub_domain_deplay') ) { // 开启子域名部署 + $domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.'); + // '子域名'=>array('项目[/分组]'); + foreach (Config::get('app_sub_domain_rules') as $key => $rule) { + if(false === strpos($key,'*') && 0=== strpos($url,$rule[0])) { + $domain = $key.strstr($domain,'.'); // 生成对应子域名 + $url = substr_replace($url,'',0,strlen($rule[0])); + break; + } + } + } + } + + // 解析参数 + if(is_string($vars)) { // aaa=1&bbb=2 转换成数组 + parse_str($vars,$vars); + }elseif(!is_array($vars)){ + $vars = []; + } + if(isset($info['query'])) { // 解析地址里面参数 合并到vars + parse_str($info['query'],$params); + $vars = array_merge($params,$vars); + } + + // URL组装 + $depr = Config::get('pathinfo_depr'); + if($url) { + if(0=== strpos($url,'/')) {// 定义路由 + $route = true; + $url = substr($url,1); + if('/' != $depr) { + $url = str_replace('/',$depr,$url); + } + }else{ + if('/' != $depr) { // 安全替换 + $url = str_replace('/',$depr,$url); + } + // 解析分组、模块和操作 + $url = trim($url,$depr); + $path = explode($depr,$url); + $var = []; + $var[Config::get('var_action')] = !empty($path)?array_pop($path):ACTION_NAME; + if(Config::get('require_controller')) { + $var[Config::get('var_controller')] = !empty($path)?array_pop($path):CONTROLLER_NAME; + } + if(Config::get('require_module')) { + $var[Config::get('var_module')] = !empty($path)?array_pop($path):MODULE_NAME; + } + } + } + + if(Config::get('url_model') == 0) { // 普通模式URL转换 + $url = Config::get('base_url').'?'.http_build_query(array_reverse($var)); + if(!empty($vars)) { + $vars = urldecode(http_build_query($vars)); + $url .= '&'.$vars; + } + }else{ // PATHINFO模式或者兼容URL模式 + if(isset($route)) { + $url = Config::get('base_url').'/'.rtrim($url,$depr); + }else{ + $url = Config::get('base_url').'/'.implode($depr,array_reverse($var)); + } + if(!empty($vars)) { // 添加参数 + foreach ($vars as $var => $val){ + if('' !== trim($val)) $url .= $depr . $var . $depr . urlencode($val); + } + } + if($suffix) { + $suffix = $suffix===true?Config::get('url_html_suffix'):$suffix; + if($pos = strpos($suffix, '|')){ + $suffix = substr($suffix, 0, $pos); + } + if($suffix && '/' != substr($url,-1)){ + $url .= '.'.ltrim($suffix,'.'); + } + } + } + if(isset($anchor)){ + $url .= '#'.$anchor; + } + if($domain) { + $url = (self::is_ssl()?'https://':'http://').$domain.$url; + } + return $url; + } + + /** + * 判断是否SSL协议 + * @return boolean + */ + static public function is_ssl() { + if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){ + return true; + }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) { + return true; + } + return false; + } +} diff --git a/Library/Think/Validate.php b/Library/Think/Validate.php new file mode 100644 index 00000000..8c92c3bf --- /dev/null +++ b/Library/Think/Validate.php @@ -0,0 +1,189 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Validate { + + protected $validate = []; // 自动验证定义 + // 是否批处理验证 + protected $patchValidate = false; + protected $error = ''; + + public function rule($rule){ + $this->validate = $rule; + return $this; + } + + public function getError(){ + return $this->error; + } + + /** + * 自动表单验证 + * @access protected + * @param array $data 创建数据 + * @param string $type 创建类型 + * @return boolean + */ + public function valid($data,$rule=[]) { + $validate = $rule?$rule:$this->validate; + // 属性验证 + if($validate) { // 如果设置了数据自动验证则进行数据验证 + if($this->patchValidate) { // 重置验证错误信息 + $this->error = []; + } + foreach($validate as $key=>$val) { + // 验证因子定义格式 + // array(field,rule,message,condition,type,params) + // 判断是否需要执行验证 + if(0==strpos($val[2],'{%') && strpos($val[2],'}')) + // 支持提示信息的多语言 使用 {%语言定义} 方式 + $val[2] = L(substr($val[2],2,-1)); + $val[3] = isset($val[3])?$val[3]:0; + $val[4] = isset($val[4])?$val[4]:'regex'; + // 判断验证条件 + if( 1 == $val[3] || (2 == $val[3] && '' != trim($data[$val[0]])) || (0 == $val[3] && isset($data[$val[0]])) ) { + if(false === $this->_validationField($data,$val)) + return false; + } + } + // 批量验证的时候最后返回错误 + if(!empty($this->error)) return false; + } + return true; + } + + /** + * 验证表单字段 支持批量验证 + * 如果批量验证返回错误的数组信息 + * @access protected + * @param array $data 创建数据 + * @param array $val 验证因子 + * @return boolean + */ + protected function _validationField($data,$val) { + if(false === $this->_validationFieldItem($data,$val)){ + if($this->patchValidate) { + $this->error[$val[0]] = $val[2]; + }else{ + $this->error = $val[2]; + return false; + } + } + return ; + } + + /** + * 根据验证因子验证字段 + * @access protected + * @param array $data 创建数据 + * @param array $val 验证因子 + * @return boolean + */ + protected function _validationFieldItem($data,$val) { + switch(strtolower(trim($val[4]))) { + case 'callback':// 调用方法进行验证 + $args = isset($val[5])?(array)$val[5]:[]; + if(is_string($val[0]) && strpos($val[0], ',')) + $val[0] = explode(',', $val[0]); + if(is_array($val[0])){ + // 支持多个字段验证 + foreach($val[0] as $field) + $_data[$field] = $data[$field]; + array_unshift($args, $_data); + }else{ + array_unshift($args, $data[$val[0]]); + } + return call_user_func_array($val[1], $args); + case 'confirm': // 验证两个字段是否相同 + return $data[$val[0]] == $data[$val[1]]; + default: // 检查附加规则 + return $this->check($data[$val[0]],$val[1],$val[4]); + } + } + + /** + * 验证数据 支持 in between equal length regex expire ip_allow ip_deny + * @access public + * @param string $value 验证数据 + * @param mixed $rule 验证表达式 + * @param string $type 验证方式 默认为正则验证 + * @return boolean + */ + public function check($value,$rule,$type='regex'){ + $type = strtolower(trim($type)); + switch($type) { + case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组 + case 'notin': + $range = is_array($rule)? $rule : explode(',',$rule); + return $type == 'in' ? in_array($value ,$range) : !in_array($value ,$range); + case 'between': // 验证是否在某个范围 + case 'notbetween': // 验证是否不在某个范围 + if (is_array($rule)){ + $min = $rule[0]; + $max = $rule[1]; + }else{ + list($min,$max) = explode(',',$rule); + } + return $type == 'between' ? $value>=$min && $value<=$max : $value<$min || $value>$max; + case 'equal': // 验证是否等于某个值 + case 'notequal': // 验证是否等于某个值 + return $type == 'equal' ? $value == $rule : $value != $rule; + case 'length': // 验证长度 + $length = mb_strlen($value,'utf-8'); // 当前数据长度 + if(strpos($rule,',')) { // 长度区间 + list($min,$max) = explode(',',$rule); + return $length >= $min && $length <= $max; + }else{// 指定长度 + return $length == $rule; + } + case 'expire': + list($start,$end) = explode(',',$rule); + if(!is_numeric($start)) $start = strtotime($start); + if(!is_numeric($end)) $end = strtotime($end); + return NOW_TIME >= $start && NOW_TIME <= $end; + case 'ip_allow': // IP 操作许可验证 + return in_array($_SERVER['REMOTE_ADDR'],explode(',',$rule)); + case 'ip_deny': // IP 操作禁止验证 + return !in_array($_SERVER['REMOTE_ADDR'],explode(',',$rule)); + case 'regex': + default: // 默认使用正则验证 可以使用验证类中定义的验证名称 + // 检查附加规则 + return $this->regex($value,$rule); + } + } + + /** + * 使用正则验证数据 + * @access public + * @param string $value 要验证的数据 + * @param string $rule 验证规则 + * @return boolean + */ + public function regex($value,$rule) { + $validate = [ + 'require' => '/.+/', + 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', + 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', + 'currency' => '/^\d+(\.\d+)?$/', + 'number' => '/^\d+$/', + 'zip' => '/^\d{6}$/', + 'integer' => '/^[-\+]?\d+$/', + 'double' => '/^[-\+]?\d+(\.\d+)?$/', + 'english' => '/^[A-Za-z]+$/', + ]; + // 检查是否有内置的正则表达式 + if(isset($validate[strtolower($rule)])) + $rule = $validate[strtolower($rule)]; + return preg_match($rule,$value)===1; + } +} diff --git a/Library/Think/View.php b/Library/Think/View.php new file mode 100644 index 00000000..7f8e16f1 --- /dev/null +++ b/Library/Think/View.php @@ -0,0 +1,228 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class View { + protected $engine = null; // 模板引擎实例 + protected $theme = ''; // 模板主题名称 + protected $data = []; // 模板变量 + protected $config = [ // 视图参数 + 'http_output_content' => true, + 'http_content_type' => 'text/html', + 'http_charset' => 'utf-8', + 'http_cache_control' => 'private', + 'http_render_content' => false, + 'theme_on' => false, + 'auto_detect_theme' => false, + 'var_theme' => 't', + 'default_theme' => 'default', + 'http_cache_id' => null, + 'view_path' => '', + 'view_suffix' => '.html', + ]; + + /** + * 模板变量赋值 + * @access public + * @param mixed $name 变量名 + * @param mixed $value 变量值 + */ + public function assign($name, $value = ''){ + if(is_array($name)) { + $this->data = array_merge($this->data, $name); + return $this; + }else { + $this->data[$name] = $value; + } + } + + /** + * 视图参数设置 + * @access public + * @param mixed $name + * @param mixed $value + */ + public function __set($name, $value = ''){ + $this->config[$name] = $value; + } + + public function __construct(array $config = []){ + $this->config = array_merge($this->config, $config); + } + + /** + * 设置当前模板解析的引擎 + * @access public + * @param string $engine 引擎名称 + * @param array $config 引擎参数 + * @return View + */ + public function engine($engine, array $config = []){ + $class = '\\Think\\View\\Driver\\' . ucwords($engine); + $this->engine = new $class($config); + return $this; + } + + /** + * 设置当前输出的模板主题 + * @access public + * @param mixed $theme 主题名称 + * @return View + */ + public function theme($theme){ + if(true === $theme) { // 自动侦测 + $this->config['theme_on'] = true; + $this->config['auto_detect_theme'] = true; + }elseif(false === $theme){ // 关闭主题 + $this->config['theme_on'] = false; + }else{ // 指定模板主题 + $this->config['theme_on'] = true; + $this->theme = $theme; + } + return $this; + } + + /** + * 加载模板和页面输出 可以返回输出内容 + * @access public + * @param string $template 模板文件名 + * @param array $vars 模板输出变量 + * @param string $cache_id 模板缓存标识 + * @return mixed + */ + public function display($template = '', $vars = [], $cache_id = '') { + Tag::listen('view_begin', $template); + // 解析并获取模板内容 + $content = $this->fetch($template, $vars, $cache_id); + // 输出内容过滤 + Tag::listen('view_filter', $content); + // 输出模板内容 + if($this->config['http_output_content']) { + $this->render($content); + }else{ // 返回解析后的内容 + return $content; + } + } + + /** + * 解析和获取模板内容 用于输出 + * @access protected + * @param string $template 模板文件名或者内容 + * @param array $vars 模板输出变量 + * @param string $cache_id 模板缓存标识 + * @return string + */ + protected function fetch($template, $vars = [], $cache_id='') { + if(!$this->config['http_render_content']) { + $template = $this->parseTemplate($template); + // 模板不存在 抛出异常 + if(!is_file($template)) + E('template file not exists:' . $template); + } + $vars = $vars ? $vars : $this->data; + // 页面缓存 + ob_start(); + ob_implicit_flush(0); + if($this->engine) { // 指定模板引擎 + $this->engine->fetch($template, $vars, $cache_id); + }else{ // 原生PHP解析 + extract($vars, EXTR_OVERWRITE); + is_file($template) ? include $template : eval('?>' . $template); + } + // 获取并清空缓存 + return ob_get_clean(); + } + + /** + * 自动定位模板文件 + * @access private + * @param string $template 模板文件规则 + * @return string + */ + private function parseTemplate($template) { + if(is_file($template)) { + return $template; + } + $template = str_replace(':', '/', $template); + // 获取当前主题名称 + $theme = $this->getTemplateTheme(); + // 分析模板文件规则 + if('' == $template) { + // 如果模板文件名为空 按照默认规则定位 + $template = CONTROLLER_NAME . '/' . ACTION_NAME; + }elseif(false === strpos($template, '/')){ + $template = CONTROLLER_NAME . '/' . $template; + } + return ($this->config['view_path'] ? $this->config['view_path'] : MODULE_PATH . 'View/').$theme.$template.$this->config['view_suffix']; + } + + /** + * 获取当前的模板主题 + * @access private + * @return string + */ + private function getTemplateTheme() { + if($this->config['theme_on']) { + if($this->theme) { // 指定模板主题 + $theme = $this->theme; + }elseif($this->config['auto_detect_theme']){ + // 自动侦测模板主题 + $t = $this->config['var_theme']; + if (isset($_GET[$t])){ + $theme = $_GET[$t]; + }elseif(Cookie::get('think_theme')){ + $theme = Cookie::get('think_theme'); + } + if(!is_dir(MODULE_PATH . 'View/' . $theme)) { + $theme = $this->config['default_theme']; + } + Cookie::set('think_theme', $theme, 864000); + }else{ + $theme = $this->config['default_theme']; + } + return $theme . '/'; + } + return ''; + } + + /** + * 视图输出参数设置 + * @access public + * @param mixed $config + * @param mixed $value + */ + public function http($config = [], $value = ''){ + if(is_array($config)) { + $this->config = array_merge($this->config, $config); + }else{ + $this->config[$config] = $value; + } + return $this; + } + + /** + * 输出内容文本可以包括Html + * @access private + * @param string $content 输出内容 + * @param string $charset 模板输出字符集 + * @param string $contentType 输出类型 + * @return mixed + */ + private function render($content){ + // 网页字符编码 + header('Content-Type:' . $this->config['http_content_type'] . '; charset=' . $this->config['http_charset']); + header('Cache-control:' . $this->config['http_cache_control']); // 页面缓存控制 + header('X-Powered-By:ThinkPHP'); + // 输出模板文件 + echo $content; + } +} diff --git a/Library/Think/View/Driver/Think.php b/Library/Think/View/Driver/Think.php new file mode 100644 index 00000000..bf73462d --- /dev/null +++ b/Library/Think/View/Driver/Think.php @@ -0,0 +1,28 @@ + +// +---------------------------------------------------------------------- + +namespace Think\View\Driver; +use Think\Template; + +class Think { + private $template = null; + public function __construct($config=[]){ + $this->template = new Template($config); + } + + public function fetch($template,$data=[],$cacheId=''){ + if(is_file($template)) { + $this->template->display($template,$data,$cacheId); + }else{ + $this->template->fetch($template,$data); + } + } +} diff --git a/Tpl/default_index.tpl b/Tpl/default_index.tpl new file mode 100644 index 00000000..4de55d92 --- /dev/null +++ b/Tpl/default_index.tpl @@ -0,0 +1,8 @@ +*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px }

    :)

    欢迎使用 ThinkPHP

    '); + } +} \ No newline at end of file diff --git a/Tpl/dispatch_jump.tpl b/Tpl/dispatch_jump.tpl new file mode 100644 index 00000000..bf035c83 --- /dev/null +++ b/Tpl/dispatch_jump.tpl @@ -0,0 +1,44 @@ + + + + +跳转提示 + + + +
    + +

    :)

    +

    + +

    :(

    +

    +
    +

    +

    +页面自动 跳转 等待时间: +

    +
    + + + \ No newline at end of file diff --git a/Tpl/page_trace.tpl b/Tpl/page_trace.tpl new file mode 100644 index 00000000..caa4c570 --- /dev/null +++ b/Tpl/page_trace.tpl @@ -0,0 +1,67 @@ +
    + + +
    +
    + \ No newline at end of file diff --git a/Tpl/think_exception.tpl b/Tpl/think_exception.tpl new file mode 100644 index 00000000..84b27e97 --- /dev/null +++ b/Tpl/think_exception.tpl @@ -0,0 +1,53 @@ + + + +系统发生错误 + + + +
    +

    :(

    +

    +
    + +
    +
    +

    错误位置

    +
    +
    +

    FILE:  LINE:

    +
    +
    + + +
    +
    +

    TRACE

    +
    +
    +

    +
    +
    + +
    +
    + + + \ No newline at end of file diff --git a/Traits/Think/Model/Auto.php b/Traits/Think/Model/Auto.php new file mode 100644 index 00000000..10122024 --- /dev/null +++ b/Traits/Think/Model/Auto.php @@ -0,0 +1,363 @@ + +// +---------------------------------------------------------------------- + +namespace Traits\Think\Model; +define('EXISTS_VALIDATE',0); +define('MUST_VALIDATE',1); +define('VALUE_VALIDATE',2); + +trait Auto { + + protected $validate = []; // 自动验证定义 + protected $auto = []; // 自动完成定义 + + /** + * 创建数据对象 但不保存到数据库 + * @access public + * @param mixed $data 创建数据 + * @param string $type 状态 + * @return mixed + */ + public function create($data='',$type='') { + // 如果没有传值默认取POST数据 + if(empty($data)) { + $data = $_POST; + }elseif(is_object($data)){ + $data = get_object_vars($data); + } + // 验证数据 + if(empty($data) || !is_array($data)) { + $this->error = L('_DATA_TYPE_INVALID_'); + return false; + } + + // 状态 + $type = $type?$type:(!empty($data[$this->getPk()])?self::MODEL_UPDATE:self::MODEL_INSERT); + + // 检测提交字段的合法性 + if(isset($this->options['field'])) { // $this->field('field1,field2...')->create() + $fields = $this->options['field']; + unset($this->options['field']); + }elseif($type == self::MODEL_INSERT && isset($this->insertFields)) { + $fields = $this->insertFields; + }elseif($type == self::MODEL_UPDATE && isset($this->updateFields)) { + $fields = $this->updateFields; + } + if(isset($fields)) { + if(is_string($fields)) { + $fields = explode(',',$fields); + } + // 判断令牌验证字段 + if(C('TOKEN_ON')) $fields[] = C('TOKEN_NAME'); + foreach ($data as $key=>$val){ + if(!in_array($key,$fields)) { + unset($data[$key]); + } + } + } + + // 数据自动验证 + if(!$this->autoValidation($data,$type)) return false; + + + // 验证完成生成数据对象 + if($this->autoCheckFields) { // 开启字段检测 则过滤非法字段数据 + $fields = $this->getDbFields(); + foreach ($data as $key=>$val){ + if(!in_array($key,$fields)) { + unset($data[$key]); + }elseif(MAGIC_QUOTES_GPC && is_string($val)){ + $data[$key] = stripslashes($val); + } + } + } + + // 创建完成对数据进行自动处理 + $this->autoOperation($data,$type); + // 赋值当前数据对象 + $this->data = $data; + // 返回创建的数据以供其他调用 + return $data; + } + + /** + * 使用正则验证数据 + * @access public + * @param string $value 要验证的数据 + * @param string $rule 验证规则 + * @return boolean + */ + public function regex($value,$rule) { + $validate = array( + 'require' => '/.+/', + 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', + 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', + 'currency' => '/^\d+(\.\d+)?$/', + 'number' => '/^\d+$/', + 'zip' => '/^\d{6}$/', + 'integer' => '/^[-\+]?\d+$/', + 'double' => '/^[-\+]?\d+(\.\d+)?$/', + 'english' => '/^[A-Za-z]+$/', + ); + // 检查是否有内置的正则表达式 + if(isset($validate[strtolower($rule)])) + $rule = $validate[strtolower($rule)]; + return preg_match($rule,$value)===1; + } + + /** + * 自动表单处理 + * @access public + * @param array $data 创建数据 + * @param string $type 创建类型 + * @return mixed + */ + private function autoOperation(&$data,$type) { + if(!empty($this->options['auto'])) { + $_auto = $this->options['auto']; + unset($this->options['auto']); + }elseif(!empty($this->auto)){ + $_auto = $this->auto; + } + // 自动填充 + if(isset($_auto)) { + foreach ($_auto as $auto){ + // 填充因子定义格式 + // array('field','填充内容','填充条件','附加规则',[额外参数]) + if(empty($auto[2])) $auto[2] = self::MODEL_INSERT; // 默认为新增的时候自动填充 + if( $type == $auto[2] || $auto[2] == self::MODEL_BOTH) { + switch(trim($auto[3])) { + case 'function': // 使用函数进行填充 字段的值作为参数 + case 'callback': // 使用回调方法 + $args = isset($auto[4])?(array)$auto[4]:[]; + if(isset($data[$auto[0]])) { + array_unshift($args,$data[$auto[0]]); + } + if('function'==$auto[3]) { + $data[$auto[0]] = call_user_func_array($auto[1], $args); + }else{ + $data[$auto[0]] = call_user_func_array(array(&$this,$auto[1]), $args); + } + break; + case 'field': // 用其它字段的值进行填充 + $data[$auto[0]] = $data[$auto[1]]; + break; + case 'ignore': // 为空忽略 + if(''===$data[$auto[0]]) + unset($data[$auto[0]]); + break; + case 'string': + default: // 默认作为字符串填充 + $data[$auto[0]] = $auto[1]; + } + if(false === $data[$auto[0]] ) unset($data[$auto[0]]); + } + } + } + return $data; + } + + /** + * 自动表单验证 + * @access protected + * @param array $data 创建数据 + * @param string $type 创建类型 + * @return boolean + */ + protected function autoValidation($data,$type) { + if(!empty($this->options['validate'])) { + $validate = $this->options['validate']; + unset($this->options['validate']); + }elseif(!empty($this->validate)){ + $validate = $this->validate; + } + // 属性验证 + if(isset($validate)) { // 如果设置了数据自动验证则进行数据验证 + if($this->patchValidate) { // 重置验证错误信息 + $this->error = []; + } + foreach($validate as $key=>$val) { + // 验证因子定义格式 + // array(field,rule,message,condition,type,when,params) + // 判断是否需要执行验证 + if(empty($val[5]) || $val[5]== self::MODEL_BOTH || $val[5]== $type ) { + if(0==strpos($val[2],'{%') && strpos($val[2],'}')) + // 支持提示信息的多语言 使用 {%语言定义} 方式 + $val[2] = L(substr($val[2],2,-1)); + $val[3] = isset($val[3])?$val[3]:EXISTS_VALIDATE; + $val[4] = isset($val[4])?$val[4]:'regex'; + // 判断验证条件 + switch($val[3]) { + case MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段 + if(false === $this->_validationField($data,$val)) + return false; + break; + case VALUE_VALIDATE: // 值不为空的时候才验证 + if('' != trim($data[$val[0]])) + if(false === $this->_validationField($data,$val)) + return false; + break; + default: // 默认表单存在该字段就验证 + if(isset($data[$val[0]])) + if(false === $this->_validationField($data,$val)) + return false; + } + } + } + // 批量验证的时候最后返回错误 + if(!empty($this->error)) return false; + } + return true; + } + + /** + * 验证表单字段 支持批量验证 + * 如果批量验证返回错误的数组信息 + * @access protected + * @param array $data 创建数据 + * @param array $val 验证因子 + * @return boolean + */ + protected function _validationField($data,$val) { + if(false === $this->_validationFieldItem($data,$val)){ + if($this->patchValidate) { + $this->error[$val[0]] = $val[2]; + }else{ + $this->error = $val[2]; + return false; + } + } + return ; + } + + /** + * 根据验证因子验证字段 + * @access protected + * @param array $data 创建数据 + * @param array $val 验证因子 + * @return boolean + */ + protected function _validationFieldItem($data,$val) { + switch(strtolower(trim($val[4]))) { + case 'function':// 使用函数进行验证 + case 'callback':// 调用方法进行验证 + $args = isset($val[6])?(array)$val[6]:[]; + if(is_string($val[0]) && strpos($val[0], ',')) + $val[0] = explode(',', $val[0]); + if(is_array($val[0])){ + // 支持多个字段验证 + foreach($val[0] as $field) + $_data[$field] = $data[$field]; + array_unshift($args, $_data); + }else{ + array_unshift($args, $data[$val[0]]); + } + if('function'==$val[4]) { + return call_user_func_array($val[1], $args); + }else{ + return call_user_func_array(array(&$this, $val[1]), $args); + } + case 'confirm': // 验证两个字段是否相同 + return $data[$val[0]] == $data[$val[1]]; + case 'unique': // 验证某个值是否唯一 + if(is_string($val[0]) && strpos($val[0],',')) + $val[0] = explode(',',$val[0]); + $map = []; + if(is_array($val[0])) { + // 支持多个字段验证 + foreach ($val[0] as $field) + $map[$field] = $data[$field]; + }else{ + $map[$val[0]] = $data[$val[0]]; + } + if(!empty($data[$this->getPk()])) { // 完善编辑的时候验证唯一 + $map[$this->getPk()] = array('neq',$data[$this->getPk()]); + } + if($this->where($map)->find()) return false; + return true; + default: // 检查附加规则 + return $this->check($data[$val[0]],$val[1],$val[4]); + } + } + + /** + * 验证数据 支持 in between equal length regex expire ip_allow ip_deny + * @access public + * @param string $value 验证数据 + * @param mixed $rule 验证表达式 + * @param string $type 验证方式 默认为正则验证 + * @return boolean + */ + public function check($value,$rule,$type='regex'){ + $type = strtolower(trim($type)); + switch($type) { + case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组 + case 'notin': + $range = is_array($rule)? $rule : explode(',',$rule); + return $type == 'in' ? in_array($value ,$range) : !in_array($value ,$range); + case 'between': // 验证是否在某个范围 + case 'notbetween': // 验证是否不在某个范围 + if (is_array($rule)){ + $min = $rule[0]; + $max = $rule[1]; + }else{ + list($min,$max) = explode(',',$rule); + } + return $type == 'between' ? $value>=$min && $value<=$max : $value<$min || $value>$max; + case 'equal': // 验证是否等于某个值 + case 'notequal': // 验证是否等于某个值 + return $type == 'equal' ? $value == $rule : $value != $rule; + case 'length': // 验证长度 + $length = mb_strlen($value,'utf-8'); // 当前数据长度 + if(strpos($rule,',')) { // 长度区间 + list($min,$max) = explode(',',$rule); + return $length >= $min && $length <= $max; + }else{// 指定长度 + return $length == $rule; + } + case 'expire': + list($start,$end) = explode(',',$rule); + if(!is_numeric($start)) $start = strtotime($start); + if(!is_numeric($end)) $end = strtotime($end); + return NOW_TIME >= $start && NOW_TIME <= $end; + case 'ip_allow': // IP 操作许可验证 + return in_array(get_client_ip(),explode(',',$rule)); + case 'ip_deny': // IP 操作禁止验证 + return !in_array(get_client_ip(),explode(',',$rule)); + case 'regex': + default: // 默认使用正则验证 可以使用验证类中定义的验证名称 + // 检查附加规则 + return $this->regex($value,$rule); + } + } + + /** + * 指定自动完成 + * @access public + * @param array $auto 自动完成设置 + * @return Model + */ + public function auto($auto){ + $this->options['auto'] = $auto; + return $this; + } + + /** + * 指定自动验证 + * @access public + * @param array $validate 自动验证设置 + * @return Model + */ + public function validate($auto){ + $this->options['validate'] = $validate; + return $this; + } +} \ No newline at end of file diff --git a/Traits/Think/Model/Extend.php b/Traits/Think/Model/Extend.php new file mode 100644 index 00000000..441c4d82 --- /dev/null +++ b/Traits/Think/Model/Extend.php @@ -0,0 +1,261 @@ + +// +---------------------------------------------------------------------- + +namespace Traits\Think\Model; + +trait Extend { + + protected $partition = []; + + /** + * 利用__call方法实现一些特殊的Model方法 + * @access public + * @param string $method 方法名称 + * @param array $args 调用参数 + * @return mixed + */ + public function __call($method,$args) { + if(in_array(strtolower($method),array('count','sum','min','max','avg'),true)){ + // 统计查询的实现 + $field = isset($args[0])?$args[0]:'*'; + return $this->getField(strtoupper($method).'('.$field.') AS tp_'.$method); + }elseif(strtolower(substr($method,0,5))=='getby') { + // 根据某个字段获取记录 + $field = parse_name(substr($method,5)); + $where[$field] = $args[0]; + return $this->where($where)->find(); + }elseif(strtolower(substr($method,0,10))=='getfieldby') { + // 根据某个字段获取记录的某个值 + $name = parse_name(substr($method,10)); + $where[$name] =$args[0]; + return $this->where($where)->getField($args[1]); + }elseif(isset($this->scope[$method])){// 命名范围的单独调用支持 + return $this->scope($method,$args[0]); + }else{ + E(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); + return; + } + } + + /** + * 设置记录的某个字段值 + * 支持使用数据库字段和方法 + * @access public + * @param string|array $field 字段名 + * @param string $value 字段值 + * @return boolean + */ + public function setField($field,$value='') { + if(is_array($field)) { + $data = $field; + }else{ + $data[$field] = $value; + } + return $this->save($data); + } + + /** + * 字段值增长 + * @access public + * @param string $field 字段名 + * @param integer $step 增长值 + * @return boolean + */ + public function setInc($field,$step=1) { + return $this->setField($field,['exp',$field.'+'.$step]); + } + + /** + * 字段值减少 + * @access public + * @param string $field 字段名 + * @param integer $step 减少值 + * @return boolean + */ + public function setDec($field,$step=1) { + return $this->setField($field,['exp',$field.'-'.$step]); + } + + + /** + * 获取一条记录的某个字段值 + * @access public + * @param string $field 字段名 + * @param string $spea 字段数据间隔符号 NULL返回数组 + * @return mixed + */ + public function getField($field,$sepa=null) { + $options['field'] = $field; + $options = $this->_parseOptions($options); + $field = trim($field); + if(strpos($field,',')) { // 多字段 + if(!isset($options['limit'])){ + $options['limit'] = is_numeric($sepa)?$sepa:''; + } + $resultSet = $this->db->select($options); + if(!empty($resultSet)) { + $_field = explode(',', $field); + $field = array_keys($resultSet[0]); + $key = array_shift($field); + $key2 = array_shift($field); + $cols = []; + $count = count($_field); + foreach ($resultSet as $result){ + $name = $result[$key]; + if(2==$count) { + $cols[$name] = $result[$key2]; + }else{ + $cols[$name] = is_string($sepa)?implode($sepa,$result):$result; + } + } + return $cols; + } + }else{ // 查找一条记录 + // 返回数据个数 + if(true !== $sepa) {// 当sepa指定为true的时候 返回所有数据 + $options['limit'] = is_numeric($sepa)?$sepa:1; + } + $result = $this->db->select($options); + if(!empty($result)) { + if(true !== $sepa && 1==$options['limit']) return reset($result[0]); + foreach ($result as $val){ + $array[] = $val[$field]; + } + return $array; + } + } + return null; + } + + /** + * 字段值延迟增长 + * @access public + * @param string $field 字段名 + * @param integer $step 增长值 + * @param integer $lazyTime 延时时间(s) + * @return boolean + */ + public function setLazyInc($field,$step=1,$lazyTime=0) { + $condition = $this->options['where']; + if(empty($condition)) { // 没有条件不做任何更新 + return false; + } + if($lazyTime>0) {// 延迟写入 + $guid = md5($this->name.'_'.$field.'_'.serialize($condition)); + $step = $this->lazyWrite($guid,$step,$lazyTime); + if(false === $step ) return true; // 等待下次写入 + } + return $this->setField($field,array('exp',$field.'+'.$step)); + } + + /** + * 字段值延迟减少 + * @access public + * @param string $field 字段名 + * @param integer $step 减少值 + * @param integer $lazyTime 延时时间(s) + * @return boolean + */ + public function setLazyDec($field,$step=1,$lazyTime=0) { + $condition = $this->options['where']; + if(empty($condition)) { // 没有条件不做任何更新 + return false; + } + if($lazyTime>0) {// 延迟写入 + $guid = md5($this->name.'_'.$field.'_'.serialize($condition)); + $step = $this->lazyWrite($guid,$step,$lazyTime); + if(false === $step ) return true; // 等待下次写入 + } + return $this->setField($field,array('exp',$field.'-'.$step)); + } + + /** + * 延时更新检查 返回false表示需要延时 + * 否则返回实际写入的数值 + * @access public + * @param string $guid 写入标识 + * @param integer $step 写入步进值 + * @param integer $lazyTime 延时时间(s) + * @return false|integer + */ + protected function lazyWrite($guid,$step,$lazyTime) { + if(false !== ($value = F($guid))) { // 存在缓存写入数据 + if(time()>S($guid.'_time')+$lazyTime) { + // 延时更新时间到了,删除缓存数据 并实际写入数据库 + S($guid,NULL); + S($guid.'_time',NULL); + return $value+$step; + }else{ + // 追加数据到缓存 + S($guid,$value+$step); + return false; + } + }else{ // 没有缓存数据 + S($guid,$step); + // 计时开始 + S($guid.'_time',time()); + return false; + } + } + + /** + * 得到分表的的数据表名 + * @access public + * @param array $data 操作的数据 + * @return string + */ + public function getPartitionTableName($data=[]) { + // 对数据表进行分区 + if(isset($data[$this->partition['field']])) { + $field = $data[$this->partition['field']]; + switch($this->partition['type']) { + case 'id': + // 按照id范围分表 + $step = $this->partition['expr']; + $seq = floor($field / $step)+1; + break; + case 'year': + // 按照年份分表 + if(!is_numeric($field)) { + $field = strtotime($field); + } + $seq = date('Y',$field)-$this->partition['expr']+1; + break; + case 'mod': + // 按照id的模数分表 + $seq = ($field % $this->partition['num'])+1; + break; + case 'md5': + // 按照md5的序列分表 + $seq = (ord(substr(md5($field),0,1)) % $this->partition['num'])+1; + break; + default : + if(function_exists($this->partition['type'])) { + // 支持指定函数哈希 + $fun = $this->partition['type']; + $seq = (ord(substr($fun($field),0,1)) % $this->partition['num'])+1; + }else{ + // 按照字段的首字母的值分表 + $seq = (ord($field{0}) % $this->partition['num'])+1; + } + } + return $this->getTableName().'_'.$seq; + }else{ + // 当设置的分表字段不在查询条件或者数据中 + // 进行联合查询,必须设定 partition['num'] + $tableName = []; + for($i=0;$i<$this->partition['num'];$i++) + $tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.($i+1); + $tableName = '( '.implode(" UNION ",$tableName).') AS '.$this->name; + return $tableName; + } + } +} \ No newline at end of file diff --git a/Traits/Think/Model/Query.php b/Traits/Think/Model/Query.php new file mode 100644 index 00000000..d3e776e7 --- /dev/null +++ b/Traits/Think/Model/Query.php @@ -0,0 +1,92 @@ + +// +---------------------------------------------------------------------- + +namespace Traits\Think\Model; + +trait Query { + + /** + * 启动事务 + * @access public + * @return void + */ + public function startTrans() { + $this->commit(); + $this->db->startTrans(); + return ; + } + + /** + * 提交事务 + * @access public + * @return boolean + */ + public function commit() { + return $this->db->commit(); + } + + /** + * 事务回滚 + * @access public + * @return boolean + */ + public function rollback() { + return $this->db->rollback(); + } + + /** + * 解析SQL语句 + * @access public + * @param string $sql SQL指令 + * @param boolean $parse 是否需要解析SQL + * @return string + */ + public function parseSql($sql,$parse) { + // 分析表达式 + if(true === $parse) { + $options = $this->_parseOptions(); + $sql = $this->db->parseSql($sql,$options); + }elseif(is_array($parse)){ // SQL预处理 + $sql = vsprintf($sql,$parse); + }else{ + $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); + } + return $sql; + } + + /** + * 批处理执行SQL语句 + * 批处理的指令都认为是execute操作 + * @access public + * @param array $sql SQL批处理指令 + * @return boolean + */ + public function patchQuery($sql=[]) { + if(!is_array($sql)) return false; + // 自动启动事务支持 + $this->startTrans(); + try{ + foreach ($sql as $_sql){ + $result = $this->execute($_sql); + if(false === $result) { + // 发生错误自动回滚事务 + $this->rollback(); + return false; + } + } + // 提交事务 + $this->commit(); + } catch (\Think\Exception $e) { + $this->rollback(); + } + return true; + } +} \ No newline at end of file diff --git a/Traits/Think/Model/Relation.php b/Traits/Think/Model/Relation.php new file mode 100644 index 00000000..2cc297ae --- /dev/null +++ b/Traits/Think/Model/Relation.php @@ -0,0 +1,346 @@ + +// +---------------------------------------------------------------------- + +namespace Traits\Think\Model; + +define('HAS_ONE',1); +define('BELONGS_TO',2); +define('HAS_MANY',3); +define('MANY_TO_MANY',4); + +trait Relation { + // 关联定义 + protected $link = array(); + + /** + * 得到关联的数据表名 + * @access public + * @return string + */ + public function getRelationTableName($relation) { + $relationTable = !empty($this->tablePrefix) ? $this->tablePrefix : ''; + $relationTable .= $this->tableName?$this->tableName:$this->name; + $relationTable .= '_'.$relation->getModelName(); + return strtolower($relationTable); + } + + // 查询成功后的回调方法 + protected function _after_find(&$result,$options) { + // 获取关联数据 并附加到结果中 + if(!empty($options['link'])) + $this->getRelation($result,$options['link']); + } + + // 查询数据集成功后的回调方法 + protected function _after_select(&$result,$options) { + // 获取关联数据 并附加到结果中 + if(!empty($options['link'])) + $this->getRelations($result,$options['link']); + } + + // 写入成功后的回调方法 + protected function _after_insert($data,$options) { + // 关联写入 + if(!empty($options['link'])) + $this->opRelation('ADD',$data,$options['link']); + } + + // 更新成功后的回调方法 + protected function _after_update($data,$options) { + // 关联更新 + if(!empty($options['link'])) + $this->opRelation('SAVE',$data,$options['link']); + } + + // 删除成功后的回调方法 + protected function _after_delete($data,$options) { + // 关联删除 + if(!empty($options['link'])) + $this->opRelation('DEL',$data,$options['link']); + } + + /** + * 对保存到数据库的数据进行处理 + * @access protected + * @param mixed $data 要操作的数据 + * @return boolean + */ + protected function _write_data($data) { + $this->_before_write($data); + return $data; + } + + /** + * 获取返回数据集的关联记录 + * @access protected + * @param array $resultSet 返回数据 + * @param string|array $name 关联名称 + * @return array + */ + protected function getRelations(&$resultSet,$name='') { + // 获取记录集的主键列表 + foreach($resultSet as $key=>$val) { + $val = $this->getRelation($val,$name); + $resultSet[$key] = $val; + } + return $resultSet; + } + + /** + * 获取返回数据的关联记录 + * @access protected + * @param mixed $result 返回数据 + * @param string|array $name 关联名称 + * @param boolean $return 是否返回关联数据本身 + * @return array + */ + protected function getRelation(&$result,$name='',$return=false) { + if(!empty($this->link)) { + foreach($this->link as $key=>$val) { + $mappingName = !empty($val['mapping_name'])?$val['mapping_name']:$key; // 映射名称 + if(empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName,$name))) { + $mappingType = !empty($val['mapping_type'])?$val['mapping_type']:$val; // 关联类型 + $mappingClass = !empty($val['class_name'])?$val['class_name']:$key; // 关联类名 + $mappingFields = !empty($val['mapping_fields'])?$val['mapping_fields']:'*'; // 映射字段 + $mappingCondition = !empty($val['condition'])?$val['condition']:'1=1'; // 关联条件 + $mappingKey =!empty($val['mapping_key'])? $val['mapping_key'] : $this->getPk(); // 关联键名 + if(strtoupper($mappingClass)==strtoupper($this->name)) { + // 自引用关联 获取父键名 + $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; + }else{ + $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($this->name).'_id'; // 关联外键 + } + // 获取关联模型对象 + $model = D($mappingClass); + switch($mappingType) { + case HAS_ONE: + $pk = $result[$mappingKey]; + $mappingCondition .= " AND {$mappingFk}='{$pk}'"; + $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); + break; + case BELONGS_TO: + if(strtoupper($mappingClass)==strtoupper($this->name)) { + // 自引用关联 获取父键名 + $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; + }else{ + $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($model->getModelName()).'_id'; // 关联外键 + } + $fk = $result[$mappingFk]; + $mappingCondition .= " AND {$model->getPk()}='{$fk}'"; + $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); + break; + case HAS_MANY: + $pk = $result[$mappingKey]; + $mappingCondition .= " AND {$mappingFk}='{$pk}'"; + $mappingOrder = !empty($val['mapping_order'])?$val['mapping_order']:''; + $mappingLimit = !empty($val['mapping_limit'])?$val['mapping_limit']:''; + // 延时获取关联记录 + $relationData = $model->where($mappingCondition)->field($mappingFields)->order($mappingOrder)->limit($mappingLimit)->select(); + break; + case MANY_TO_MANY: + $pk = $result[$mappingKey]; + $mappingCondition = " {$mappingFk}='{$pk}'"; + $mappingOrder = $val['mapping_order']; + $mappingLimit = $val['mapping_limit']; + $mappingRelationFk = $val['relation_foreign_key']?$val['relation_foreign_key']:$model->getModelName().'_id'; + $mappingRelationTable = $val['relation_table']?$val['relation_table']:$this->getRelationTableName($model); + $sql = "SELECT b.{$mappingFields} FROM {$mappingRelationTable} AS a, ".$model->getTableName()." AS b WHERE a.{$mappingRelationFk} = b.{$model->getPk()} AND a.{$mappingCondition}"; + if(!empty($val['condition'])) { + $sql .= ' AND '.$val['condition']; + } + if(!empty($mappingOrder)) { + $sql .= ' ORDER BY '.$mappingOrder; + } + if(!empty($mappingLimit)) { + $sql .= ' LIMIT '.$mappingLimit; + } + $relationData = $this->query($sql); + break; + } + if(!$return){ + if(isset($val['as_fields']) && in_array($mappingType,array(HAS_ONE,BELONGS_TO)) ) { + // 支持直接把关联的字段值映射成数据对象中的某个字段 + // 仅仅支持HAS_ONE BELONGS_TO + $fields = explode(',',$val['as_fields']); + foreach ($fields as $field){ + if(strpos($field,':')) { + list($relationName,$nick) = explode(':',$field); + $result[$nick] = $relationData[$relationName]; + }else{ + $result[$field] = $relationData[$field]; + } + } + }else{ + $result[$mappingName] = $relationData; + } + unset($relationData); + }else{ + return $relationData; + } + } + } + } + return $result; + } + + /** + * 操作关联数据 + * @access protected + * @param string $opType 操作方式 ADD SAVE DEL + * @param mixed $data 数据对象 + * @param string $name 关联名称 + * @return mixed + */ + protected function opRelation($opType,$data='',$name='') { + $result = false; + if(empty($data) && !empty($this->data)){ + $data = $this->data; + }elseif(!is_array($data)){ + // 数据无效返回 + return false; + } + if(!empty($this->link)) { + // 遍历关联定义 + foreach($this->link as $key=>$val) { + // 操作制定关联类型 + $mappingName = $val['mapping_name']?$val['mapping_name']:$key; // 映射名称 + if(empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName,$name)) ) { + // 操作制定的关联 + $mappingType = !empty($val['mapping_type'])?$val['mapping_type']:$val; // 关联类型 + $mappingClass = !empty($val['class_name'])?$val['class_name']:$key; // 关联类名 + $mappingKey =!empty($val['mapping_key'])? $val['mapping_key'] : $this->getPk(); // 关联键名 + // 当前数据对象主键值 + $pk = $data[$mappingKey]; + if(strtoupper($mappingClass)==strtoupper($this->name)) { + // 自引用关联 获取父键名 + $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; + }else{ + $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($this->name).'_id'; // 关联外键 + } + if(!empty($val['condition'])) { + $mappingCondition = $val['condition']; + }else{ + $mappingCondition = array(); + $mappingCondition[$mappingFk] = $pk; + } + // 获取关联model对象 + $model = D($mappingClass); + $mappingData = isset($data[$mappingName])?$data[$mappingName]:false; + if(!empty($mappingData) || $opType == 'DEL') { + switch($mappingType) { + case HAS_ONE: + switch (strtoupper($opType)){ + case 'ADD': // 增加关联数据 + $mappingData[$mappingFk] = $pk; + $result = $model->add($mappingData); + break; + case 'SAVE': // 更新关联数据 + $result = $model->where($mappingCondition)->save($mappingData); + break; + case 'DEL': // 根据外键删除关联数据 + $result = $model->where($mappingCondition)->delete(); + break; + } + break; + case BELONGS_TO: + break; + case HAS_MANY: + switch (strtoupper($opType)){ + case 'ADD' : // 增加关联数据 + $model->startTrans(); + foreach ($mappingData as $val){ + $val[$mappingFk] = $pk; + $result = $model->add($val); + } + $model->commit(); + break; + case 'SAVE' : // 更新关联数据 + $model->startTrans(); + $pk = $model->getPk(); + foreach ($mappingData as $vo){ + if(isset($vo[$pk])) {// 更新数据 + $mappingCondition = "$pk ={$vo[$pk]}"; + $result = $model->where($mappingCondition)->save($vo); + }else{ // 新增数据 + $vo[$mappingFk] = $data[$mappingKey]; + $result = $model->add($vo); + } + } + $model->commit(); + break; + case 'DEL' : // 删除关联数据 + $result = $model->where($mappingCondition)->delete(); + break; + } + break; + case MANY_TO_MANY: + $mappingRelationFk = $val['relation_foreign_key']?$val['relation_foreign_key']:$model->getModelName().'_id';// 关联 + $mappingRelationTable = $val['relation_table']?$val['relation_table']:$this->getRelationTableName($model); + if(is_array($mappingData)) { + $ids = array(); + foreach ($mappingData as $vo) + $ids[] = $vo[$mappingKey]; + $relationId = implode(',',$ids); + } + switch (strtoupper($opType)){ + case 'ADD': // 增加关联数据 + case 'SAVE': // 更新关联数据 + if(isset($relationId)) { + $this->startTrans(); + // 删除关联表数据 + $this->table($mappingRelationTable)->where($mappingCondition)->delete(); + // 插入关联表数据 + $sql = 'INSERT INTO '.$mappingRelationTable.' ('.$mappingFk.','.$mappingRelationFk.') SELECT a.'.$this->getPk().',b.'.$model->getPk().' FROM '.$this->getTableName().' AS a ,'.$model->getTableName()." AS b where a.".$this->getPk().' ='. $pk.' AND b.'.$model->getPk().' IN ('.$relationId.") "; + $result = $model->execute($sql); + if(false !== $result) + // 提交事务 + $this->commit(); + else + // 事务回滚 + $this->rollback(); + } + break; + case 'DEL': // 根据外键删除中间表关联数据 + $result = $this->table($mappingRelationTable)->where($mappingCondition)->delete(); + break; + } + break; + } + } + } + } + } + return $result; + } + + /** + * 进行关联查询 + * @access public + * @param mixed $name 关联名称 + * @return Model + */ + public function relation($name) { + $this->options['link'] = $name; + return $this; + } + + /** + * 关联数据获取 仅用于查询后 + * @access public + * @param string $name 关联名称 + * @return array + */ + public function relationGet($name) { + if(empty($this->data)) + return false; + return $this->getRelation($this->data,$name,true); + } +} \ No newline at end of file diff --git a/Traits/Think/Model/View.php b/Traits/Think/Model/View.php new file mode 100644 index 00000000..1f5589a2 --- /dev/null +++ b/Traits/Think/Model/View.php @@ -0,0 +1,239 @@ + +// +---------------------------------------------------------------------- + +namespace Traits\Think\Model; + +trait View { + + protected $viewFields = []; + + /** + * 自动检测数据表信息 + * @access protected + * @return void + */ + protected function _checkTableInfo() {} + + /** + * 得到完整的数据表名 + * @access public + * @return string + */ + public function getTableName() { + if(empty($this->trueTableName)) { + $tableName = ''; + foreach ($this->viewFields as $key=>$view){ + // 获取数据表名称 + if(isset($view['_table'])) { // 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图 + $tableName .= $view['_table']; + }else{ + $class = $key.'Model'; + $Model = class_exists($class)?new $class():M($key); + $tableName .= $Model->getTableName(); + } + // 表别名定义 + $tableName .= !empty($view['_as'])?' '.$view['_as']:' '.$key; + // 支持ON 条件定义 + $tableName .= !empty($view['_on'])?' ON '.$view['_on']:''; + // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效 + $type = !empty($view['_type'])?$view['_type']:''; + $tableName .= ' '.strtoupper($type).' JOIN '; + $len = strlen($type.'_JOIN '); + } + $tableName = substr($tableName,0,-$len); + $this->trueTableName = $tableName; + } + return $this->trueTableName; + } + + /** + * 表达式过滤方法 + * @access protected + * @param string $options 表达式 + * @return void + */ + protected function _options_filter(&$options) { + if(isset($options['field'])) + $options['field'] = $this->checkFields($options['field']); + else + $options['field'] = $this->checkFields(); + if(isset($options['group'])) + $options['group'] = $this->checkGroup($options['group']); + if(isset($options['where'])) + $options['where'] = $this->checkCondition($options['where']); + if(isset($options['order'])) + $options['order'] = $this->checkOrder($options['order']); + } + + /** + * 检查是否定义了所有字段 + * @access protected + * @param string $name 模型名称 + * @param array $fields 字段数组 + * @return array + */ + private function _checkFields($name,$fields) { + if(false !== $pos = array_search('*',$fields)) {// 定义所有字段 + $fields = array_merge($fields,M($name)->getDbFields()); + unset($fields[$pos]); + } + return $fields; + } + + /** + * 检查条件中的视图字段 + * @access protected + * @param mixed $data 条件表达式 + * @return array + */ + protected function checkCondition($where) { + if(is_array($where)) { + $view = []; + // 检查视图字段 + foreach ($this->viewFields as $key=>$val){ + $k = isset($val['_as'])?$val['_as']:$key; + $val = $this->_checkFields($key,$val); + foreach ($where as $name=>$value){ + if(false !== $field = array_search($name,$val,true)) { + // 存在视图字段 + $_key = is_numeric($field)? $k.'.'.$name : $k.'.'.$field; + $view[$_key] = $value; + unset($where[$name]); + } + } + } + $where = array_merge($where,$view); + } + return $where; + } + + /** + * 检查Order表达式中的视图字段 + * @access protected + * @param string $order 字段 + * @return string + */ + protected function checkOrder($order='') { + if(is_string($order) && !empty($order)) { + $orders = explode(',',$order); + $_order = []; + foreach ($orders as $order){ + $array = explode(' ',$order); + $field = $array[0]; + $sort = isset($array[1])?$array[1]:'ASC'; + // 解析成视图字段 + foreach ($this->viewFields as $name=>$val){ + $k = isset($val['_as'])?$val['_as']:$name; + $val = $this->_checkFields($name,$val); + if(false !== $_field = array_search($field,$val,true)) { + // 存在视图字段 + $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field; + break; + } + } + $_order[] = $field.' '.$sort; + } + $order = implode(',',$_order); + } + return $order; + } + + /** + * 检查Group表达式中的视图字段 + * @access protected + * @param string $group 字段 + * @return string + */ + protected function checkGroup($group='') { + if(!empty($group)) { + $groups = explode(',',$group); + $_group = []; + foreach ($groups as $field){ + // 解析成视图字段 + foreach ($this->viewFields as $name=>$val){ + $k = isset($val['_as'])?$val['_as']:$name; + $val = $this->_checkFields($name,$val); + if(false !== $_field = array_search($field,$val,true)) { + // 存在视图字段 + $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field; + break; + } + } + $_group[] = $field; + } + $group = implode(',',$_group); + } + return $group; + } + + /** + * 检查fields表达式中的视图字段 + * @access protected + * @param string $fields 字段 + * @return string + */ + protected function checkFields($fields='') { + if(empty($fields) || '*'==$fields ) { + // 获取全部视图字段 + $fields = []; + foreach ($this->viewFields as $name=>$val){ + $k = isset($val['_as'])?$val['_as']:$name; + $val = $this->_checkFields($name,$val); + foreach ($val as $key=>$field){ + if(is_numeric($key)) { + $fields[] = $k.'.'.$field.' AS '.$field; + }elseif('_' != substr($key,0,1)) { + // 以_开头的为特殊定义 + if( false !== strpos($key,'*') || false !== strpos($key,'(') || false !== strpos($key,'.')) { + //如果包含* 或者 使用了sql方法 则不再添加前面的表名 + $fields[] = $key.' AS '.$field; + }else{ + $fields[] = $k.'.'.$key.' AS '.$field; + } + } + } + } + $fields = implode(',',$fields); + }else{ + if(!is_array($fields)) + $fields = explode(',',$fields); + // 解析成视图字段 + $array = []; + foreach ($fields as $key=>$field){ + if(strpos($field,'(') || strpos(strtolower($field),' as ')){ + // 使用了函数或者别名 + $array[] = $field; + unset($fields[$key]); + } + } + foreach ($this->viewFields as $name=>$val){ + $k = isset($val['_as'])?$val['_as']:$name; + $val = $this->_checkFields($name,$val); + foreach ($fields as $key=>$field){ + if(false !== $_field = array_search($field,$val,true)) { + // 存在视图字段 + if(is_numeric($_field)) { + $array[] = $k.'.'.$field.' AS '.$field; + }elseif('_' != substr($_field,0,1)){ + if( false !== strpos($_field,'*') || false !== strpos($_field,'(') || false !== strpos($_field,'.')) + //如果包含* 或者 使用了sql方法 则不再添加前面的表名 + $array[] = $_field.' AS '.$field; + else + $array[] = $k.'.'.$_field.' AS '.$field; + } + } + } + } + $fields = implode(',',$array); + } + return $fields; + } +} \ No newline at end of file diff --git a/Vendor/phpRPC/bigint.php b/Vendor/phpRPC/bigint.php new file mode 100644 index 00000000..9c8dc703 --- /dev/null +++ b/Vendor/phpRPC/bigint.php @@ -0,0 +1,369 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* Big integer expansion library. + * + * Copyright: Ma Bingyao + * mgccl + * Version: 3.0.1 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + */ + +if (extension_loaded('gmp')) { + function bigint_dec2num($dec) { + return gmp_init($dec); + } + function bigint_num2dec($num) { + return gmp_strval($num); + } + function bigint_str2num($str) { + return gmp_init("0x".bin2hex($str)); + } + function bigint_num2str($num) { + $str = gmp_strval($num, 16); + $len = strlen($str); + if ($len % 2 == 1) { + $str = '0'.$str; + } + return pack("H*", $str); + } + function bigint_random($n, $s) { + $result = gmp_init(0); + for ($i = 0; $i < $n; $i++) { + if (mt_rand(0, 1)) { + gmp_setbit($result, $i); + } + } + if ($s) { + gmp_setbit($result, $n - 1); + } + return $result; + } + function bigint_powmod($x, $y, $m) { + return gmp_powm($x, $y, $m); + } +} +else if (extension_loaded('big_int')) { + function bigint_dec2num($dec) { + return bi_from_str($dec); + } + function bigint_num2dec($num) { + return bi_to_str($num); + } + function bigint_str2num($str) { + return bi_from_str(bin2hex($str), 16); + } + function bigint_num2str($num) { + $str = bi_to_str($num, 16); + $len = strlen($str); + if ($len % 2 == 1) { + $str = '0'.$str; + } + return pack("H*", $str); + } + function bigint_random($n, $s) { + $result = bi_rand($n); + if ($s) { + $result = bi_set_bit($result, $n - 1); + } + return $result; + } + function bigint_powmod($x, $y, $m) { + return bi_powmod($x, $y, $m); + } +} +else if (extension_loaded('bcmath')) { + function bigint_dec2num($dec) { + return $dec; + } + function bigint_num2dec($num) { + return $num; + } + function bigint_str2num($str) { + bcscale(0); + $len = strlen($str); + $result = '0'; + $m = '1'; + for ($i = 0; $i < $len; $i++) { + $result = bcadd(bcmul($m, ord($str{$len - $i - 1})), $result); + $m = bcmul($m, '256'); + } + return $result; + } + function bigint_num2str($num) { + bcscale(0); + $str = ""; + while (bccomp($num, '0') == 1) { + $str = chr(bcmod($num, '256')) . $str; + $num = bcdiv($num, '256'); + } + return $str; + } + // author of bcmath bigint_random: mgccl + function bigint_pow($b, $e) { + if ($b == 2) { + $a[96] = '79228162514264337593543950336'; + $a[128] = '340282366920938463463374607431768211456'; + $a[160] = '1461501637330902918203684832716283019655932542976'; + $a[192] = '6277101735386680763835789423207666416102355444464034512896'; + $a[256] = '115792089237316195423570985008687907853269984665640564039457584007913129639936'; + $a[512] = '13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096'; + $a[768] = '1552518092300708935148979488462502555256886017116696611139052038026050952686376886330878408828646477950487730697131073206171580044114814391444287275041181139204454976020849905550265285631598444825262999193716468750892846853816057856'; + $a[1024] = '179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216'; + $a[1356] = '1572802244866018108182967249994981337399178505432223228293716677435703277129801955281491139254988030713172834803458459525011536776047399098682525970017006610187370020027540826048617586909475175880278263391147764612823746132583281588112028234096933800670620569966257212339315820309710495898777306979706509398705741430192541287726011814541176060679505247297118998085067003005943214893171428950699778511718055936'; + $a[2048] = '32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656'; + $a[3072] = '5809605995369958062859502533304574370686975176362895236661486152287203730997110225737336044533118407251326157754980517443990529594540047121662885672187032401032111639706440498844049850989051627200244765807041812394729680540024104827976584369381522292361208779044769892743225751738076979568811309579125511333093243519553784816306381580161860200247492568448150242515304449577187604136428738580990172551573934146255830366405915000869643732053218566832545291107903722831634138599586406690325959725187447169059540805012310209639011750748760017095360734234945757416272994856013308616958529958304677637019181594088528345061285863898271763457294883546638879554311615446446330199254382340016292057090751175533888161918987295591531536698701292267685465517437915790823154844634780260102891718032495396075041899485513811126977307478969074857043710716150121315922024556759241239013152919710956468406379442914941614357107914462567329693696'; + $a[4096] = '1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336'; + $a[8192] = '1090748135619415929462984244733782862448264161996232692431832786189721331849119295216264234525201987223957291796157025273109870820177184063610979765077554799078906298842192989538609825228048205159696851613591638196771886542609324560121290553901886301017900252535799917200010079600026535836800905297805880952350501630195475653911005312364560014847426035293551245843928918752768696279344088055617515694349945406677825140814900616105920256438504578013326493565836047242407382442812245131517757519164899226365743722432277368075027627883045206501792761700945699168497257879683851737049996900961120515655050115561271491492515342105748966629547032786321505730828430221664970324396138635251626409516168005427623435996308921691446181187406395310665404885739434832877428167407495370993511868756359970390117021823616749458620969857006263612082706715408157066575137281027022310927564910276759160520878304632411049364568754920967322982459184763427383790272448438018526977764941072715611580434690827459339991961414242741410599117426060556483763756314527611362658628383368621157993638020878537675545336789915694234433955666315070087213535470255670312004130725495834508357439653828936077080978550578912967907352780054935621561090795845172954115972927479877527738560008204118558930004777748727761853813510493840581861598652211605960308356405941821189714037868726219481498727603653616298856174822413033485438785324024751419417183012281078209729303537372804574372095228703622776363945290869806258422355148507571039619387449629866808188769662815778153079393179093143648340761738581819563002994422790754955061288818308430079648693232179158765918035565216157115402992120276155607873107937477466841528362987708699450152031231862594203085693838944657061346236704234026821102958954951197087076546186622796294536451620756509351018906023773821539532776208676978589731966330308893304665169436185078350641568336944530051437491311298834367265238595404904273455928723949525227184617404367854754610474377019768025576605881038077270707717942221977090385438585844095492116099852538903974655703943973086090930596963360767529964938414598185705963754561497355827813623833288906309004288017321424808663962671333528009232758350873059614118723781422101460198615747386855096896089189180441339558524822867541113212638793675567650340362970031930023397828465318547238244232028015189689660418822976000815437610652254270163595650875433851147123214227266605403581781469090806576468950587661997186505665475715792896'; + return (isset($a[$e]) ? $a[$e] : bcpow(2, $e)); + } + return bcpow($b, $e); + } + function bigint_random($n, $s) { + bcscale(0); + $t = bigint_pow(2, $n); + if ($s == 1) { + $m = bcdiv($t, 2); + $t = bcsub($m, 1); + } + else { + $m = 0; + $t = bcsub($t, 1); + } + $l = strlen($t); + $n = (int) ($l / 9) + 1; + $r = ''; + while($n) { + $r .= substr('000000000' . mt_rand(0, 999999999), -9); + --$n; + } + $r = substr($r, 0, $l); + while (bccomp($r, $t) == 1) $r = substr($r, 1, $l) . mt_rand(0, 9); + return bcadd($r, $m); + } + if (!function_exists('bcpowmod')) { + function bcpowmod($x, $y, $modulus, $scale = 0) { + $t = '1'; + while (bccomp($y, '0')) { + if (bccomp(bcmod($y, '2'), '0')) { + $t = bcmod(bcmul($t, $x), $modulus); + $y = bcsub($y, '1'); + } + + $x = bcmod(bcmul($x, $x), $modulus); + $y = bcdiv($y, '2'); + } + return $t; + } + } + function bigint_powmod($x, $y, $m) { + return bcpowmod($x, $y, $m); + } +} +else { + function bigint_mul($a, $b) { + $n = count($a); + $m = count($b); + $nm = $n + $m; + $c = array_fill(0, $nm, 0); + for ($i = 0; $i < $n; $i++) { + for ($j = 0; $j < $m; $j++) { + $c[$i + $j] += $a[$i] * $b[$j]; + $c[$i + $j + 1] += ($c[$i + $j] >> 15) & 0x7fff; + $c[$i + $j] &= 0x7fff; + } + } + return $c; + } + function bigint_div($a, $b, $is_mod = 0) { + $n = count($a); + $m = count($b); + $c = array(); + $d = floor(0x8000 / ($b[$m - 1] + 1)); + $a = bigint_mul($a, array($d)); + $b = bigint_mul($b, array($d)); + for ($j = $n - $m; $j >= 0; $j--) { + $tmp = $a[$j + $m] * 0x8000 + $a[$j + $m - 1]; + $rr = $tmp % $b[$m - 1]; + $qq = round(($tmp - $rr) / $b[$m - 1]); + if (($qq == 0x8000) || (($m > 1) && ($qq * $b[$m - 2] > 0x8000 * $rr + $a[$j + $m - 2]))) { + $qq--; + $rr += $b[$m - 1]; + if (($rr < 0x8000) && ($qq * $b[$m - 2] > 0x8000 * $rr + $a[$j + $m - 2])) $qq--; + } + for ($i = 0; $i < $m; $i++) { + $tmp = $i + $j; + $a[$tmp] -= $b[$i] * $qq; + $a[$tmp + 1] += floor($a[$tmp] / 0x8000); + $a[$tmp] &= 0x7fff; + } + $c[$j] = $qq; + if ($a[$tmp + 1] < 0) { + $c[$j]--; + for ($i = 0; $i < $m; $i++) { + $tmp = $i + $j; + $a[$tmp] += $b[$i]; + if ($a[$tmp] > 0x7fff) { + $a[$tmp + 1]++; + $a[$tmp] &= 0x7fff; + } + } + } + } + if (!$is_mod) return $c; + $b = array(); + for ($i = 0; $i < $m; $i++) $b[$i] = $a[$i]; + return bigint_div($b, array($d)); + } + function bigint_zerofill($str, $num) { + return str_pad($str, $num, '0', STR_PAD_LEFT); + } + function bigint_dec2num($dec) { + $n = strlen($dec); + $a = array(0); + $n += 4 - ($n % 4); + $dec = bigint_zerofill($dec, $n); + $n >>= 2; + for ($i = 0; $i < $n; $i++) { + $a = bigint_mul($a, array(10000)); + $a[0] += (int)substr($dec, 4 * $i, 4); + $m = count($a); + $j = 0; + $a[$m] = 0; + while ($j < $m && $a[$j] > 0x7fff) { + $a[$j++] &= 0x7fff; + $a[$j]++; + } + while ((count($a) > 1) && (!$a[count($a) - 1])) array_pop($a); + } + return $a; + } + function bigint_num2dec($num) { + $n = count($num) << 1; + $b = array(); + for ($i = 0; $i < $n; $i++) { + $tmp = bigint_div($num, array(10000), 1); + $b[$i] = bigint_zerofill($tmp[0], 4); + $num = bigint_div($num, array(10000)); + } + while ((count($b) > 1) && !(int)$b[count($b) - 1]) array_pop($b); + $n = count($b) - 1; + $b[$n] = (int)$b[$n]; + $b = join('', array_reverse($b)); + return $b; + } + function bigint_str2num($str) { + $n = strlen($str); + $n += 15 - ($n % 15); + $str = str_pad($str, $n, chr(0), STR_PAD_LEFT); + $j = 0; + $result = array(); + for ($i = 0; $i < $n; $i++) { + $result[$j++] = (ord($str{$i++}) << 7) | (ord($str{$i}) >> 1); + $result[$j++] = ((ord($str{$i++}) & 0x01) << 14) | (ord($str{$i++}) << 6) | (ord($str{$i}) >> 2); + $result[$j++] = ((ord($str{$i++}) & 0x03) << 13) | (ord($str{$i++}) << 5) | (ord($str{$i}) >> 3); + $result[$j++] = ((ord($str{$i++}) & 0x07) << 12) | (ord($str{$i++}) << 4) | (ord($str{$i}) >> 4); + $result[$j++] = ((ord($str{$i++}) & 0x0f) << 11) | (ord($str{$i++}) << 3) | (ord($str{$i}) >> 5); + $result[$j++] = ((ord($str{$i++}) & 0x1f) << 10) | (ord($str{$i++}) << 2) | (ord($str{$i}) >> 6); + $result[$j++] = ((ord($str{$i++}) & 0x3f) << 9) | (ord($str{$i++}) << 1) | (ord($str{$i}) >> 7); + $result[$j++] = ((ord($str{$i++}) & 0x7f) << 8) | ord($str{$i}); + } + $result = array_reverse($result); + $i = count($result) - 1; + while ($result[$i] == 0) { + array_pop($result); + $i--; + } + return $result; + } + function bigint_num2str($num) { + ksort($num, SORT_NUMERIC); + $n = count($num); + $n += 8 - ($n % 8); + $num = array_reverse(array_pad($num, $n, 0)); + $s = ''; + for ($i = 0; $i < $n; $i++) { + $s .= chr($num[$i] >> 7); + $s .= chr((($num[$i++] & 0x7f) << 1) | ($num[$i] >> 14)); + $s .= chr(($num[$i] >> 6) & 0xff); + $s .= chr((($num[$i++] & 0x3f) << 2) | ($num[$i] >> 13)); + $s .= chr(($num[$i] >> 5) & 0xff); + $s .= chr((($num[$i++] & 0x1f) << 3) | ($num[$i] >> 12)); + $s .= chr(($num[$i] >> 4) & 0xff); + $s .= chr((($num[$i++] & 0x0f) << 4) | ($num[$i] >> 11)); + $s .= chr(($num[$i] >> 3) & 0xff); + $s .= chr((($num[$i++] & 0x07) << 5) | ($num[$i] >> 10)); + $s .= chr(($num[$i] >> 2) & 0xff); + $s .= chr((($num[$i++] & 0x03) << 6) | ($num[$i] >> 9)); + $s .= chr(($num[$i] >> 1) & 0xff); + $s .= chr((($num[$i++] & 0x01) << 7) | ($num[$i] >> 8)); + $s .= chr($num[$i] & 0xff); + } + return ltrim($s, chr(0)); + } + + function bigint_random($n, $s) { + $lowBitMasks = array(0x0000, 0x0001, 0x0003, 0x0007, + 0x000f, 0x001f, 0x003f, 0x007f, + 0x00ff, 0x01ff, 0x03ff, 0x07ff, + 0x0fff, 0x1fff, 0x3fff); + $r = $n % 15; + $q = floor($n / 15); + $result = array(); + for ($i = 0; $i < $q; $i++) { + $result[$i] = mt_rand(0, 0x7fff); + } + if ($r != 0) { + $result[$q] = mt_rand(0, $lowBitMasks[$r]); + if ($s) { + $result[$q] |= 1 << ($r - 1); + } + } + else if ($s) { + $result[$q - 1] |= 0x4000; + } + return $result; + } + function bigint_powmod($x, $y, $m) { + $n = count($y); + $p = array(1); + for ($i = 0; $i < $n - 1; $i++) { + $tmp = $y[$i]; + for ($j = 0; $j < 0xf; $j++) { + if ($tmp & 1) $p = bigint_div(bigint_mul($p, $x), $m, 1); + $tmp >>= 1; + $x = bigint_div(bigint_mul($x, $x), $m, 1); + } + } + $tmp = $y[$i]; + while ($tmp) { + if ($tmp & 1) $p = bigint_div(bigint_mul($p, $x), $m, 1); + $tmp >>= 1; + $x = bigint_div(bigint_mul($x, $x), $m, 1); + } + return $p; + } +} +?> \ No newline at end of file diff --git a/Vendor/phpRPC/compat.php b/Vendor/phpRPC/compat.php new file mode 100644 index 00000000..def43384 --- /dev/null +++ b/Vendor/phpRPC/compat.php @@ -0,0 +1,241 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* Provides missing functionality for older versions of PHP. + * + * Copyright: Ma Bingyao + * Version: 1.5 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + */ + +require_once("phprpc_date.php"); + +if (!function_exists('file_get_contents')) { + function file_get_contents($filename, $incpath = false, $resource_context = null) { + if (false === $fh = fopen($filename, 'rb', $incpath)) { + user_error('file_get_contents() failed to open stream: No such file or directory', + E_USER_WARNING); + return false; + } + clearstatcache(); + if ($fsize = @filesize($filename)) { + $data = fread($fh, $fsize); + } + else { + $data = ''; + while (!feof($fh)) { + $data .= fread($fh, 8192); + } + } + fclose($fh); + return $data; + } +} + +if (!function_exists('ob_get_clean')) { + function ob_get_clean() { + $contents = ob_get_contents(); + if ($contents !== false) ob_end_clean(); + return $contents; + } +} + +/** +3 more bugs found and fixed: +1. failed to work when the gz contained a filename - FIXED +2. failed to work on 64-bit architecture (checksum) - FIXED +3. failed to work when the gz contained a comment - cannot verify. +Returns some errors (not all!) and filename. +*/ +function gzdecode($data, &$filename = '', &$error = '', $maxlength = null) { + $len = strlen($data); + if ($len < 18 || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + $error = "Not in GZIP format."; + return null; // Not GZIP format (See RFC 1952) + } + $method = ord(substr($data, 2, 1)); // Compression method + $flags = ord(substr($data, 3, 1)); // Flags + if ($flags & 31 != $flags) { + $error = "Reserved bits not allowed."; + return null; + } + // NOTE: $mtime may be negative (PHP integer limitations) + $mtime = unpack("V", substr($data, 4, 4)); + $mtime = $mtime[1]; + $xfl = substr($data, 8, 1); + $os = substr($data, 8, 1); + $headerlen = 10; + $extralen = 0; + $extra = ""; + if ($flags & 4) { + // 2-byte length prefixed EXTRA data in header + if ($len - $headerlen - 2 < 8) { + return false; // invalid + } + $extralen = unpack("v", substr($data, 8, 2)); + $extralen = $extralen[1]; + if ($len - $headerlen - 2 - $extralen < 8) { + return false; // invalid + } + $extra = substr($data, 10, $extralen); + $headerlen += 2 + $extralen; + } + $filenamelen = 0; + $filename = ""; + if ($flags & 8) { + // C-style string + if ($len - $headerlen - 1 < 8) { + return false; // invalid + } + $filenamelen = strpos(substr($data, $headerlen), chr(0)); + if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) { + return false; // invalid + } + $filename = substr($data, $headerlen, $filenamelen); + $headerlen += $filenamelen + 1; + } + $commentlen = 0; + $comment = ""; + if ($flags & 16) { + // C-style string COMMENT data in header + if ($len - $headerlen - 1 < 8) { + return false; // invalid + } + $commentlen = strpos(substr($data, $headerlen), chr(0)); + if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) { + return false; // Invalid header format + } + $comment = substr($data, $headerlen, $commentlen); + $headerlen += $commentlen + 1; + } + $headercrc = ""; + if ($flags & 2) { + // 2-bytes (lowest order) of CRC32 on header present + if ($len - $headerlen - 2 < 8) { + return false; // invalid + } + $calccrc = crc32(substr($data, 0, $headerlen)) & 0xffff; + $headercrc = unpack("v", substr($data, $headerlen, 2)); + $headercrc = $headercrc[1]; + if ($headercrc != $calccrc) { + $error = "Header checksum failed."; + return false; // Bad header CRC + } + $headerlen += 2; + } + // GZIP FOOTER + $datacrc = unpack("V", substr($data, -8, 4)); + $datacrc = sprintf('%u', $datacrc[1] & 0xFFFFFFFF); + $isize = unpack("V", substr($data, -4)); + $isize = $isize[1]; + // decompression: + $bodylen = $len - $headerlen - 8; + if ($bodylen < 1) { + // IMPLEMENTATION BUG! + return null; + } + $body = substr($data, $headerlen, $bodylen); + $data = ""; + if ($bodylen > 0) { + switch ($method) { + case 8: + // Currently the only supported compression method: + $data = gzinflate($body, $maxlength); + break; + default: + $error = "Unknown compression method."; + return false; + } + } // zero-byte body content is allowed + // Verifiy CRC32 + $crc = sprintf("%u", crc32($data)); + $crcOK = $crc == $datacrc; + $lenOK = $isize == strlen($data); + if (!$lenOK || !$crcOK) { + $error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.'); + return false; + } + return $data; +} + +if (version_compare(phpversion(), "5", "<")) { + function serialize_fix($v) { + return str_replace('O:11:"phprpc_date":7:{', 'O:11:"PHPRPC_Date":7:{', serialize($v)); + } +} +else { + function serialize_fix($v) { + return serialize($v); + } +} + +function declare_empty_class($classname) { + static $callback = null; + $classname = preg_replace('/[^a-zA-Z0-9\_]/', '', $classname); + if ($callback===null) { + $callback = $classname; + return; + } + if ($callback) { + call_user_func($callback, $classname); + } + if (!class_exists($classname)) { + if (version_compare(phpversion(), "5", "<")) { + eval('class ' . $classname . ' { }'); + } + else { + eval(' + class ' . $classname . ' { + private function __get($name) { + $vars = (array)$this; + $protected_name = "\0*\0$name"; + $private_name = "\0'.$classname.'\0$name"; + if (array_key_exists($name, $vars)) { + return $this->$name; + } + else if (array_key_exists($protected_name, $vars)) { + return $vars[$protected_name]; + } + else if (array_key_exists($private_name, $vars)) { + return $vars[$private_name]; + } + else { + $keys = array_keys($vars); + $keys = array_values(preg_grep("/^\\\\x00.*?\\\\x00".$name."$/", $keys)); + if (isset($keys[0])) { + return $vars[$keys[0]]; + } + else { + return NULL; + } + } + } + }'); + } + } +} +declare_empty_class(ini_get('unserialize_callback_func')); +ini_set('unserialize_callback_func', 'declare_empty_class'); +?> \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams.php b/Vendor/phpRPC/dhparams.php new file mode 100644 index 00000000..f6cbbb56 --- /dev/null +++ b/Vendor/phpRPC/dhparams.php @@ -0,0 +1,77 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* Diffie-Hellman Parameters for PHPRPC. + * + * Copyright: Ma Bingyao + * Version: 1.2 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + */ +class DHParams { + var $len; + var $dhParams; + function getNearest($n, $a) { + $j = 0; + $m = abs($a[0] - $n); + for ($i = 1; $i < count($a); $i++) { + $t = abs($a[$i] - $n); + if ($m > $t) { + $m = $t; + $j = $i; + } + } + return $a[$j]; + } + function DHParams($len = 128) { + if (extension_loaded('gmp')) { + $a = array(96, 128, 160, 192, 256, 512, 768, 1024, 1536, 2048, 3072, 4096); + } + else if (extension_loaded('big_int')) { + $a = array(96, 128, 160, 192, 256, 512, 768, 1024, 1536); + } + else if (extension_loaded('bcmath')) { + $a = array(96, 128, 160, 192, 256, 512); + } + else { + $a = array(96, 128, 160); + } + $this->len = $this->getNearest($len, $a); + $dhParams = unserialize(file_get_contents("dhparams/{$this->len}.dhp", true)); + $this->dhParams = $dhParams[mt_rand(0, count($dhParams) - 1)]; + } + function getL() { + return $this->len; + } + function getP() { + return $this->dhParams['p']; + } + function getG() { + return $this->dhParams['g']; + } + function getDHParams() { + return $this->dhParams; + } +} +?> \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/1024.dhp b/Vendor/phpRPC/dhparams/1024.dhp new file mode 100644 index 00000000..ed320745 --- /dev/null +++ b/Vendor/phpRPC/dhparams/1024.dhp @@ -0,0 +1 @@ +a:50:{i:0;a:2:{s:1:"p";s:309:"129568058281196283485969852045082973240479662299833649655915078881064134837274587910680098630145331833314073809374103784577764371196941250131234226069290860531036282954125295253065782312888837858123565769812895344947719425674132117445174120829192037368513888110324906224313165146847550484828304476957369485661";s:1:"g";s:308:"74412411029812389060767064911429672552248323538380131684788386010483894594411356094583336355490245501438293594829741708592904979946709371629796413585578141928082616135469461600898538625232411795670398765206603348868016930193300395280159142433716706006511660846845763458752473756129210341944622900425176170770";}i:1;a:2:{s:1:"p";s:309:"146193716869508619647305139679263213856542375804651729246358043697244513997202825507519324367123148648281879781307709063806446534378531476829417062359168328754542266700915025319077860004928830404502692827043033744869104026437533251268433855993485126622032912525153084481026752912774722114259386768298899564303";s:1:"g";s:308:"69665008455351035902394440968350840909694548939696068493230686992883959134340037657032165407927257240961367927202156451938187477478359634699944054421395915668737939732656947241547267360211113199573477019756112574891965201688300035561288642801756915210306669313742136966503710236246509657858186512804588405518";}i:2;a:2:{s:1:"p";s:308:"95970011504465972968216025516056735009523168150391746798863350750628487022016558740903123981082492162615783238679595252201525891309321115574038283300200553527545213133632613244817126822324712292522172514337488336034824554888257812134279471335077413101896300746428316633744784706951717209185447418443121828621";s:1:"g";s:308:"32001234390591214193376879256032978095845138099384488396534938726527801485162551386074446838732561408327325537297587819822423354587910793955894800881058361532317172632826489329393036463815876353502280065088397376255064545313409639353330402859010245535643271582946371682731202352698451064261945530458419829640";}i:3;a:2:{s:1:"p";s:309:"107367948657744622403351910382294871172660886134042766184588950504191167376012553664832448482914453405627212505369017275057422865739635860055799977469867384589433510482716878025125735208146717913693754643825156388993040417089240042847866172996856390845604134659166867638714932484445695129717762215323852506223";s:1:"g";s:308:"35432052256872063868380956371395369446567951518895107007371489162979699703174160026603508244941666811604433385191485350533989707755652344700251327330272344163390347214659013791982459809652840042138137711943397019067880567618517864203333641800939772871309165704182113537048788646733770754235738140765119642861";}i:4;a:2:{s:1:"p";s:309:"165076179689180236399041719787853905509559840110034542544821025282142300182647737111192078636521696281849625331314634684082301307117056917096084810635909894266458257170816689088720750305011783930982287890608917322401215758373776087180348344303687659936705613789033223734686153637245444289163498175528538355183";s:1:"g";s:307:"7257097778465434411970060755441602617276464732216022873078841090902519498242797047568465618978053870338781634251702056843711528548879065633440550225057048183819140181212548735400876351188282105313257390821504822836725204187551346143027851261294592312829247674258710064400797532984515687719153634209645797992";}i:5;a:2:{s:1:"p";s:309:"138802088285708272974606443360541903346755775272625641090315912444740167056631682245175130288849653779718099745685973721625582881257253471469912033588275732534407812075504114028885001344754657979521240743598222852482713324944422564190132042911693426108095636266310291976312275051127638653255600619607748768161";s:1:"g";s:308:"68417768739254288613606538235899747640172953332166946096752518553591767961690284351247936702095359234884835162554920982218175460417056547752295163372680384373462615386345790712015724670852234108269209123765999335189635261342502383470729223332462342297600651014620539252087004543259974622328979031296782522180";}i:6;a:2:{s:1:"p";s:309:"143440408822834063256304001072379447612928758831014798604598968475998050944779945738610267109704057122027136269142323992275612512625193416837116502688466400091418946141409771130888652460438203432957802868229911319337716618772433262235445217129634258191904843258295950976235881931957544024858700764228870924421";s:1:"g";s:308:"61885916543751673602854962504624587475387355618874847004083364702999025366671327986702041494614967630576074420375515923449100469967023926671469204064186238960923581265396747860313554113531614635769731691080040797055303045109323006390999930220320481566672724416853132332620783770495166761662347109658807273598";}i:7;a:2:{s:1:"p";s:309:"157252810195046895262106972751573106014543521514519685514526312280470173673406217073362718196542447054177557777738853814564750348460292213548574898522849672157043162206681839289942712907178681480637456651237911559217788828984121397898667057591070954484991528199933918709759507489576582524237672309515073016337";s:1:"g";s:308:"88226515089489108825617534479543271381941380524155142801992166781725218337072902847660176074387609831777431786756574825615371213334332751708239568948591365196022411207206473125172401071031742000701493998811906302094840062532406089297779300213805172292794534054882548609113290200502606862814087039389398551133";}i:8;a:2:{s:1:"p";s:309:"114985530386639637192010327425709343494853838706808117399040944819410823551476787051890386585662495343435908127066317727387347589667037619326044414841194906165233165057587169819071837348100721622631027068393757028075105078368224325215567994990905693082132591256895393626358055498114303429757135090165754244597";s:1:"g";s:308:"91954658886623204543428135320064913668075738156343770210065195276894435619024576837084985906949383771834865278634709820758891770161134832009386328837080524363696464802456836386619858686421228303195226824855233384173023438331596052943262733993003608039164968687338024645722948542213129080275663447923469190543";}i:9;a:2:{s:1:"p";s:309:"109636871523409279767790340972634754329051398909884556956779733482149548929953420172455820185754193594396218755018820210816939914164446953253105835196134775430129532317887497749035659147652091944602377709986911544686721669749555303104118253472318080141451307479645737852211400120068770412867048403875625444929";s:1:"g";s:308:"37818248395638490196506083616037424071497042139318912208572715518335166153504034280853968065109925945696374241300596948545678886278292730681088749422984938877674324593818392935665057102238497543046661120593623474923808390078589110389438482877938086514382910775723604677940765395739691577027916901419974181668";}i:10;a:2:{s:1:"p";s:309:"171730493569370019376800099225484177890965402584439879262134362090208780017825875746914723522867989271423524805865035183047449735154919305905173130906979533370250036154805449250313007756615641578776997081126674385739513158578666666475902928085117932562730012747788409809904847316965666667562299267227963953209";s:1:"g";s:309:"108416022315624195962025023721429686956214474671377630577595792182130934651146546536934806785055934780756022131579568185897105910304336666966603269784935938299676652324388066306399902577207000810316610396941802565186861722182315811374339068009895153890079993046590210907050629248793523019275731677163852103278";}i:11;a:2:{s:1:"p";s:309:"122106850849876812974026248474577243429513625504577859983625726463984009864701112373037766966449574405643986501924059709161200764018639946475182619842398415505427880887419201361794547676397333516971649037394750916047253475385290090455656437086867354170238521151796557315029217026885863606073266370855712820719";s:1:"g";s:308:"24735148417562057840168476236802864525918787478183767549255404873115071566410820342975609285551159637301964099270689346814428231138259200159783611910129880506577636334045758775993631403235839108647573874932088398186329326859338337177512287828022266115337530677346513192023934283754416757903570244925408141124";}i:12;a:2:{s:1:"p";s:308:"98563064041855485547203709600999976616419318617005972312351844359425573674247265938234295573987429665676307716147248366503793293946473843863821094112041842163433187820029643571486513623012617552199332014038456603155834453649363234466831889556280793416223207898261294552530862813499919423410866004801362984157";s:1:"g";s:308:"59438969191433206885160654546800973338113955254155498154081588424773915117978710991458854168836846149574281831646696983304381311140860938963799520039261884497369538383372456178914971487015682793424582209855322967460266300754823895771337403292656106744806123861995705604402095631107844241722972208149696069901";}i:13;a:2:{s:1:"p";s:309:"178284570928419116251879511232308570183768336425183537983900704602870837188332981934665351235828833856090429560178119229215140472009400606724448162311527189376668655398871211015154270102539242482291841778242319866102591751437519616120511427151657963001938761731491181176323677631190765849664845153959486560283";s:1:"g";s:309:"148866999117635919417654566555696301710898017486560869603508728720369000308011510499499432872896469950541973497581527050700259381170969069051888183343314713029719431048716245290397673569650907200574767862492308652304273160426175251156907772789224555079381452284087020498494077430745587197689507967768857105956";}i:14;a:2:{s:1:"p";s:309:"116738580923175563597852946259942668774376741851243739225112168154299319378570097819002752583211279288010166314376092749452022693090749405496712595173427088219917593978092666816371487183342540185349140910668072044197068187531521505601089090756898828738261874761402398001673390547712523143844149045116052320447";s:1:"g";s:308:"40034019056813540582152025088875031301471554203237488324792191579491686866385133449374555241477936777633651939990968648667228424361281957258281751622971833684652653172758624480857897678112312636724089024553363699426562753044909465441006363024563493791311183967053810493340062539118031062536501032727371656556";}i:15;a:2:{s:1:"p";s:309:"126416923016504794892262733817762961386741581091282927102847048681387859009976911891213445835335683685961824220040945930186942069653866470565058006364859508113271188926837922616983429432971047367039856437192480727203019675679406394279531743601364712279259153955168108639232674771097755353305522755827224808783";s:1:"g";s:309:"115217983612815221807881039047616510833937677746347677762674420215129457029965858858381020879648451528607840750667922014522507961901103522126616783107408227640178996788031640423168737789746950166860880632363377442064306092590337543542962209423238876035647879264300565404605950968938772318148521663749673131099";}i:16;a:2:{s:1:"p";s:309:"143625235691679173790886628527372299203036999068004043049293157737498971333598566984526746417282853572231806173640623863668011175162069116291184420978114679218220215343843707983230876997357140567082288451238414474598947943184854685135804783998570746961957854573146698096808752435056693051401194762660928100291";s:1:"g";s:307:"2811906146542542544508099935802560496259761014277619841236735465830246544879946190087219311700423280133249036896828576018583549158462866232998364790129911777154099906740274868660919875297049045056201762749104047808011371830286824154334564178537171875355764504606152138545087944095720124720892297463471228703";}i:17;a:2:{s:1:"p";s:309:"121993314148770027219037424907576269470769429753193286495985674269623203562674630388975936634497963788324829621047210948121667489694438986232246907066349832212292491390918321554381941982921602817218049875411538677739007395791700194829322235503670960059494915298990576486708275549417539146086251251624135349939";s:1:"g";s:308:"76136756831073177744226997691236148872628027575601681328786412569385300051842743182050455179596968765127239279852680795886929553043311383681954887233978473067877172753495304640131160100079991048334006169655578631036144643965635995290531840054826540373743555549720623816740175043396340429759474512569110591151";}i:18;a:2:{s:1:"p";s:309:"124507994067600742618074869849502068365304040789212000487597154884662225035334860191210068989342872209246000032800019976883544484524411784905306951476799686163700601896271250346743329785269061645715826764256180887461136011848692557042253327916990782493758819566513663718823981060679554727596357143528871317029";s:1:"g";s:308:"35482091456711296536619960625191304461320385791007440302280000459820091544274446698718600582729456595724243302196867721560781247921581506087934961217320172517820436375036025679986744433993300325533389319578275768579785520050047676029798921290638765091850128922108253967600366949053220716093204424923866639659";}i:19;a:2:{s:1:"p";s:309:"109064911958670773649835739607804087660086265501176811018327103461487668225519906223353251760111190939688515131932304441638992866400411226029802671305803598781894196659707854750685867585938708782669538095831227041248283200630619059108032196443898570993622064280958838616123797547223348352709177595311511599127";s:1:"g";s:308:"19319085215957110536116059458132145601846897698032302263421502982575340197281074377754938122814767436026933811580737427951112223724536263615505177029727037084943699236718859061711113087160230654888547614277944690686053963024350436971089168545071233076652921578379142066648762537208150629974955548551496035508";}i:20;a:2:{s:1:"p";s:309:"152906937544903906500158994700987429025320104102810683664637770214766670911595774070719831089658199116354030446402893709562506135087569908102297576309390792224913162999986166517633590115811057491043292747990827411008636071214350838529749370926702854124191129277803120854478952648197409338821905891673530410583";s:1:"g";s:308:"91187914216528946835934502389977046892487031834663291019963344959483826794791886459334460883860381266880371274752391802612238136138804906007128976482853796298630067218594097450162858199508629386035676253140564960068420655423166899188074787874980346006766017039274380084312606630473497196077651554580178899620";}i:21;a:2:{s:1:"p";s:309:"120086911902590349366454763756514126237708714726873488009496335335637189915037279805404346623857583026128779203569864388549114527319559676012081995869302301188337042796528657367058068666482059979304786341533831397236939898922005010598725616120953311774451680404822020000603731144436784446124165276717107943767";s:1:"g";s:307:"4424877313153692455459160010045442376627290942868240892963899133364693215888804616996451658036573295042389069650630298172240061707271934897152643400497308474473895781338189295452861594891955327070306932371961613259631255464856486062618144044590877854971649831663385524916482609955557119733681027235051394932";}i:22;a:2:{s:1:"p";s:309:"114348651836506523500945935233374922736007775412847938214326113685832510534729952115503013208770982688991421802461695224699078655218430623713975694946030893977655752146594815185747948759946130185443646234087578887495356406232198663781066104307878855072887544156539853609255635001994884140842596116557739719339";s:1:"g";s:307:"3057093897497336474088939848688661425207560147177357671574081687524315743030139763595840116604296424154647944641166825852937323648159223225785426718349765948296485966934692317251464598254426752313531074560614623259760117723367044048992743223355384969321694573041256516497658853328140689287015483841963198485";}i:23;a:2:{s:1:"p";s:309:"151327650171178840752159959652360320262504680172183688626941326142323285313387175965893936843422387583059747539217294800332826680621899964529924259987091710340379569950289775771095947259209635172546634980224610800461576519968535309440918178046872340066339103756730010311335921411262306273623820892604544491083";s:1:"g";s:308:"93698947898542625080224999126897954039977816399726641263795164630099055943251781086266175948233460340162387832326085867234397994791219403143430000582587477992357941677427763758041941957575706031515765338579564903757662164614536867472674838978395200565535988130855861706547826534924631265525304939324782653714";}i:24;a:2:{s:1:"p";s:308:"93521349632285344521892805711041617086177867320264156006082942266085555239430140082892856429101554903795878410700096375285554712092378461187415152844263072615812187854557693901260441992278421683913551405640379450072927340627546240607073580365588955121454018383348564233577572631416908081675968109054718213651";s:1:"g";s:308:"72771444498359995710897378671512916022955775236629004788865109476298715383451615148812465275461129578179286998456555171089504695435937979981487681863800662090010955930732523942155243068394783205736383507489827275947913244113978685677151547805378500227336458209605695806261274104663472071017000731176318137622";}i:25;a:2:{s:1:"p";s:309:"154538027567571020051211849456110781402373992733880648830768917597755638265440933232881652059213857800411025814190629364180958088042486785080095848649421973721170250640044907161165782781498829401355213704798178816875963125988553036855252471477479214335533104910682313679864758691208754871335938134146570244233";s:1:"g";s:309:"151878268383910627178775626075769783354408670111552691713603803262208268504534598144185757441663543391767524850440098706725577284510706316706784129116482666131665290402058351722910804879096297592649548518592704064553732795220929615663992939631806717400234044169768626282218689487288304150755186241724898111829";}i:26;a:2:{s:1:"p";s:309:"101653566005311023925476332074740680760986376640227033128030649304832500364833045686179637239812634502064069571359223433072628429786421692593933101196289496232554055527830367596771381014857286540650623892767418966585533940466064017851317632676358364053937566259716232595107740160572362341096507417302692903861";s:1:"g";s:308:"74513607929035958667614526386443731970505034893688087329791851500228238599981508473298612939972711716486678692030303405741746145559282283162063549999965122587859070966516041155490470664682457776474615008916731802079841562892122761530124749566709348258961907082769282945089628529694000014717122454967698917460";}i:27;a:2:{s:1:"p";s:308:"95013960730537646945707930117033259716425250443303065109257923132885025742351896240153856832266522610218042023001720718571959026083577683594238991046216761447273850529095670800239812482889546714995990857314170023607531299056678286770352047754090948625051516504247244141244971934385607741647807871939423643417";s:1:"g";s:307:"8865118845127243015967838648938431880490166248417614215833772532595068334088382421370444972119810353915368575955429426679051753997676166286454497698339421653032306173169181980560322753725269776395160793563057913381832550741293157158306307662293960121073170223223526549325156207936691130571839423818348804874";}i:28;a:2:{s:1:"p";s:309:"165171568680967123886817133609555478777376451381185880118392760161526195696056154677234447980800025307869740068307389118220255165799524209662639178475579984315366245832285858100155088238540583941028875367935393602555119105296112422147861581513097413687377533516651030313147659549849822429529620533241957376461";s:1:"g";s:309:"125035932268322111740442907189656967999398670741804679117991185625792797440733765792321494160564108005199651911011206634432661255852804587565419942716241432891303926297868064874944963552504922882417912648147956818566297482440510358827099695306382023608097107907616454643867088476820708208837260972148368028666";}i:29;a:2:{s:1:"p";s:309:"149426789853068576691755408517052689479631486303474855851435537819356576423401695805659694193339781938404097894957535566502875170679660046587328388332483673210946843879963235153300984461866198864922318697292136026813009299028730482141451343653633845072186024898362005994170295241610203348654612524541396422397";s:1:"g";s:308:"73049073326296538965204086376153534487090415894032911283800130298629512997442525640837238968619479480629231884187445441225287944042744290713844591778499386520701583015778604634989765861327662774146166059025009694822186345094204748823299314036557275575979692921442204327068917190507323721173826594618769385979";}i:30;a:2:{s:1:"p";s:309:"135576329950386319783588278542132482993509697780105687913763037715299072538393798842105766084812653813647207393906971415039384965453861783642420021499035478002876073188931021393616989459213349405347142133542309416134384844351939543623768121011240069777383730773881088056874192238013050626270026174182267430717";s:1:"g";s:308:"60290997726824005308014865952860150036003597394047065883797290775765998303031531128172348476104602100923880751224159249009015002013080863909428509827722962421722642840399830757903808956875244743719288448455233739472345388057408045449495018163568905120714599842949385074246992032986074584000551188391542767463";}i:31;a:2:{s:1:"p";s:309:"159065776098323310441379296801791022455112191137870334479728771028751912269616629460900852200402421009307482473450428015915046824869147855243477769734130917997450446203411540494770348199589203378022151536992114137202513049016111036147137494187423144663693903693069118404837384424743130353522620387505597979359";s:1:"g";s:308:"43262178902448634370560334233060164330909659542673106272550614113862676255101507573561918404933225250124875942010295679192073921803863446466704825450009940939748827765323598689766356218791822315938651724944088733794097890759186493099112538275600413748100124980228285409612371429943359045997493847309113094420";}i:32;a:2:{s:1:"p";s:309:"160394941658450930276801031843077823785507821874720567147511483933208719668066705194765948461937550873363758297677780099637494770481353160979298177536248116532480392143334998523558523755864576621025753190170092723744034008237711325789361465741779607652217503455195004836525957182459455212695365562397642327793";s:1:"g";s:308:"80547204427645310086317970329606761433064424399921493097938200607767280488068285659681897406984483932897624033557910172823554540190625306750715210905207903368482988268690529944147507714249162654641932802591997206826192545609133886659250269751768696058736169665371823013501660148951330528409739051259717561690";}i:33;a:2:{s:1:"p";s:309:"177204881539784382588587844818041975965303560543162630455910056438154838593138830187319688900891313579137735937814467432633223178967482608482890993831012978464354436059856781658299553545037014282810727108082122588695746040219389387811199278574283486984537788675106695657576082357971493731577296175232034436141";s:1:"g";s:308:"69235053132347779619993662979522806857339437477106976840223821553847294669711048050675068877860119501392090174568568049659762185187804664573479845315366181247065012559547353319817063459644529835997237851200186729133930957640120723326425914499963919940154634598957978320326819438511948953408983404730431346679";}i:34;a:2:{s:1:"p";s:309:"170632450386449252892177651707784510677816625351105295529973803089643511952292071117487088243581854585627834705143965097010002760714509270510175372080209246944381024402704210823368565134636107733496734242350149868764032016679575323249886774833276221888180845935536877312614375117430059888272016549986096298381";s:1:"g";s:308:"24472385768968026997798980591786418974391665216646569808610375270769405972123783498459702414787564780388487976158770080827973184539797280411107573023349088116818340517293319973443760108032296957122632603976045312015768310687201612205589952908786210188329173621466708105183429140807264065028128471662573361600";}i:35;a:2:{s:1:"p";s:309:"106658122355520675039628277711696683144582739154934203137085123160221461841008030522414574684630155853821380331921319540272434071011591133318016562285627539130389090569115783107308483014499994503494308836196758225421785889774862524445335359696266057221770535448860053645733764498088036270185537882385482831183";s:1:"g";s:308:"39783652361002485670275466730672530969147764387968401456017775771979782025778665517161604038096192323204967577144624873089805078877923323600555536296131983877118252913078053205536795585717846083877586544103441059828092151865494642451758943378392029454891361242185344072415082423303093417563841046684352151448";}i:36;a:2:{s:1:"p";s:309:"103044743450356815717280629987073025863731845223317680836739897408078663728915414987974010186550546586595930233874188379117304132766900332673653606876214967343386204242329787067659113843205186608833761820128296608284953666985708091388382863740453928554110827130493742351284285532384147373799262231569250856959";s:1:"g";s:308:"90090058479749571428201045607912930124405620381996502603882386590496176073989569208448372732705389891721609719648629186673350918601783194334467381010968712369734326596190517082744138100466263787508381087402925634188635370622908873072815732169546219741518638971435909681793234308560167890325451296165583963178";}i:37;a:2:{s:1:"p";s:309:"125388209275868954338919318322433241106530307022343221377908573761945875896771826464040700182523361756959326040847908815078631193501532095938945095221093193286494713316096166068936244486440645154697824243384714912745011963991559904054699172169083499465381741721552580299869624834814200547479930954834702869467";s:1:"g";s:308:"88667109474041919409913794223971780303805302466161109886012349328724495178758113804709357734253441488703362846364137262391434253925210240752446097480963427198378575051635750668392116625679462417025783392797833504899554705232341840759599879188837609823053497744463005858819123144669211197475473256421788902998";}i:38;a:2:{s:1:"p";s:309:"143949768931086061604940118166532662934380945231267334574786086591887870050187582969268702068457305227173986915861510012707751007961140008160896148194781758723093984226682835875932742978257118050540576674378910935190769292316700539205182480917522964863427122871625517021839596567122012919478156411734686915977";s:1:"g";s:309:"138466632730009703263604483957935077591344930459555672237159749136157934320422889392131771025368995584492516955806991516958678527504262618479774885187067450769695885037834750726818277199698417657533016521761911424894327191784411447815745375877220891536113807184440318107567817825269486823752156243704505549697";}i:39;a:2:{s:1:"p";s:309:"175420727176478352783121714923416552881222745068680163347615288184223170132146515858071589662128422601876827315329015908922123050339231472535066426849260567046474903451891613375732255710996752666666429634222976593100111925186060523566568836985586751950683018244960710294161130739354264999973915392300513010669";s:1:"g";s:309:"102214296436553733388725636282118899490816111744922220769692374117300143278361415759909106009565248076781429421870924605232528811484830856869108078614870493726394947463288917149234179718831259015495904087236508316630128687330799396156049244218724291725012201270174939120336334613215053968238776073474709467334";}i:40;a:2:{s:1:"p";s:309:"159794800055348506571008906374836701462998540886533040353197135807163688421982933759743988362547882565601903919320227504216575700066744239387795654881352389673948479450887254384341226868981920609707096127165751516392484968378483701427198667309154393238401926688124380137237516707820272504228443061371360165201";s:1:"g";s:309:"125545954061807909213440974725673246010848665665902291111413828394758575587589962734315460601269956757971755540646548110374935166026100201454535822567189177241543789524176158023868303335124684764707826312875234354490525831170982282949580832090899553475185463231422993237487770186065056142320929583755264509339";}i:41;a:2:{s:1:"p";s:309:"100539882750827218683038523645435201793549230666573329915693212453304697477172915665745340230392862173855829201370306578877441376204178128180077679525298804707605907524492059908201893059201739409946592544808266797888266407195817995198097047681246712771143508501927477035153907568921002415521626713210871346043";s:1:"g";s:308:"35502053686226969950955336189827903558684377002850015450754413739937497087878601307174154780066555396845534338310205261283992241970794651452902383865029730265568871805501296029304576201222119877387937815777937271202653885649169466455244309442119655722851543473700201461896508440245001817562486228545596343608";}i:42;a:2:{s:1:"p";s:309:"163883088092169708750236298536140720039687203494799123680434192685621955270090430640683485012985988431013394323683780842964037507442368800026594927494950463285267496279525753657775606544352907707733174181132340012100157483379593750752972189141532209198932176506722571756928339227587633423995901120004952354761";s:1:"g";s:308:"21165897458274279623174933098408694536958819285248101600565840156627556793518769244526228428619827425694586345400323334844888827367491379029972237832974198947482513794112611577346475499184088771263690674973716665704216023869046245629889113229885861874638379352584818782358324175120814914412282487903605785953";}i:43;a:2:{s:1:"p";s:309:"158310278732715787022902619395810013339735267417224324445908572573513416852425846360209440725706619854191344489651342220702140566155238540802871753904947103638583986388285621112626977421886423502443003940413306887906083091475336779687502256926095204824702267835164082066519548090177807665844915376119641694361";s:1:"g";s:308:"10843632849807178081621701225073955336720497461666456417094069730548352280008748877225736209050583172763152571705900002329657804689214917415555838692658283058931020733361636160389821172444581043732406612290988648168803751381009032812842751877417489545282283613937636557019594975816844435163566172375045198580";}i:44;a:2:{s:1:"p";s:309:"153347735020776109672598090634216407499745284347480917300658818545198675701611122459685722367884460242515317436949386602816072625929743971764067680916616908761905707081856774209123031494295472642947392714965504325544410178836879029320131059764623341098464482119547364444225790414659989577180817023099747806219";s:1:"g";s:309:"122954310235084188725866074640958827281122476177323936387469275802984759490453353855653375904411138407476003678979649372393814463080666349613725044716044211530706906010081396524233937871139226812356391818759073899430860506374698518561365425436590854680442478600581253443022679747914324251713532666663803955266";}i:45;a:2:{s:1:"p";s:309:"105119383111574947555756749613427034115871685365338216999216182362104799407352348214405998777527422827499905338598543186574235633401319346122740730194104928531642469747870053113686583094237980081517574187423239107189826416021743315549437633596207434042084300173060678340091298306743614170285022383892833272317";s:1:"g";s:308:"67178980779596302685699276457331133093242115605891944037453156935974692034220792130263273292844686981258966134995193845401621693196880186953298375654676956749648419727313952831168688324511752698322454731426431593820106946644202118100133887201187978438871644005504337273486695678858525227931317595656959050814";}i:46;a:2:{s:1:"p";s:309:"103032591117379756539799688773679250452536252275580478745302392328252396825436802273785825761894063424135369686372016268918702883198596320220024055090905544130543248384556888996699089102078751994102466915262697550823095429698807867041857056199662639242062280833453801650111530359676277918138500762149217203791";s:1:"g";s:308:"77132801423319304165796207386958946320042494252108286515106992435042926191729318949722863127204416805833659339064969009910067600668843619911038984483433433617169906588079273102517397432168428053712322220890666083309668099651430019267046493644946772357567590144667581996075280334527222547528339859786299081931";}i:47;a:2:{s:1:"p";s:309:"102085155627955815095542920619146526387782679507307151846526493529130800012104779480514121921687848167194688460305927109149559545461691767269495772073701759547274290545646610000657936697419432724419115249685635339910931149030927018431690660081084386412665095805815028555042991555828923349280187447568942620549";s:1:"g";s:308:"27454324351455464224886256988337512968951014643818071525638765600705727743455262346758378628869548773191699219835696316409465156796657956179447196850180340548717017879359249274532768288404896887877489800526718802490569932601316656411893344856428111523823705865338040702336541777735189187460764613244420564133";}i:48;a:2:{s:1:"p";s:309:"139300783541692859595840908230318717324833616486825199849963109829727143946631572973434050282537779419439403310172134664925360812720995043013071012554656861162082506619208677576419320741818481236877774498337260619037804797461901823273337809052154052894849643006097478216997712928420055709178233445255308361101";s:1:"g";s:309:"110543956085772475876488567113525531945490203248111771432474506376282741746886768658898900409682098825014100780195520527561919350237842066983251165229178651412242741196039787820589590428519549154581837021452969522343352353534257888745437891875564792402023341678616463369894744400700376676910140567752536422210";}i:49;a:2:{s:1:"p";s:309:"140481282042623513171757047048340154221489789742748447730567837747883807070388996878704463331184460145505583061254384935268451450084968799400716266246866822185422597411114352295673685607245117959083546383457343144702896784371346366101512480777183669620433643591158243003892756293342479583829460630913480276589";s:1:"g";s:308:"75251167460967282352429912701249403706989070317963542102818801005423115111161788531265287611693282776684802138420198727319983028866819384860839081670321428144683302615744779867229499830239463688840840537403755994658696002903600035111943070257625695218188008419573921013401986992437874454517822788002411777111";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/128.dhp b/Vendor/phpRPC/dhparams/128.dhp new file mode 100644 index 00000000..12ab5fa7 --- /dev/null +++ b/Vendor/phpRPC/dhparams/128.dhp @@ -0,0 +1 @@ +a:150:{i:0;a:2:{s:1:"p";s:39:"292056242036581752787140391622158091519";s:1:"g";s:38:"92195130631865270616756943775010543543";}i:1;a:2:{s:1:"p";s:39:"306974919588773364832090085053788336623";s:1:"g";s:39:"114777600433746811424326551581233247669";}i:2;a:2:{s:1:"p";s:39:"293639007200039809639032425563054392623";s:1:"g";s:39:"142581017277461467135688328294730434355";}i:3;a:2:{s:1:"p";s:39:"196846296865248186540320570524502677427";s:1:"g";s:39:"151521785256606845258315346858388704159";}i:4;a:2:{s:1:"p";s:39:"214058314731091729962462647631129015047";s:1:"g";s:39:"157657285759615277755120995221831770183";}i:5;a:2:{s:1:"p";s:39:"211544627828281195628005482334918005743";s:1:"g";s:39:"164526962259030671035597644393561273977";}i:6;a:2:{s:1:"p";s:39:"264374153248813750338546404933838455927";s:1:"g";s:39:"161889252888199530110939775462329045141";}i:7;a:2:{s:1:"p";s:39:"250744024384599107683215360741111008699";s:1:"g";s:39:"118285577307522764878235247551273436525";}i:8;a:2:{s:1:"p";s:39:"203253285951672991854853186118633154923";s:1:"g";s:39:"109635202434828818623372966675160073683";}i:9;a:2:{s:1:"p";s:39:"297230087236684619171820155222807526239";s:1:"g";s:39:"151698002932284917728519787908419298293";}i:10;a:2:{s:1:"p";s:39:"183928564855833010909727349867640971323";s:1:"g";s:39:"162553618575521753939201816833697743889";}i:11;a:2:{s:1:"p";s:39:"282116071387851542448859292585051222447";s:1:"g";s:38:"96195080035033034987512884449304800701";}i:12;a:2:{s:1:"p";s:39:"323821345162263657163869210284973385427";s:1:"g";s:39:"165647931357595553282108059453854618133";}i:13;a:2:{s:1:"p";s:39:"325782265605496815296945192046960828803";s:1:"g";s:39:"146673523487430798803433071896683677919";}i:14;a:2:{s:1:"p";s:39:"292656882446135308138325253216560626763";s:1:"g";s:39:"133750897967258475364439141350154768333";}i:15;a:2:{s:1:"p";s:39:"326502508934692287898138354588749827579";s:1:"g";s:38:"95055028992751783265751636323610219169";}i:16;a:2:{s:1:"p";s:39:"238737081982465824552117175513390104503";s:1:"g";s:39:"149717268104904047668959026140422455329";}i:17;a:2:{s:1:"p";s:39:"325520862010996140507951562729031642939";s:1:"g";s:39:"160750290369379144250044243773210944781";}i:18;a:2:{s:1:"p";s:39:"284660075545249738683462999870017380547";s:1:"g";s:38:"93610554989070752708257914727841862017";}i:19;a:2:{s:1:"p";s:39:"216624906373462199236239231733765471247";s:1:"g";s:39:"147533447450211848127450101532248247737";}i:20;a:2:{s:1:"p";s:39:"310957194217588922918999164668665752919";s:1:"g";s:39:"149940487727634664074703848896592397309";}i:21;a:2:{s:1:"p";s:39:"223668363326959021386397963580036366123";s:1:"g";s:39:"107617531844346373239590352039307075491";}i:22;a:2:{s:1:"p";s:39:"215978097038720595934062824264229612527";s:1:"g";s:39:"159683714362048234485774830980270810467";}i:23;a:2:{s:1:"p";s:39:"254574157135387128396125954269859179739";s:1:"g";s:39:"152701269536030391318337642370271369325";}i:24;a:2:{s:1:"p";s:39:"285631418265701142797921983323494263559";s:1:"g";s:39:"146069911336721121221056226300966199857";}i:25;a:2:{s:1:"p";s:39:"338159277198626832869677887277616180423";s:1:"g";s:39:"115921496078116668896708740833402711065";}i:26;a:2:{s:1:"p";s:39:"216947143156151209031346105444363017339";s:1:"g";s:39:"138824874907565129063997286858881153973";}i:27;a:2:{s:1:"p";s:39:"276066866652515571839979520442563284323";s:1:"g";s:39:"128901507729551455645968559013908755883";}i:28;a:2:{s:1:"p";s:39:"285669464286230064035191348420068105563";s:1:"g";s:39:"133687329906681409517596983499858741779";}i:29;a:2:{s:1:"p";s:39:"191091625204338316951536541367974663739";s:1:"g";s:39:"115858048207727468438106103077246560679";}i:30;a:2:{s:1:"p";s:39:"337515161669050885294632549226272979259";s:1:"g";s:39:"120854804811508331843161695166187664953";}i:31;a:2:{s:1:"p";s:39:"174917215197953698624444001586175836407";s:1:"g";s:39:"139145545032511871649890757539716139745";}i:32;a:2:{s:1:"p";s:39:"286385113219804783667463282575249335643";s:1:"g";s:39:"148416238100899996847378967300424921461";}i:33;a:2:{s:1:"p";s:39:"209708268755657765718168447424437273947";s:1:"g";s:38:"89390121362982706116847582116053792661";}i:34;a:2:{s:1:"p";s:39:"225466796807811837787826426622847748483";s:1:"g";s:39:"119671516376904551623274021751719706435";}i:35;a:2:{s:1:"p";s:39:"230641118913675753332052029881543537319";s:1:"g";s:39:"106904796246200906002843413808899345201";}i:36;a:2:{s:1:"p";s:39:"320356446694223075350802268074194516883";s:1:"g";s:39:"110058673619329486246922731333508660107";}i:37;a:2:{s:1:"p";s:39:"196818317043011000998928174914246107563";s:1:"g";s:39:"113324249626145305887996118612518826373";}i:38;a:2:{s:1:"p";s:39:"224525332386128175478101630046930189763";s:1:"g";s:39:"108794399937298102548174167123976936181";}i:39;a:2:{s:1:"p";s:39:"240020159051805416566835088425214246683";s:1:"g";s:39:"122682169319663959002558338806306526673";}i:40;a:2:{s:1:"p";s:39:"194462122760796075851727083710896064019";s:1:"g";s:39:"125773984560640978959501682731083867083";}i:41;a:2:{s:1:"p";s:39:"185409874317812986685079176545573532819";s:1:"g";s:38:"99333837867312477025526770551684789929";}i:42;a:2:{s:1:"p";s:39:"249577380183382163061926592594820452239";s:1:"g";s:39:"145358444229966857167759564629611560067";}i:43;a:2:{s:1:"p";s:39:"175893673428733191813784481998618328243";s:1:"g";s:39:"132841634307591201423154416956579429157";}i:44;a:2:{s:1:"p";s:39:"307677647975104863327346573139531157887";s:1:"g";s:39:"165281368579891364595473211906122097919";}i:45;a:2:{s:1:"p";s:39:"325531007121336077474467231244998934603";s:1:"g";s:39:"113453603821265113678470265129170917013";}i:46;a:2:{s:1:"p";s:39:"291853334277762332165460454523197195883";s:1:"g";s:39:"112304674628631114572271595370414970737";}i:47;a:2:{s:1:"p";s:39:"321095002670328264904742293131676711247";s:1:"g";s:39:"111234333539460488850936780994186665521";}i:48;a:2:{s:1:"p";s:39:"327904717403107858772768435620257823703";s:1:"g";s:39:"135928358598869100491972026891044903849";}i:49;a:2:{s:1:"p";s:39:"184167219998611207248355443296589162623";s:1:"g";s:39:"157493611435172681271008684759507092185";}i:50;a:2:{s:1:"p";s:39:"214547513104198035614282222084852692283";s:1:"g";s:39:"143129048934951872319248661290580415565";}i:51;a:2:{s:1:"p";s:39:"180935587267248385659347192451794341139";s:1:"g";s:38:"87403976648407948326670717447739794827";}i:52;a:2:{s:1:"p";s:39:"263818812910108424430492542012743121123";s:1:"g";s:39:"150521173398666971792260292936530681753";}i:53;a:2:{s:1:"p";s:39:"297105925338731622311494789834838923367";s:1:"g";s:39:"105412171901317536491270709831194772423";}i:54;a:2:{s:1:"p";s:39:"243477408509935222548750912761663403707";s:1:"g";s:39:"144281761591161263922410500392425300369";}i:55;a:2:{s:1:"p";s:39:"299510309907221406889358192415160524359";s:1:"g";s:38:"89872008322088932958761182838622988425";}i:56;a:2:{s:1:"p";s:39:"304910526413244884233459829695367833307";s:1:"g";s:39:"161607538803038797936035617030686594595";}i:57;a:2:{s:1:"p";s:39:"203291411173723738334374535456283611867";s:1:"g";s:38:"89443086632858787787237362893463069233";}i:58;a:2:{s:1:"p";s:39:"205944278815676907758242117465652266619";s:1:"g";s:39:"108018077395004037033024244150011486699";}i:59;a:2:{s:1:"p";s:39:"296687706241624223629592967033355602527";s:1:"g";s:38:"96745488554386356827679857768107368081";}i:60;a:2:{s:1:"p";s:39:"293550116043549804890822649451111414703";s:1:"g";s:39:"158806215400749784831080725121944668243";}i:61;a:2:{s:1:"p";s:39:"263428134653217195777465522428064821807";s:1:"g";s:39:"118547891080671339398050662124658121383";}i:62;a:2:{s:1:"p";s:39:"325923864457460442868064053037621833547";s:1:"g";s:39:"150617615016200927618807658935974292457";}i:63;a:2:{s:1:"p";s:39:"196476504632822117192236200421668858239";s:1:"g";s:39:"160523445701389768553272859591184805705";}i:64;a:2:{s:1:"p";s:39:"176583442445218673933803855316690739563";s:1:"g";s:39:"132111065569185005904201982609461776533";}i:65;a:2:{s:1:"p";s:39:"208026268064317066201094177474542461779";s:1:"g";s:39:"129201867469581710101028427020543597815";}i:66;a:2:{s:1:"p";s:39:"334723033531927024498400970288217064519";s:1:"g";s:39:"127487291993357723200673873414989528691";}i:67;a:2:{s:1:"p";s:39:"233829356466320610519071132649157616807";s:1:"g";s:38:"94860858528074519022402472317646994195";}i:68;a:2:{s:1:"p";s:39:"188691996182260359105060338959757354147";s:1:"g";s:39:"162385010597491525627389624230217003233";}i:69;a:2:{s:1:"p";s:39:"226897261159415273301339620896213232363";s:1:"g";s:39:"156442352209872496712773155991679649819";}i:70;a:2:{s:1:"p";s:39:"236583358352137488729569337157796756399";s:1:"g";s:39:"152581941462805442071888683283182954713";}i:71;a:2:{s:1:"p";s:39:"201191190567504115316899173583099194503";s:1:"g";s:39:"103194169583174226029359181901898862399";}i:72;a:2:{s:1:"p";s:39:"283922273486502260013681112736384903039";s:1:"g";s:39:"135753190954064714225129600901141433767";}i:73;a:2:{s:1:"p";s:39:"223678587798519865477081555130490930887";s:1:"g";s:39:"137587074669296278642987846569068217767";}i:74;a:2:{s:1:"p";s:39:"223668244430177551435115121204793146587";s:1:"g";s:39:"156320667147688293051263750282389084613";}i:75;a:2:{s:1:"p";s:39:"194289571790886902139380720985511224443";s:1:"g";s:39:"107945851243046988533476937950371933915";}i:76;a:2:{s:1:"p";s:39:"278775692009590991350111858729107596627";s:1:"g";s:39:"129657043560683363524105717085311868437";}i:77;a:2:{s:1:"p";s:39:"319979086847889596207807729864047286663";s:1:"g";s:39:"145322816086479761996731697936810408423";}i:78;a:2:{s:1:"p";s:39:"198304778645918608926012835033912241723";s:1:"g";s:38:"92721662469836619760966684666997323119";}i:79;a:2:{s:1:"p";s:39:"248958430506627478869847133684906264999";s:1:"g";s:39:"163946236115509075218677438118567021097";}i:80;a:2:{s:1:"p";s:39:"211126209972926688870595842369993071207";s:1:"g";s:39:"108563592364604435542369366145242235593";}i:81;a:2:{s:1:"p";s:39:"239692691796226521380036414431702787147";s:1:"g";s:39:"137476683692977742290483495678290382501";}i:82;a:2:{s:1:"p";s:39:"252311610716959305132008843115717379139";s:1:"g";s:39:"123328978402999139145213144352371439599";}i:83;a:2:{s:1:"p";s:39:"174047087138041833610836860678128035299";s:1:"g";s:39:"170009271577662203836398662496227735453";}i:84;a:2:{s:1:"p";s:39:"231348363522122086066280667498528389519";s:1:"g";s:39:"141093524922727559438821864373557385467";}i:85;a:2:{s:1:"p";s:39:"248864664933152526411279596376158030567";s:1:"g";s:39:"123889374381029290108579278155184768689";}i:86;a:2:{s:1:"p";s:39:"224462201405966083242230789750023192919";s:1:"g";s:39:"158021232799967127661274365236078929611";}i:87;a:2:{s:1:"p";s:39:"245879376734021512682830793285031923579";s:1:"g";s:39:"158046576746250718282268617313434731959";}i:88;a:2:{s:1:"p";s:39:"253637925905658982372489538655726599363";s:1:"g";s:39:"149864317488110155844324751701060009647";}i:89;a:2:{s:1:"p";s:39:"279412238023962995721371699198188829207";s:1:"g";s:39:"155598915764501153026223926768958705767";}i:90;a:2:{s:1:"p";s:39:"304106342193803880773594320966748339927";s:1:"g";s:38:"92322047090452031206421560601306928951";}i:91;a:2:{s:1:"p";s:39:"322913290480087002459462604003828469603";s:1:"g";s:38:"92524856578633519411437518532800131563";}i:92;a:2:{s:1:"p";s:39:"277089057388309352780642604697631788919";s:1:"g";s:39:"105249705735663037159358894119941901753";}i:93;a:2:{s:1:"p";s:39:"280236513995939039844557210758532708147";s:1:"g";s:39:"158306374689206241016162477506012836773";}i:94;a:2:{s:1:"p";s:39:"234719020513353193747658715815920552619";s:1:"g";s:38:"91223745999232718078741004083061517243";}i:95;a:2:{s:1:"p";s:39:"209990000707927251175406243525264022623";s:1:"g";s:39:"125642114179469428756488157507005128403";}i:96;a:2:{s:1:"p";s:39:"275737100760368939576948745650805280043";s:1:"g";s:39:"167145628416726604176821531341460996895";}i:97;a:2:{s:1:"p";s:39:"213783951740539117048794197148144657227";s:1:"g";s:39:"109417094981752227864776346864591549789";}i:98;a:2:{s:1:"p";s:39:"318677936852074604097023986317860558759";s:1:"g";s:39:"115037656438911641363193487524231340943";}i:99;a:2:{s:1:"p";s:39:"222750162478363691468158822602615735239";s:1:"g";s:39:"113556306002604103800443505592028066063";}i:100;a:2:{s:1:"p";s:39:"239051669069722927531642869778838542343";s:1:"g";s:39:"159620246209558910663028687970469241585";}i:101;a:2:{s:1:"p";s:39:"308867039809658627190349828399950839963";s:1:"g";s:39:"111777033404344242825393328519333723859";}i:102;a:2:{s:1:"p";s:39:"191578329058918619482978110290472855563";s:1:"g";s:38:"96920536616578690169019365830583899443";}i:103;a:2:{s:1:"p";s:39:"325447228570210752496684536118034998379";s:1:"g";s:39:"129437827816980982882065741607934187687";}i:104;a:2:{s:1:"p";s:39:"199496827021205922362423961503975322443";s:1:"g";s:38:"95449372423705665601914584672984436985";}i:105;a:2:{s:1:"p";s:39:"238204010443217252139505257991989127187";s:1:"g";s:38:"91317591567351091929487842436160672987";}i:106;a:2:{s:1:"p";s:39:"210575582741342359714046308724434638407";s:1:"g";s:39:"142543190721741958237717199151161265865";}i:107;a:2:{s:1:"p";s:39:"193835921830776847504350847922101912943";s:1:"g";s:39:"151813485796154943234684032504099327579";}i:108;a:2:{s:1:"p";s:39:"178427490906676735864591330886670926819";s:1:"g";s:39:"146413567376325921761866049795179195397";}i:109;a:2:{s:1:"p";s:39:"299716072306325255352875980371073738499";s:1:"g";s:39:"157210887501582163921135958059988460769";}i:110;a:2:{s:1:"p";s:39:"174501134484857074197927837838115864819";s:1:"g";s:39:"146752211101339794211955770327266075471";}i:111;a:2:{s:1:"p";s:39:"263141644198405815082265954631245057027";s:1:"g";s:38:"89010976094266637055743371326639574349";}i:112;a:2:{s:1:"p";s:39:"176466451619066725947852784079425521863";s:1:"g";s:39:"152509734985991674456496918102451358687";}i:113;a:2:{s:1:"p";s:39:"292682206572230534435344520034906633599";s:1:"g";s:39:"142874105165878163065284219612333009551";}i:114;a:2:{s:1:"p";s:39:"201328074386089494127672485138355071347";s:1:"g";s:39:"139056812479572385637122227340971141837";}i:115;a:2:{s:1:"p";s:39:"229826790296235981066004577347766874047";s:1:"g";s:39:"124485556392824999787963979933226961505";}i:116;a:2:{s:1:"p";s:39:"332795007680636342427162437048877824483";s:1:"g";s:39:"132371062218285402701784934167045475545";}i:117;a:2:{s:1:"p";s:39:"264128365565511611517695773592609678303";s:1:"g";s:39:"114615254022882630385756450073964824147";}i:118;a:2:{s:1:"p";s:39:"268698717748706869710939835298615927267";s:1:"g";s:39:"117152896705025823674979508347665141611";}i:119;a:2:{s:1:"p";s:39:"302105198709942553044124021979667091103";s:1:"g";s:39:"115210049253772003791162765412858545515";}i:120;a:2:{s:1:"p";s:39:"244101232788334692748605391991798485199";s:1:"g";s:39:"106653638158862023536690078428324579011";}i:121;a:2:{s:1:"p";s:39:"230273108057481536883566583583109559023";s:1:"g";s:39:"100481439316995264801026403022097167371";}i:122;a:2:{s:1:"p";s:39:"322984349144126882101119659857800338459";s:1:"g";s:39:"159007973907722446137944813244793447289";}i:123;a:2:{s:1:"p";s:39:"336551506278300215412128472087071431523";s:1:"g";s:38:"94575518869614444784555444648323179985";}i:124;a:2:{s:1:"p";s:39:"325853084786159562250150213907913293147";s:1:"g";s:39:"165854802536055673479990720116207791091";}i:125;a:2:{s:1:"p";s:39:"267169176591038828428461564163619391419";s:1:"g";s:39:"156305369077672218039563577497885459563";}i:126;a:2:{s:1:"p";s:39:"239647394471266396711562577661521640079";s:1:"g";s:39:"135150945658333061448039765686757664557";}i:127;a:2:{s:1:"p";s:39:"310272220468352202006936575621174675363";s:1:"g";s:39:"149183267477594191196034583076725103145";}i:128;a:2:{s:1:"p";s:39:"282045133469485047888914986480632943019";s:1:"g";s:39:"125711764274064417833132422105222333643";}i:129;a:2:{s:1:"p";s:39:"234599771405208353221227496890421334027";s:1:"g";s:39:"114241200628618711658613583227486232613";}i:130;a:2:{s:1:"p";s:39:"228152795513450511034942449472495573367";s:1:"g";s:39:"168398706283838543234401695778589281927";}i:131;a:2:{s:1:"p";s:39:"212097593073542307065347538486191261919";s:1:"g";s:39:"149940368580113076918890078852679018041";}i:132;a:2:{s:1:"p";s:39:"297412983264745482861745631486523413147";s:1:"g";s:39:"125354297262324596636132561377813415813";}i:133;a:2:{s:1:"p";s:39:"294153649598454137023569177048904340663";s:1:"g";s:39:"119618232671986101725255082853317991993";}i:134;a:2:{s:1:"p";s:39:"175487816341984471056566550210858970703";s:1:"g";s:39:"140601690952468213621103178853863520569";}i:135;a:2:{s:1:"p";s:39:"176180359739294489581394694681108500843";s:1:"g";s:38:"98077114592993318593790787139676895321";}i:136;a:2:{s:1:"p";s:39:"279572267891227674183294094072204319543";s:1:"g";s:39:"141474017873114223498048340610357082035";}i:137;a:2:{s:1:"p";s:39:"239629442130765299778978223853239788839";s:1:"g";s:38:"88754684643523546470289505769224285729";}i:138;a:2:{s:1:"p";s:39:"311261240312331479969447936407219323047";s:1:"g";s:39:"151343131310288676643199151763364576911";}i:139;a:2:{s:1:"p";s:39:"273396005392900911093204799067494731419";s:1:"g";s:39:"106778038879588069377890944288814468931";}i:140;a:2:{s:1:"p";s:39:"261721287666608603538123341686220061467";s:1:"g";s:39:"138711968008728462202723866189802040861";}i:141;a:2:{s:1:"p";s:39:"215937395349495995166858415892962367759";s:1:"g";s:39:"155398583112088458001793075753882872685";}i:142;a:2:{s:1:"p";s:39:"212936571128682845071308878878059010067";s:1:"g";s:39:"101442737521645273653232103903447910079";}i:143;a:2:{s:1:"p";s:39:"298838175786452844147867416306769452987";s:1:"g";s:39:"160565315644879191178274475105507742033";}i:144;a:2:{s:1:"p";s:39:"316176852999320912845222134672775131119";s:1:"g";s:38:"87523304206694080898971766076264143747";}i:145;a:2:{s:1:"p";s:39:"202013126308834551658071627160007872163";s:1:"g";s:38:"91110917788528883796996360661218204029";}i:146;a:2:{s:1:"p";s:39:"310457373590695815028028265615601682987";s:1:"g";s:39:"164392575017790858253925716306682762491";}i:147;a:2:{s:1:"p";s:39:"233494437113899933858624559487545643707";s:1:"g";s:39:"147087009669715116027793726225269012183";}i:148;a:2:{s:1:"p";s:39:"175158366760549586270815259855245814027";s:1:"g";s:39:"137880202528675896604634215375162273381";}i:149;a:2:{s:1:"p";s:39:"200440310559660779805280958200078988363";s:1:"g";s:39:"142805624090912627846213953550472112815";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/1536.dhp b/Vendor/phpRPC/dhparams/1536.dhp new file mode 100644 index 00000000..38ba4148 --- /dev/null +++ b/Vendor/phpRPC/dhparams/1536.dhp @@ -0,0 +1 @@ +a:30:{i:0;a:2:{s:1:"p";s:463:"1484321112960587045156307044653452978091514252781732555377115872744370782753532223710520596651771862094580430622810781137079954026654443009773353316487869110581614335387257791372300366363986959520162727301094381504710539122423215449953773749566665075390663795515064927524541364929410161593571002665960511042368404720007227185351442857133729332461681414076545413251514012799785726764386304857603161524569772320497781834398411353556378812114248426854017223765792447";s:1:"g";s:462:"635774037287666756005286201992926844882049694229071109060527214859683349345634244908520777317972311779819169417124227454944478231493944538362566784762524159848118679198133615209134587519203999139059358147991164119330583496102138414754471736404205776201609984433151539366053179678590829297151308903314368108491194375955538280261511309639674764255718253005505707839857874962943779665415343296052187866967481027372096404738753403721555758189272826817559193637462120";}i:1;a:2:{s:1:"p";s:463:"1319436802072744870627529725982335407106255106838769259080484192948822006093801447135658971621913672383780818570900869846109477900474351617379125755158877287287443914503331845436479622427887788221295041360592939442869830231851542580082543738933690647798111929121232075109013051084277527846507106765265691741993543124300304586965031520186535035306131873674243292213566694074549356897012038902793605597813873772107032094774604447038888760851123996389333697066500089";s:1:"g";s:463:"1094948501651870927866408997875807332362132368280764746635102906522376980935616408160803921204390676267735235340675683774918584046129467358536658452112779035005246945500990564970828900915876183847784477372105600610181992912866134280979202520819598729274804910027149270482786962118597828865094775152221808068814764597063219931910461862798242682996856821691502783024562237507266046103319637879315130332069878279043189748255613212869917119499585630902196048518389141";}i:2;a:2:{s:1:"p";s:463:"1640222121300873590885740903711612856053216234718072467371799710030209040805232294429104366467106949818620126839460635110688960840211274066511897330827987110967763711157204318410155927749323139656115284192624456851102305115967064988358305606231181648345630705027165974291804661428533435957993527621517312013100947564241032286994712995946793397929587066127500563005307122895245755325339947878136458621529441597532795180908459053645027157995663081045092178737236951";s:1:"g";s:463:"1091699155014785793699927849492118315207217763778609939374849137247626111244977609635966506015908867479947153952351409289738203198557207594461117445750302094758880324908956395448076571856589921995881773374725119459511313687786646810555589375887009649909789659937861969554238484131951359065310736811264948846669566484058857698917573131819117850621387652382598432460267007035050505884971612126049437914803225531487958278531161911691953811685277239553704185614100254";}i:3;a:2:{s:1:"p";s:463:"2042201993843598159468568251727021381151204860153180105899105583856572114957522535810934397491695695827381512620409599315961608902985092050021488412358853723928122649403442200573138328100885455439417892396869322127744220101094644670053440714135390977909178803486242950685670919693087337352955059110458693240470974292348857021512713811450682539944478562513964203257401079664973633503395515416018593081165879055440039280270143172237165005252136496925734559160180063";s:1:"g";s:463:"1500442284667586192076348842045301367167296162953592222959388230854684580797148712288866802146615945078966804943095812267797017849054865779802801614224624014374538152627740263805739007646764205976963263146061122561909911419750642286362084298710720418238017005026967541716370169549583274076872905500601850314761635440475203807971054187862037414097487067989205898779614632989928913601024677346758843158175861275923151746018118718105464617356557647207655221747328074";}i:4;a:2:{s:1:"p";s:463:"1637153014024763059444878705223203780681858093138911571751979728838657707993054069819608775778753857062986551340167861371895956608008303443247254570296681365466843835598991865198789305509785381105738587250553832156097575877088631555130354903285869176634617910439198251693833897364578795592212671604970740451504483168483241814403323016500573560687048758004696815940230413780398956047311381874244761196793125330727878608765576917373701666692053785475387091211014381";s:1:"g";s:462:"253146196079304316266434733768872749372301038198365665590883109674350222564840862236916235404732761220504241323463873735246003784699325498867656640778717821729675220766842521488720124623809011690475912948904742512957103216664404537195645503873467006909218174832003149223675383918994291709588651481979088751673955939897523459289418812245730766260986806015360755507568343631994201583412347069821756072284985530614961162489684943738005917848451625837740216654238218";}i:5;a:2:{s:1:"p";s:463:"1219739395129421980986817581093875899847343408305888101989901813253982523812274106436433323689615865668476392367734814970480804904428414841429633998030501300762701392560716063753422306285174523408337113228268818879405961220480195573703497617321463271891741904278861642257906422159298231098658985526457662170038010292931860549511504497994128931079950747868651823087004354747165956919277426382129565650723679401668983210698395935172256570765605609849286691377452069";s:1:"g";s:462:"170749392644970811287030749108243672722681483625922470846523134882486580425232339780276174257909030458715830716692588702557598044687908844893420066097048011582288383239010520033914489804041483203577102579487035826567669554277956785062140672417410620876815360564263566630149415924467405717903800222598776815469568149017143892771598944636450610659476217733997741232959262233276018211413849373069396149673782042636144584577674185171593340362723828343131348119216530";}i:6;a:2:{s:1:"p";s:463:"1823795465713565701278315869400723495457475261130852713977770426795435140015065407392713025910005837170602206359208592843713477109036614911956946724377495049413103985503099433241790626512151502197550302263168341159195533492294383405632570116732818018836333704092194728943213064115454736812855110357810165024286142395540987558177053133376862609281101196043894433574854253390690930850852001602168837076660408735360137300780178764720747999733920473649502672753029133";s:1:"g";s:463:"1442839829947671234369496200676072588081612459677607985530300351859499357749262146238588298044263018187404783155947200807580123587074809026438733937831837276863552797962633391437862262487983073076526197006774206392599749277196760629805690702748736444555470229978387347874033267703600471989608673950742255064321002547976555706582185670106509022326628674460174579619942903604626192360640005219137811717889441546118271454105656302351748483598142884252491906462551344";}i:7;a:2:{s:1:"p";s:463:"2330987243466161089189453913980054878244548203271516593454871586865008572865835925509538466874454336703982083570636604988092181165159923670888163875699666429239768275554084525673152372358619029724159564367314059390020704727416486501641650913127442368735560126459032806262580912363799758293882503234653435264501039310901361922396293916077012477020084343090921096158915280800532439667442662661436491373212982496729726298927418474654567058464055252208378074662306911";s:1:"g";s:462:"386680618508384973423672062850508522397135947113284374965100744322646472653484962944409055998358573494424314461090206662182780860368561763485570382561152186069945568506098043823478071525306398614029486640941099890329530883797789468233801063149372300345673355594678489190792290553970578096255571413645141468699974372196819473802551597223213318243705334542362861643744710123296535080834831744256642683094762389663106543125584931608216839951706680087663895979524043";}i:8;a:2:{s:1:"p";s:463:"1262620669861477839190844459069625161157458691447808343984704184159371136895931239924491606146944991489400086233879378957339498118133191256004545753457451547013077389884363597994672087814969621667075874313137230455646979150907696693252095577556652543710779314562280787859056548289029664793556128094449637512640549596088042279135346001711726938677020098004905539793932511494769831294545941118419853855421666428039455145569228072097189891576088267457892585617327537";s:1:"g";s:462:"526663796116646673994851998981201669178713058539445963858436667089710552476905374236164705691170375947481081607610541303274006827378957464313549841097789508218946402515689199903038313446510101310473849351954858966871650717674123149287955406174093369789719324626912240862929635523839987379204148425806480078269046549263204392631011143098816027493919238398815279095074992826115644273740497748876160953621171789407359553722390062142143510560327171403556962711579228";}i:9;a:2:{s:1:"p";s:463:"1802806247618212052847139445190286650067259060192535756510698193625342451183591635366213416695234519378646880682633767718314783369603831326194387419926531041225952412795286571196321300818787263025582858179591437678991886851088704122896117267126236018088255041959547292291014433680944304432469776645236818313507336442478521079624340532244747798364495759367518444452373370920933200025543833730541849004863942871483124484895889874086358389451367377636915283155601279";s:1:"g";s:463:"1284641594416543525662036145628946288335762230298381205343844315244784563257207376136770309765261982199619179919538857693102793738277562060812035117250208559853314039706519792948991125592723028835849628618414032901893842763449637332613735729524022145278901762445067158581783058804762286976909689060845327084055603617159850945703843763012315352891860697254579455882005066597307381839438396573376674188203126522446102248606816032797012113930789171978183813977343611";}i:10;a:2:{s:1:"p";s:463:"1582811987242397018030371731694457345235827088681427679697116889089464714688234072738746320838265451104885880125066461941990856320096604611671565283402794876779139028522997427206721007041029858890516120432680771700972923994634541796145230018505355925572838476051871410554406298275632980176315170349424989011480109942413662675414441427096441297934858425355818410353360190492203797797818306162889687552448049037239909742012439530936824490474509059846737144151122589";s:1:"g";s:462:"904005487385713022379621349592992471612880301537581879253733082184761289667473824498027399895869972592947693035054381286316769789684527733801483110012752797833748591601744372689718751357647506175043276817062912956835261917728246198019654354323587119778378183866021920352464303862458402855590059151030218669892369596629436855331014343306882939528512800958166479957444885999360235000004595914301695408522151397314039624683984435249704259386328592373210860823431745";}i:11;a:2:{s:1:"p";s:463:"1751567140177216355913464714923925382303386077987286661087016520920361085694926448713658621586777889815549014628902654175565156184204401359255645222938554308180406673877599066706797648397605589808600115965605825074379462812206558724269393890032645033281680588349893461463965184465169874061908663284055226215854545962327006625887546931982197079318292414797922218674375886474872777173052121315637184932090274167091399081333368914449195411820479987084002907490075763";s:1:"g";s:463:"1728933896829190229135447673930534573193230270896317083457020113596793657167810111090059614779411353579891050636265959009334790354242367021222694211284484143733427402392439443059568114957827430341392137236643159465739007046315676182953770441979720779755837087984309128307509317093013153746661996696823485906207481328520018097291489862365101433457635101786564648836715943624165952560449579601292473841876104693571448114740692851519203213185026138219553941381566465";}i:12;a:2:{s:1:"p";s:463:"2151630423012647537844703576294810579565336708199678266911187790505880932879424817434691270964383838946482745460110687378195032802933406049645640068316727857023948732325344487226996291312649936737107355368206848804098606231594113432864566561818799062515941354699429199159774308376691772761126331126068157104422783733539530755190226719384389650570576991103463111113686035442716666605835661122272855402177927187769060522635806443701402511727404912236646468773112033";s:1:"g";s:463:"2121000333525367470091854954993095574153670551827036751868266597572256874667759117352446133965472453043969463344538546533166991278117936837955676339645546669209260506924224811209384588096653947044134595805874397580120514968802999183663119396415206905026521518610277469511452527761346355780035751949172413793085089893406122320590054677391074249022019433205414681586553029386620571667778599880374927413315499007958756221913701138872501077944472074702822713887024468";}i:13;a:2:{s:1:"p";s:463:"2205070084150365578520443567286113338063494441182286711879349386447420617550082998305163124583124659968411565696253507239750319335503844156433325217320099646707812531275013377115385880286002737298380907436927575080574058027459561347795249533536110306336676674626272337164368057238635634936325623385295555008743962525297432660594530824633717776372520550493992724995773138869871133949848960548326013413861077038851781317075929760883962338374431825689935375843218653";s:1:"g";s:463:"2164986491453150181997307394732315140614298464027330379977238121790004601675170871987978031576748094029228652746235016225704766983618671573830403937213847957627426849730795717992909097124266785777500451244045698059566929616174668460223079201751303173880459434689685322490463699023678343346462747706418014566753958287780845925077591239643442031042118280194530297714211983675755199763003168178308438929299250986345700682377534935196768002884135000786173463676024879";}i:14;a:2:{s:1:"p";s:463:"1521251664255354648387650579429147645003851430901308819073432965199333067089633939765298667366222286385404882515876653909529252398129005889801425507724811977996173982929147187904902391198280960871297119665598540835597034200064446205943817755106610845073388515419027205081211825491636302401445316595226697481153192188703355175647181368777041455082796264978831047550011469827974208535580950629540118699486070742792447196201207794623773356284583460065990997086238511";s:1:"g";s:462:"965193605452145797059670328874441819155298622619297053175552499937680640644666445940944882855932307148639941581084597423672394906108044956969878533384135603691286438773265879206361085382287378400275018398045193374212541331042637252930194708676430354898774667565187596063250380298789522845687589570438674857628002717877707884455323523299181393442629310322092655889918930430566295027767644067297428030033271832881357044821777678830457933953075655243142288927175592";}i:15;a:2:{s:1:"p";s:463:"2359088529688849695976172882354276186572333793676129238480483310356338119512834416470889516824103143013456265231779354325107949482185103514573493123174776224113354923823459005285100692068081219492746850787514937711005894611615247331157020496376924834185574122667041507752735016917771570908300383091007334114696800556196459897399050681446783294994048701546990851161672721128777031448669634022236634171162072443925053239893879803599386757951784662290977479728876099";s:1:"g";s:462:"531712821169676924995279008450573863171422718303644923801999592407585710289327315712811203262677550193268920385621678284963439199695456438890216930330152156118253891030820312933931857809080143365111231914817537856093519081740430912993465432826979612678871678391441229601885573783843423731588207120032647787887396014960941864835572694180911866701771212825132326338693544497332820354308355809281971835819585009137470469515712697555045631883330889364226786485235267";}i:16;a:2:{s:1:"p";s:463:"2263415250426790488990021998541593923985939453932066947986968571160941622802612177769141891039473489070175302867802751596946353154172125528234191468643981304299429091395959809710836541720420021923806062020453686237371369098960991935904732896776305367149806546520869591216966307337101655332797619207182444936519569732492987788087886323058898445366441139143155332695122745405143154390717222686607255170420221316368625610824961565878490680157211889540793859511314029";s:1:"g";s:463:"1592300040248123484343304872412609674278233000042429776065779160677830870546995470357954916165832640025797321967048755775627713204352714564717585266051163773689777402235485084734939182825652015026616241954245365070589307618851173791011445842933302480677887284019554610611546717089545421534402349743077171151964768597699449831915488170530900787436161510470323524667270065908642393725707849007244393660272712704257485664362080753091384435793689644134869046685439697";}i:17;a:2:{s:1:"p";s:463:"2140021758751023276840079207042484968828483938990224910948092870606013654041680930240672408316776269908489537157093230523921913791933713307571209743090663930053524182963000614494056181878721267909181559101467357866435493815183307483633613451238642152941855619490861935672760757676221198639329013244377526408249320935076623838134966951658604802937666471551992167087938734246741266040666007877163204679608400933144213094457105599599278002366948889603083533991484951";s:1:"g";s:463:"1100233131056620948296063080261400071657894915014156851614190078061725775652724042802252052520540922949797249690960522349654067595799262331593777556819278792085357168985669988636673921131639681240048032250759952721270517316659925423462247942806786822053233647319893585509026604836599081906066169311006342005206909012755218672694523070884738297514453530775609726869693934264786610643627147185023994300750387486846804192790799167713142235625081920945676492185259837";}i:18;a:2:{s:1:"p";s:463:"1551038949501222691978272893261175182106190568814977369412264479269203984617935284649271672983221996009702717185850835368097716239680362427876850240608711832907992991904207080846078476339794107796679682792702952426396050690103152939322069717802959355097917068461854377217432372587859666863879175341220281173708131767332774632477155184400678077766817498132455212226304905057355970071577431782390842748315762830917398894909591248369951918144444569327038256791412189";s:1:"g";s:463:"1122743139630282153879868251492800292369119837055724070863937958954275141004659287445630535750518696420133153588928570581644864109649651087502307048496388930886123022314248669533791822102495449596897585018024718364807118889886919617488854825417330211828450024519870873403366339898166468075791590348995064663082411049461483459672090493049746342023873181820458364596806245316113771672923399540575780554223789112003339156911840140412416044701352663673472942552084352";}i:19;a:2:{s:1:"p";s:463:"1356275386127542659017850102084213162793783886645454180765334717833233223399711893326242349980495053147731601929882665213599239957578370346016474113462672990475517633062742504791277452523124568556338228152297085410743499668547067578837155876739204833738979418284421167514815201003427454456488029773197444587939264563226841204796270250197007137759631209198185435416640354634993592234914740333637656688867749691551325073441320772525747422461099343214212606226782837";s:1:"g";s:462:"196158088095289507282635289372105179799925532380890601501328888911791240059921911676135260880026187732965333332154750913555772522540516226362849912153957919289972463443703634672828466780953764986723451520741685547186167518702308476173818830280887990050604198896217462931059031114540897431967632771864183496847755209674316498138796078477827464190973060848610335479452576965859000719469049864951119151409590349552233657722495217934957865156668731479214259056401619";}i:20;a:2:{s:1:"p";s:463:"1791472286915428465800935822692265439238355517646096021981341373610022332512685662672947071726756151791966985572565143427965511257073988222706151587711707922926145814850587537844646412281461515307166194779513849936528281689522221763047607949743506742487857989673563402712460260035284340298722075617413469890846240032571221443912374997991636958525327747208883933428540123519800669703170185597472417427612584127771897699916422137284895495208176450975703263813324361";s:1:"g";s:462:"812472889838316626876044476525910659797355846637807902006476703903476420879104141089450116597850471591854168698938145448631879864081920890692042259147592692842192344636910396472895957516670523402513152790835262569312900065055814220909837365727450527054620162030353510549825571076047117901301818937913974245991960708251362745962177597540916436370662595856237213188011429189642229756130467882589450794829062521138060916740805890466164921142302272783761185243603093";}i:21;a:2:{s:1:"p";s:463:"1366833399447889457775990207973615802619259554875634153621347812296968814287533898166660206284964915570047939236738102337370803059310419972815705036689363773719211310818018266452632959459163662445386701608870658012250012908275516846937941749608216814626236706133229312021626209945109912604144285299956864973471892748876868743616995712656203256727782738514688441353283479027877383331448042965099734616412228147115211289999408629682850400139227689027478749749643129";s:1:"g";s:462:"907557415940991513285090149273768674738060366453456203997124609929673130784634611327985434585529146305092377176336004581435837526756015176571782139094736301097343760037832143538056782557460948471665233952196990668005720646728143894341643654773015046788101057446846122595778433416647442456793837598177060389929898700066416155469357326609097459960392457609590714208063472803992682255477495194457805322420281681213623504075777095465460597665129371748683785603721006";}i:22;a:2:{s:1:"p";s:463:"2235728210829391857071877580387511359891390738738547942772210596588328209288888619866661081922620605650811252760893976945841607232634557684199493942964002252162424504613619431329645308417700225310454244837374950644090517139907683618729560064949837356919805580405898545089057377346475412311999128342123657940599847558896191574146322896441284187120358475517988223178353246518708051100480174846708707357073697915628723229994725004763047252056120943361187825791150229";s:1:"g";s:462:"637312041409355177411974853221109947515744101798389146528774548932214498916777092630192887092630101160548857054003728871186609001785761461978704016797748424302136028903368917925007154954833444321746626415766303651171977419175936950344617277881927411604172961404838392604376361557623813071848677171881812344396160401179223323005436600038362498640753349274380695107444847658991166255571478370115034110598577092991547493707110073804159767315333427952395510117923986";}i:23;a:2:{s:1:"p";s:463:"1230402277951024128207424741876734394235328971165405947947309299701490787264435301233695030361940893216739801304221858099834185444907555321212424523500469201287869965553274789652940874658275644861206255728959954319026799091669216522927588979607033270355519456618530483628821237748037726704478448642599776349590126053959737752737091372398004324976961760898043643776494456825641032767428880516321734928192412624057914470785381494106990379306675385876696847389286223";s:1:"g";s:462:"338337574239177317877461820340406296118689570674139174934980557907797512993831045015071764512723465929820824827380230251055682801255297225194129788221954886452049216535615519736643436909474283900148561820437578555501524700402534304860476771494314549265082281559541403101063023463350081318114948129018156823637901049100325822416263781450628275355097055535634266452391214951018991141462795558102155975109587453970354234061405806819338677858746939660250096487381222";}i:24;a:2:{s:1:"p";s:463:"1911767397217174389580635454501278451662399330679149216825063753986107516887627348972329152716670344012835523361399914204681188251842967025811126913965113226481849273439748670394027983781685504896105459795325034776516327708392082217034648247322633497779699909897101710745541317469488983418685560845904692510588194960780198750170837577339091255717698429947336017783990981810701228856804637301843263146401004874083727217362581520156327048282377140355341630648456103";s:1:"g";s:463:"1268080483672427216958224975801292383587547866099684747810305400482861740550272965009363034958263517021319762496237599899200861869592948185998662594716738084240326115111554194231937679759491622552543609081009157285370194938894887072173502498902751488787514342330471293536467270061388282245612044342368852132279034623689831591544404552563026490733134267915461931000181987531966569228462873362813573826868674356654050782457393475684373296479964951832380516920006289";}i:25;a:2:{s:1:"p";s:463:"2384935185013046067220035179863998606999812912034904502807061575246271675961542850429667517360449796538685788629608299911037304799677705521562064126448310662928476680131793925576111182979091807631918029238440547258773202993568005355415069181820061179910375968834527608205575122828826565040222250604808188617658493902058160064391648525420926805258250520000765029746606323909864960353779235018441612552606347709443678131979120380997560640005810607751789857065091451";s:1:"g";s:462:"230062907685243780452883658835151462600168821285212753199061160240952213288476497310814110927786162764424336746127033997732663996065843294573577068538063140935014911132098778420167116292666336310665075633034800774149967367198046709558691946018417849690027139977567315959230391862191299426094157615629906301773814641864682077331169324528132423969523713789011223825672691018959906797878940942325987433373308932869795904147206530299908785287056288995547797933032443";}i:26;a:2:{s:1:"p";s:463:"1663344306655279209292925933415166673010218801912608607453659111186281765127963906747334142803861207045175907185341633566803131965665187241347507240355184503320145325035527549916946203208831099788683360925692343298292440438383759779170710699485403197390947453941054427159513193680633041344238030245452902236794214288355312770188493677390972819610775968168652115902497717012047496016490638636145149167033047041445335801731491846790475339025877805955311338540934627";s:1:"g";s:463:"1348517767365160364561068532904450579389328908173180354117747600022821268147921395670753439266957892637547548008485068735206283651393859868620973098249719756384276748664816488024695266868296400105329740343009341872599721665814103616635578948648432158793708382891711073045093444826262905305696088996707838189289814208503263563885857974203581050042104854142464557342916467428964426721186094462371984492943151324037650392852237078007527006264829593973374800503511630";}i:27;a:2:{s:1:"p";s:463:"1848896919173844897115484621965301937359468417329851937907613498405516616011344671755604661971819633223199683969701205993540557973998057014209439444926623445981416341404885878413044311920287373049322289489438247126578629730258903184306797687934935350338100288227740150503007566329840870600743965247269417726969943195718972903432914079036061575699149971862372213649397422747198211710272236417380710992790034751870619005138531869354200728018277815675987411571131107";s:1:"g";s:462:"429289696470275857775530951197073972688947870516364972269559535627701213069259530612419679756895227063669544280791154240670740796327818039237257228266226324946015459066054920164656517497021576366860242621801116329987278409508133315146909097111808932821633739861288491142391412283558567587612085914476484689127470974041956005153680024608674762079992623386827477985783098347117926214711810179658634316931882010723029050458260674735096275563410284828547714615788587";}i:28;a:2:{s:1:"p";s:463:"1890627014913175910326850340749681958428380980658681063341993939499758659173497200321459369998720011914355660203102403990377765814366385664710421582183545804000705271168997410589122642202301568560127610873466167697468942968722497122944122708091225065758185048845958631514107208078217188714984825957124996155345718832704656526384220047044919842429499771982984326066654442486078088122441757917824305647778599411466539066279681960968021776697929069992812086995172789";s:1:"g";s:463:"1034169370222927208782825986578728083410858536450578282698009964268185939867622641861765948506913540342157742240963716977855562177703039976409349173614991743536434594022269319553704422130919086785254310146515389889792593033954067278811337387826083570183292948307563695335501352996895214719576396591180371565611649224388919323192934331934511203267468141351305137769380687345028766066767615175846034605155402960198555165557055819821481579985055010194120972583631597";}i:29;a:2:{s:1:"p";s:463:"1353376715698694849416351054567317097442253008810215280534973591952340453592336519345747889023649593465096755863361196728613726954884457107103432300908272357398779044553771760203942803845422237037780075398705912790942805326030680104878331383092211642487952263739901176183050028520343734351006071449564249238382691445895174993577066686591254578612760844748234214169371540250401278015897965301864679606231139850512645245671839049032702402176156740309810593611782337";s:1:"g";s:462:"305210523129475840536236800901702737664215769845725796264865453089967287991947101293919245527199033267819594245571745616219504679083065675697898466435089350029442525196013314642200460699909921210419450041030462063057375054885732135352452147932369599618025917306836513163880414992131359626837644091776191785661118303776333488611066656526575787363225807387004783769682322145335656768853220570786204450747084576926149782903428402575178991488369822354375043423248544";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/160.dhp b/Vendor/phpRPC/dhparams/160.dhp new file mode 100644 index 00000000..b038571d --- /dev/null +++ b/Vendor/phpRPC/dhparams/160.dhp @@ -0,0 +1 @@ +a:100:{i:0;a:2:{s:1:"p";s:49:"1305369760393067573903784608000086685092429430939";s:1:"g";s:48:"474563639061072388724737904946142937816029120423";}i:1;a:2:{s:1:"p";s:49:"1144635340808941051501659871557102316521726101183";s:1:"g";s:48:"619759652154730913011023153136163766014870982079";}i:2;a:2:{s:1:"p";s:48:"988955281135516012494592134176727394285740835259";s:1:"g";s:48:"661721534235998300528018590812024177782995358121";}i:3;a:2:{s:1:"p";s:48:"831054466535764214539847067184849497020622445943";s:1:"g";s:48:"602568635360210647114201968475098190709943951119";}i:4;a:2:{s:1:"p";s:49:"1273451162499824010415840310357006535387759756083";s:1:"g";s:48:"388940627425287673610018679790118209342077054037";}i:5;a:2:{s:1:"p";s:49:"1194158228146097682568743682506593014684819848887";s:1:"g";s:48:"580787644966973602366617775052430689914269385029";}i:6;a:2:{s:1:"p";s:49:"1250825835634860199205277909400801107314922391847";s:1:"g";s:48:"581587982876966650518121867963233577479897748201";}i:7;a:2:{s:1:"p";s:49:"1133337270744463694484988529020735933451408606039";s:1:"g";s:48:"631442441351111432384530483916287036387111747321";}i:8;a:2:{s:1:"p";s:48:"804221707628161205330927629041516333589063181087";s:1:"g";s:48:"631006589253137060927543237371342862321104607941";}i:9;a:2:{s:1:"p";s:49:"1002191724199846857337324294157355803232206888867";s:1:"g";s:48:"483655550172758115887335144054596363427233334927";}i:10;a:2:{s:1:"p";s:49:"1394184516879107196137044604429830692800149361183";s:1:"g";s:48:"683437286820195951723981107586029551808106506279";}i:11;a:2:{s:1:"p";s:48:"961405043336466250012279555201953463057072208663";s:1:"g";s:48:"548079459627278793375356546007540397027073822501";}i:12;a:2:{s:1:"p";s:49:"1386832263378811893090905015568465530933732830547";s:1:"g";s:48:"604192202606404180885679845081675292033551734613";}i:13;a:2:{s:1:"p";s:48:"783786288502740985223534835310606558783982116919";s:1:"g";s:48:"500926370623902489501579323312356666918032852369";}i:14;a:2:{s:1:"p";s:48:"782621235048592548743271821187900290544473673119";s:1:"g";s:48:"596692264293782688278359189116397439489932369599";}i:15;a:2:{s:1:"p";s:49:"1367746360017583392658813834721766340000578997379";s:1:"g";s:48:"538797978419712469408715343382303371532760124217";}i:16;a:2:{s:1:"p";s:49:"1135354155681947332382326494639504774124357656419";s:1:"g";s:48:"602214275291935588667865684153452385069344891247";}i:17;a:2:{s:1:"p";s:48:"790833869591119782666903580768794672968217564203";s:1:"g";s:48:"584158672869014766593166474252578740731182247631";}i:18;a:2:{s:1:"p";s:49:"1097291211491744018366481025948305908720865493439";s:1:"g";s:48:"439509359160916576695841620747699133810064517915";}i:19;a:2:{s:1:"p";s:48:"918692550503510060358872429607147446953066891283";s:1:"g";s:48:"654945249942805992787768128395123781115962625817";}i:20;a:2:{s:1:"p";s:49:"1332092254872377835477605844037036203458943086819";s:1:"g";s:48:"423679953504051996511091129522726961838960898025";}i:21;a:2:{s:1:"p";s:48:"933877274777927890528040884397656631578329276887";s:1:"g";s:48:"608217136583914041823260551340788541238317810097";}i:22;a:2:{s:1:"p";s:48:"859725203063513692512603341846423987592762126743";s:1:"g";s:48:"440919501974522445512311709528159976986712491187";}i:23;a:2:{s:1:"p";s:48:"837664251768125986868150132183481466127924307047";s:1:"g";s:48:"555285975589793727593496223597124870607008893367";}i:24;a:2:{s:1:"p";s:49:"1327569384563655583886043185949541133884438458323";s:1:"g";s:48:"613130346337979086911714027415445562125235878865";}i:25;a:2:{s:1:"p";s:49:"1428411692032230775295758088618237721277667517983";s:1:"g";s:48:"535225122050760327826451080434600817792628009249";}i:26;a:2:{s:1:"p";s:49:"1223896787241177872573145930611964429377687205323";s:1:"g";s:48:"595494123131028191906314657449402679736765235803";}i:27;a:2:{s:1:"p";s:49:"1086048631695619847613317770068005258168656629899";s:1:"g";s:48:"572284264033707549413957863779727001669628388815";}i:28;a:2:{s:1:"p";s:48:"822022638232373521110350304334064578294406009867";s:1:"g";s:48:"657635385587761135663653068076150080262596376919";}i:29;a:2:{s:1:"p";s:48:"874932399873633702319139314690832967223336821143";s:1:"g";s:48:"599534542056608408276116956516745768064851371255";}i:30;a:2:{s:1:"p";s:48:"843427967333716318343697147670009659629329073039";s:1:"g";s:48:"535889566902096730048601747743521871868718255559";}i:31;a:2:{s:1:"p";s:49:"1024009511101153299776517092199472217626850026127";s:1:"g";s:48:"466596086730216509212034465709587270534916154537";}i:32;a:2:{s:1:"p";s:49:"1320980696430805902000359363849168914081628941619";s:1:"g";s:48:"610718039359114569724584449995403893298609474271";}i:33;a:2:{s:1:"p";s:49:"1092432640209269431497453399910526986961082646847";s:1:"g";s:48:"463049212539097020105319388432709824833485998251";}i:34;a:2:{s:1:"p";s:49:"1379609959417773161390936687752808731631732084783";s:1:"g";s:48:"523798400483215508398847538082598935117370208797";}i:35;a:2:{s:1:"p";s:48:"921078024075785201943929096178126751669361769839";s:1:"g";s:48:"490512063141551178776615087664624573070816149093";}i:36;a:2:{s:1:"p";s:48:"989183702275163955646438143208065558843002781563";s:1:"g";s:48:"634089170820543168467541507246098164427596903717";}i:37;a:2:{s:1:"p";s:49:"1275967997029234336396643206755914224132707033899";s:1:"g";s:48:"640788943520119214196146942744877589585775435683";}i:38;a:2:{s:1:"p";s:48:"931840992701647448146789164397900838241044885903";s:1:"g";s:48:"534315128594159356486413265871709172887173141369";}i:39;a:2:{s:1:"p";s:48:"942069618564062766077167557363733874684068976927";s:1:"g";s:48:"485898747279783894692037240129360297792095013363";}i:40;a:2:{s:1:"p";s:49:"1001789339197699052355670128971121065627297992007";s:1:"g";s:48:"595155718255698292695322354602201327756898470131";}i:41;a:2:{s:1:"p";s:49:"1375600571680089498740013276064864072342162854983";s:1:"g";s:48:"498415279224520972219426394139746930392949512579";}i:42;a:2:{s:1:"p";s:49:"1303779257813293468830624797057168306311850997203";s:1:"g";s:48:"403451059131446434613889922097963893429478142833";}i:43;a:2:{s:1:"p";s:48:"800005908639641965569689452284039674108265369227";s:1:"g";s:48:"402323816163796613170618111976343104099001279247";}i:44;a:2:{s:1:"p";s:48:"844583281698326903788926899664249893532888110447";s:1:"g";s:48:"517528430635008553688766531790077155586957536869";}i:45;a:2:{s:1:"p";s:49:"1094285529414095396966242208681559809227871496263";s:1:"g";s:48:"551358249287881329263799188692784095718943179907";}i:46;a:2:{s:1:"p";s:48:"983660711222388249045315062345897636170761443663";s:1:"g";s:48:"530552213889630252659015358537515844230369285207";}i:47;a:2:{s:1:"p";s:49:"1351013775227766136479340311908217998210575835363";s:1:"g";s:48:"610369552440185821513978440751416631043249970137";}i:48;a:2:{s:1:"p";s:49:"1354563829742534304843697230885200452462665538439";s:1:"g";s:48:"406800662086513110930754334679064364192661267367";}i:49;a:2:{s:1:"p";s:49:"1398563347597624601077663460163417305420541555143";s:1:"g";s:48:"619655395370666441364849115839740936961386486543";}i:50;a:2:{s:1:"p";s:49:"1387517700339083788987800628137655557973366876907";s:1:"g";s:48:"538444384733151203412364008770185341348899980491";}i:51;a:2:{s:1:"p";s:48:"846173836479196853651659824753744331267546831199";s:1:"g";s:48:"650935589280629646805939830602148789608779985997";}i:52;a:2:{s:1:"p";s:48:"798285016588165120883258650093433041877186987219";s:1:"g";s:48:"441529709876893173588604889016439199867969459331";}i:53;a:2:{s:1:"p";s:48:"809397346401439086740185140566814806808684379967";s:1:"g";s:48:"538236957911425614153489245348547397710621101513";}i:54;a:2:{s:1:"p";s:48:"809952999200455191901540837089805778142345835223";s:1:"g";s:48:"487385441754309571397412911571477016204651475301";}i:55;a:2:{s:1:"p";s:49:"1237709265001243211076717714981240635777036971019";s:1:"g";s:48:"618784272482379871992008983619376563093070592813";}i:56;a:2:{s:1:"p";s:49:"1025700231883796313398360726901170861727266024483";s:1:"g";s:48:"598151296213247324217168913027595200303295217225";}i:57;a:2:{s:1:"p";s:48:"793327128551442023767444463890995300870522218687";s:1:"g";s:48:"539794565569805340039859573323545355484274999091";}i:58;a:2:{s:1:"p";s:49:"1147402390250712399306262523075499402015636746759";s:1:"g";s:48:"626507572659492347430889119427988244627761972155";}i:59;a:2:{s:1:"p";s:48:"757314137648932572630417643460920752998094447203";s:1:"g";s:48:"529283349041682923530633778652165533595093720655";}i:60;a:2:{s:1:"p";s:49:"1361950860510200593841383238144379709182596697347";s:1:"g";s:48:"584714604603156245090438264122564252115723640809";}i:61;a:2:{s:1:"p";s:48:"776225946963506180259175310291119749813149477423";s:1:"g";s:48:"383570041528464505301304825748078346935105119677";}i:62;a:2:{s:1:"p";s:49:"1095615178700277152695831820099513466482620295507";s:1:"g";s:48:"539625950517641194035243952302416933336756627853";}i:63;a:2:{s:1:"p";s:49:"1347136297248479737442676121297888888430630212907";s:1:"g";s:48:"566059213942829857928591483029870033388619728299";}i:64;a:2:{s:1:"p";s:49:"1093293569259645131193126647642958931622598722387";s:1:"g";s:48:"594343997827841315653770570204548979906235062547";}i:65;a:2:{s:1:"p";s:48:"887602414535217945702184615603540100183295065747";s:1:"g";s:48:"662347294674167895627463959587876305268045160149";}i:66;a:2:{s:1:"p";s:49:"1010557038806704847526311588973776853554356024247";s:1:"g";s:48:"532893541909339954576938979713865521494468007783";}i:67;a:2:{s:1:"p";s:48:"829844939396446076032841069668619300178067878587";s:1:"g";s:48:"631998266108121979610799989316873576683309167661";}i:68;a:2:{s:1:"p";s:49:"1046494928460345758716197297416292696746658575579";s:1:"g";s:48:"615891927105300226068825732290141791815544028735";}i:69;a:2:{s:1:"p";s:48:"834135728048076165111266946917275399239031768439";s:1:"g";s:48:"389213395234196335590445606749808103986455524927";}i:70;a:2:{s:1:"p";s:49:"1154700011458848510187096294835728566622120955159";s:1:"g";s:48:"548503798393624074154942230942131583774664088813";}i:71;a:2:{s:1:"p";s:48:"978672053754186026248750553289218329620184542299";s:1:"g";s:48:"641055835629088201611166793394301543897343093531";}i:72;a:2:{s:1:"p";s:49:"1070102503643189144647061857723130426933962673999";s:1:"g";s:48:"711869563468284271638708344931033641934315745625";}i:73;a:2:{s:1:"p";s:49:"1323812811328381869130694828828061281852276002319";s:1:"g";s:48:"487053656886806410763695828754103165927486554599";}i:74;a:2:{s:1:"p";s:49:"1169329801421612423199318261807267948752947753967";s:1:"g";s:48:"408680246627811380564801297727106398902783872371";}i:75;a:2:{s:1:"p";s:49:"1384652955769809627275543328404332791741666272363";s:1:"g";s:48:"449672474457280124868466963066446412571192105159";}i:76;a:2:{s:1:"p";s:49:"1350000196205739429961458014370965793276931747667";s:1:"g";s:48:"505425622396261383117666278099826061597545042231";}i:77;a:2:{s:1:"p";s:48:"894705447065273442961638823541618192797889809703";s:1:"g";s:48:"510741338778056615339728592753920772472096642561";}i:78;a:2:{s:1:"p";s:48:"891337116692625714018605359651236312842104375007";s:1:"g";s:48:"413522626116106665014504432665726545091134259373";}i:79;a:2:{s:1:"p";s:49:"1297939713670228460811861978176871752377877828999";s:1:"g";s:48:"647298056544131270364838136232559701869206992523";}i:80;a:2:{s:1:"p";s:48:"976351259950759294642978741592083950506931483539";s:1:"g";s:48:"481165731343196004629915370853114428787031678927";}i:81;a:2:{s:1:"p";s:48:"980764218473209598929377503670805572400056847187";s:1:"g";s:48:"462874955150610793645950273938064092414395927293";}i:82;a:2:{s:1:"p";s:49:"1078402246449839832492595497686341465770525338447";s:1:"g";s:48:"510022575873437628725501442440267016121819348391";}i:83;a:2:{s:1:"p";s:48:"822926078477097486444962323277458446756022978259";s:1:"g";s:48:"589910875783545994219126942930975255660655801503";}i:84;a:2:{s:1:"p";s:49:"1431038025067691058996244066273531476107919268967";s:1:"g";s:48:"646932847368644396052277873258548552204273847065";}i:85;a:2:{s:1:"p";s:48:"748914983317514213116978697376736239495039622199";s:1:"g";s:48:"380231440226574322623857841433603704817502783043";}i:86;a:2:{s:1:"p";s:48:"746072024360294846456065926995318746311968317499";s:1:"g";s:48:"447450101636477251499694410520804920618515586095";}i:87;a:2:{s:1:"p";s:49:"1187131965479053580515236709652828301619620145103";s:1:"g";s:48:"497069754034640342738232452898528527704513730253";}i:88;a:2:{s:1:"p";s:48:"960772791831553183940713554045441733504839855479";s:1:"g";s:48:"467189892742053032374040989028169931254382194485";}i:89;a:2:{s:1:"p";s:48:"744720969935722391016885990661932354762971107847";s:1:"g";s:48:"672892260298249149453889871675067812728254959745";}i:90;a:2:{s:1:"p";s:49:"1284138085754206095984621825714666759051533360447";s:1:"g";s:48:"670680653213753375576284488437938207972423819365";}i:91;a:2:{s:1:"p";s:49:"1219703410168163907606714523859829978847615579703";s:1:"g";s:48:"677566000162233783460796007673293061475277168933";}i:92;a:2:{s:1:"p";s:48:"758709279959164862900864570318174449302613241339";s:1:"g";s:48:"452090953215317329319057610469368245672033968833";}i:93;a:2:{s:1:"p";s:49:"1071627691050988181827045931713008063023490617507";s:1:"g";s:48:"395161002059489287272140658032643593929127864197";}i:94;a:2:{s:1:"p";s:48:"747205427461860752092585693183163490214259858423";s:1:"g";s:48:"417612284638201080293586217380241875657446616109";}i:95;a:2:{s:1:"p";s:49:"1006525224732904380987702972930703364127273860867";s:1:"g";s:48:"577545982783186527062549787160719734065840781741";}i:96;a:2:{s:1:"p";s:48:"913028069291155898874907016169442803156338579159";s:1:"g";s:48:"382328749628965365180053208087496476372826871403";}i:97;a:2:{s:1:"p";s:49:"1180257192448033707067808765981766151872541980359";s:1:"g";s:48:"614672147155176708479881170756885404265660714751";}i:98;a:2:{s:1:"p";s:49:"1131049454834123578538951980844254468954332837143";s:1:"g";s:48:"516237691590580412638232604519378047537778117673";}i:99;a:2:{s:1:"p";s:49:"1237424753161543304728304439687733366979209986923";s:1:"g";s:48:"443245341306104571668320672937798146976581923033";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/192.dhp b/Vendor/phpRPC/dhparams/192.dhp new file mode 100644 index 00000000..b5707e4c --- /dev/null +++ b/Vendor/phpRPC/dhparams/192.dhp @@ -0,0 +1 @@ +a:80:{i:0;a:2:{s:1:"p";s:58:"5079153797574224533127650903566678124394292110246160120503";s:1:"g";s:58:"1775655624786036047244981958605679297671494641475669966087";}i:1;a:2:{s:1:"p";s:58:"5280951490903349944274113198979805160361532116756714331587";s:1:"g";s:58:"2750563206691870569645796674371212328334419605349825272301";}i:2;a:2:{s:1:"p";s:58:"4908566683395613935027848474793864939536478635831425790279";s:1:"g";s:58:"2217539231350728286886430339426948674052631001859542132203";}i:3;a:2:{s:1:"p";s:58:"5703624436271395096304848287817139341138468504063713187679";s:1:"g";s:58:"3022750833775105018689926348454114058182309558353388910967";}i:4;a:2:{s:1:"p";s:58:"3408373670273337858591681243643970689646571912179487614519";s:1:"g";s:58:"1758856341362672700409627738845335577349659073518321527443";}i:5;a:2:{s:1:"p";s:58:"4287320311873603445306168782852197886252881409583514378587";s:1:"g";s:58:"2443195977736559684026176246109530132630326857948446510283";}i:6;a:2:{s:1:"p";s:58:"4761797641028563107617146852177956262274271252575050657847";s:1:"g";s:58:"1967905564901738530971339075129813513598845172896595290077";}i:7;a:2:{s:1:"p";s:58:"3404255621100712761608995448456580112050385881116515218743";s:1:"g";s:58:"3120045944636737237456921814814946983811560917318686693791";}i:8;a:2:{s:1:"p";s:58:"3518512132339784039367856376100548636855822828484663862139";s:1:"g";s:58:"2936406192235066242230149165110575455148803961090995968809";}i:9;a:2:{s:1:"p";s:58:"4520842854376900535800877686817612397649559103675227962403";s:1:"g";s:58:"1874657377100137046702279108249554882052905843093324820341";}i:10;a:2:{s:1:"p";s:58:"6203733978483113711573047161762684887620736693334966038399";s:1:"g";s:58:"2281917699991259331857077643208127496786819947163020051699";}i:11;a:2:{s:1:"p";s:58:"5214094012046521402304871473025167219554075012879966514639";s:1:"g";s:58:"3088934086307430848999804849857781760708880102815101369475";}i:12;a:2:{s:1:"p";s:58:"5265787227241273761511382896841225398989161548919690936399";s:1:"g";s:58:"1712679489582782094723102988233060994358404878702641326991";}i:13;a:2:{s:1:"p";s:58:"5067782971873137269486362087896632172119409421624139384687";s:1:"g";s:58:"1957215522412301847352896019837878268005516128183054332167";}i:14;a:2:{s:1:"p";s:58:"3879943934531405521219894064328899150202248043781792741163";s:1:"g";s:58:"2689322241684381372458698909603283328674743428685220509813";}i:15;a:2:{s:1:"p";s:58:"4120056568851266360689374732995900645396167325280679087463";s:1:"g";s:58:"2739056964678871613984984850786368930553006484449754894415";}i:16;a:2:{s:1:"p";s:58:"5290823285697561402595250303494270872946043138293779317867";s:1:"g";s:58:"2999800290205863127707463942846916629036584233489088821049";}i:17;a:2:{s:1:"p";s:58:"4696296982773151008599445288256643884813021679236448495543";s:1:"g";s:58:"2408594073193339386366580971829213213076930843022656561407";}i:18;a:2:{s:1:"p";s:58:"3998268366250968840287647928335220016278201614040738565227";s:1:"g";s:58:"2595910859797751097123521430486225763957170171506802652187";}i:19;a:2:{s:1:"p";s:58:"5105069304661883494321382458240500613472126523513595557707";s:1:"g";s:58:"2825214821736761039502493498877270698148881800422346821893";}i:20;a:2:{s:1:"p";s:58:"5939529852124350341005590253411362002186693503432217871263";s:1:"g";s:58:"3137030337042042092888657799036721412663511814250070150533";}i:21;a:2:{s:1:"p";s:58:"3735981060035319331704321434148243550135576868950902098459";s:1:"g";s:58:"2989931789688807377997994070703231972926299933593627385837";}i:22;a:2:{s:1:"p";s:58:"5230792378968521455498964433594802701706868629126441715183";s:1:"g";s:58:"2992268420669971207665248346210532238175082330707685959423";}i:23;a:2:{s:1:"p";s:58:"5749526646585270332971754516348605824542707999962994742387";s:1:"g";s:58:"2573170301376768608263799013605480737285869306043252438563";}i:24;a:2:{s:1:"p";s:58:"3699527020894248790756291220971126715267429809359417078203";s:1:"g";s:58:"2021241263496862637571247756030282715635367895206297981837";}i:25;a:2:{s:1:"p";s:58:"5427626576291640178697581041470814432676853894644639708223";s:1:"g";s:58:"1848499510997690637725982471703590963955757498487817240199";}i:26;a:2:{s:1:"p";s:58:"5452425390533601550543539501601743784582084084867811688443";s:1:"g";s:58:"2199548899998832053779931991591849993353619475860404941523";}i:27;a:2:{s:1:"p";s:58:"5878470339621492376906133148257205717408902857792669244327";s:1:"g";s:58:"2910743244761101832680480464052389046853832954372521194003";}i:28;a:2:{s:1:"p";s:58:"3587801443783379284860115673588846335881679053068010151367";s:1:"g";s:58:"2315160945585969381035789749922662556153810767582805204681";}i:29;a:2:{s:1:"p";s:58:"5653795417450857251329458236472236527706349566486470589027";s:1:"g";s:58:"2802943059453712266640356788067020589920472674707906596571";}i:30;a:2:{s:1:"p";s:58:"3457732635912905545926589910894036857464442278032296155323";s:1:"g";s:58:"1903129017479274520911249166986172071538526145448641719123";}i:31;a:2:{s:1:"p";s:58:"3273859658245405519746765698873884234918875187826838068579";s:1:"g";s:58:"2929782824160658072753520803173577956848457241680756520565";}i:32;a:2:{s:1:"p";s:58:"4761700036076133445360827240122621071147714758522838080359";s:1:"g";s:58:"3119507520206605362692770863344057997665729918422544613457";}i:33;a:2:{s:1:"p";s:58:"4405233922665692538904792642661732972090380014017234871299";s:1:"g";s:58:"2156108555163829703349347996634361253078629587693591085311";}i:34;a:2:{s:1:"p";s:58:"5434930531607967663872622555642175923042733006024997147363";s:1:"g";s:58:"2390628958788389539882354377548156413067155083898369544581";}i:35;a:2:{s:1:"p";s:58:"4344406185108632577312980841629309659365783238791736671263";s:1:"g";s:58:"2647210942852956042972151850238629788613813461130912113809";}i:36;a:2:{s:1:"p";s:58:"5278098580436144905030665703594552427147893589111423504363";s:1:"g";s:58:"2814874609333584535379357984744374068073324062962155810123";}i:37;a:2:{s:1:"p";s:58:"5508427450523598806685760544636322560098559536697021132747";s:1:"g";s:58:"2761184507918258267367204938499934170019870825853641891507";}i:38;a:2:{s:1:"p";s:58:"3197969999493675106847802004872388076312076345632578632803";s:1:"g";s:58:"2764533290029322821411173465515504778592964392854621620083";}i:39;a:2:{s:1:"p";s:58:"3568017303357088501066971162950692936521340156006663981979";s:1:"g";s:58:"2462095370676111544085426676206766871866947565184370207309";}i:40;a:2:{s:1:"p";s:58:"5008365436214491146872187578253187471375499980831929272867";s:1:"g";s:58:"2004937842465852411676297045663569672559418220307277093907";}i:41;a:2:{s:1:"p";s:58:"3660373588674338114259459300737035072550434338346265097359";s:1:"g";s:58:"2991636412905001507296739812030759919233136578804181824709";}i:42;a:2:{s:1:"p";s:58:"6157975818295494991242524096807318074150442170944799777487";s:1:"g";s:58:"1912881834041571656233505839143523520426242139511439944719";}i:43;a:2:{s:1:"p";s:58:"5337235345895474227895552498603823319310250209297678658503";s:1:"g";s:58:"2004866565219588730716376725495942807885729550763014887077";}i:44;a:2:{s:1:"p";s:58:"4371864179460543040008442352670502630060546908322397366867";s:1:"g";s:58:"1935388976841885638579286522024434829194894520675959876927";}i:45;a:2:{s:1:"p";s:58:"3414083549094939748645823179851604517084752156079674932167";s:1:"g";s:58:"1816546965247162148701261384470515149792513541950434437581";}i:46;a:2:{s:1:"p";s:58:"5536741182273059380739258337848493476934305752266586238483";s:1:"g";s:58:"2634952255041246307511360974017554325693333324673254108479";}i:47;a:2:{s:1:"p";s:58:"5775171283053461281137695211327289107677094643699899519647";s:1:"g";s:58:"3031757045742291978953154643467910261283123063435248617143";}i:48;a:2:{s:1:"p";s:58:"3660370278097827798512899847051044607487572010565769322563";s:1:"g";s:58:"1871171166775120299644215319226940768117395474691743314505";}i:49;a:2:{s:1:"p";s:58:"5912814201192481980980973291370859137726857826993424267459";s:1:"g";s:58:"1957331954178238262489699534050120077442696109610799864601";}i:50;a:2:{s:1:"p";s:58:"5184758634017280989737969096729809423029735654784172479563";s:1:"g";s:58:"2747826512297974451893717897444511651643434922118473813467";}i:51;a:2:{s:1:"p";s:58:"5016554360555320960358874145319693037228385506831515688167";s:1:"g";s:58:"1784356253939847363273820130798312708011366157682845326497";}i:52;a:2:{s:1:"p";s:58:"4824111221728894496275833910627403059802694666016696093139";s:1:"g";s:58:"2662092108701388387028814515342811320842361286171226121265";}i:53;a:2:{s:1:"p";s:58:"3542653376711233154532437989275009789150906759425833977107";s:1:"g";s:58:"2993413985944641497043043994022562701684915788578786069553";}i:54;a:2:{s:1:"p";s:58:"4187665199221743303574139512590690486755802614141320341839";s:1:"g";s:58:"2510543985310768653707854276415093099545041552566817022349";}i:55;a:2:{s:1:"p";s:58:"4346276948576799819411680068399983993443471275733281789763";s:1:"g";s:58:"2442402785838021648812881999905665222333408565418673938453";}i:56;a:2:{s:1:"p";s:58:"5941963164742000720764400502847295414251200623156896167063";s:1:"g";s:58:"3109075742957968243564487898153518334570588261995161851867";}i:57;a:2:{s:1:"p";s:58:"4968360668694082055763517916799832503511627402142244841019";s:1:"g";s:58:"1631103685513385955188695844999787805548545198875281032329";}i:58;a:2:{s:1:"p";s:58:"5352110123307966463863605353613413090377648808052386739639";s:1:"g";s:58:"2750049649165087696925391766691408509531457761506337220083";}i:59;a:2:{s:1:"p";s:58:"3492541419748637892497432009505335534778776020683091511999";s:1:"g";s:58:"3049208593127223291568667028585263138784341270026974399485";}i:60;a:2:{s:1:"p";s:58:"4861492597654350078184874961008205492784601986955728398347";s:1:"g";s:58:"1749429043719289142747830392455920053316428401625067853441";}i:61;a:2:{s:1:"p";s:58:"3409541503404917386768832654354691273018080275627195068863";s:1:"g";s:58:"2845917921644585587482900072159268135689400842569349846455";}i:62;a:2:{s:1:"p";s:58:"5001587109106537100754211008462547142888306106754962133079";s:1:"g";s:58:"1736190567706663129392257076867802867666208577891613530111";}i:63;a:2:{s:1:"p";s:58:"4671631568303408929313557979933219261990730864997882387607";s:1:"g";s:58:"1583827872809517491425531274727857065425946452716427187595";}i:64;a:2:{s:1:"p";s:58:"6146891969648692994042239520945566269789751886818035128903";s:1:"g";s:58:"2727147900282056053406651420169531118678689909616560664319";}i:65;a:2:{s:1:"p";s:58:"4691567770908195706485352720805469781946194453032677202383";s:1:"g";s:58:"2236768896068337176672581634512929610734819856751870275011";}i:66;a:2:{s:1:"p";s:58:"3872368398279580027726321029226746610541428160314301688863";s:1:"g";s:58:"1608040030265058297534235316667763045728366641295263678285";}i:67;a:2:{s:1:"p";s:58:"3203632401065450194024989211370201773029103146907460791907";s:1:"g";s:58:"3108490534046256038320616158880085899798273995837799898229";}i:68;a:2:{s:1:"p";s:58:"6073671011810509460429303954978560171127887337149697533643";s:1:"g";s:58:"2957181103947316246707372225424441718695563269317354251891";}i:69;a:2:{s:1:"p";s:58:"5074938515907596155271435330326725395033521551806939456543";s:1:"g";s:58:"2485585061148875179271778918652789326197814093765863878501";}i:70;a:2:{s:1:"p";s:58:"3597117650406458524784844736459676469944049182578914376967";s:1:"g";s:58:"2257773347341600753179198090802149292787501545042330325401";}i:71;a:2:{s:1:"p";s:58:"3692791074237392866630655248999144283662143204054214329563";s:1:"g";s:58:"2534194325117231881996721493067203343094197216768153045559";}i:72;a:2:{s:1:"p";s:58:"6135290864129465394143806935986184464296313272645041006623";s:1:"g";s:58:"2285613745291849023050799771859696833587607166899781802297";}i:73;a:2:{s:1:"p";s:58:"5106945177113923512700853358787168136230226375108347673543";s:1:"g";s:58:"2936475085379719192967479751088291541575787778419060330529";}i:74;a:2:{s:1:"p";s:58:"5181718537893973578476916094185424173615729216146516666819";s:1:"g";s:58:"1865764650967895204996751102080042379553463091437317170481";}i:75;a:2:{s:1:"p";s:58:"3531421829504016980971043040659044882221181410827188828199";s:1:"g";s:58:"1754788776989782747965652935525104074154211520611110481407";}i:76;a:2:{s:1:"p";s:58:"4161793909460184982769028720635087392704116618587096387343";s:1:"g";s:58:"1981894828271550034470871640268847167031481222081314887149";}i:77;a:2:{s:1:"p";s:58:"4649508772336796680142675195864617980598769529445092576119";s:1:"g";s:58:"2060260193469253389049874052470270879843305419455903720777";}i:78;a:2:{s:1:"p";s:58:"3794461735620721528002956624730277693135123278831773787983";s:1:"g";s:58:"2189746373719240792072113566225714440698072247775237220387";}i:79;a:2:{s:1:"p";s:58:"4259297905676945125094110840005802642699827572246773326227";s:1:"g";s:58:"2109550980417331068335665282608229962431326830969146948525";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/2048.dhp b/Vendor/phpRPC/dhparams/2048.dhp new file mode 100644 index 00000000..2b42490b --- /dev/null +++ b/Vendor/phpRPC/dhparams/2048.dhp @@ -0,0 +1 @@ +a:20:{i:0;a:2:{s:1:"p";s:617:"26119538730417652824386042875531065645936518917298962859898441526145920544648057315613454013347891735147825801670444929736964945371870320839420114081211312040311426747341924926796064326790154135416828824406498127049192207991150849791263466384758021041373648403002021019670485486194422368037809226590462008768240610399792452398657398016040828114270291337378645720426235644484515722968943627611602608942224415247853186618238500673174946668053663930012369427127054431907175454668091517702372418355188739885994249239971879046563843965996805199808782303607940929503059770051997236902131942802683449268228989972965647643569";s:1:"g";s:617:"21692939338493471757047070972142857798654655518644033814839259110511954364805167016395345229599656727059168581562814761049085679655778308409884937999942260287379782711541364254190475889453590033170167544793765866452374932516116637879718064465014425017927830556064617293664040306920668006143308702764719183733796439597113613238493154190242995109778425085299465944352613372309093551104453581823748016505746665915971846990430996971870763550674830590105744057158734865757657025005213833571438489370197722184401250800148831017627655890275298519934855829463439326391192412757063584883487921219859606832338748797027614904402";}i:1;a:2:{s:1:"p";s:617:"17494852415029253500263451635519645209848793831494844994025633838817687049071127640459187917644787835777597552920325283395311336348831223620733928313170193589173111165038138057869913225151019592978760413756939078573486040073633063605591180413506497786330721001074819795357862986504220202400959786152850399991084732854557124231380109637676272229893604175498706260833666050908881082936323794606250012464077347589487455541114492420426914154675480402370321252743256114353020297093701386337644658626048585971064205107100595069003802366933563435053584207760412338330625134515253507734839954484610005303585268020855550319783";s:1:"g";s:616:"2357536766000763120599640303735871022142042544950223627657783713207355119762671384828323528942597724321262315162871435756768680295649894617172738865491552395499945910352628711737711459272586894150019111123607450240818973582127295016918052347511023159480848100006890622723727515688121279961377206539154059916280008591560324035228208297543602421189229162987642842188359302005359697956742412268879330969306518512079332500066243775980282601895703673233538458812861112392269922097185505956010310178122235450911471276428561302761444822273287825322542011844279562807283571980685665180825337747868563602172878452348907437991";}i:2;a:2:{s:1:"p";s:617:"25780867781251628440065459712673652906933462699778652742815597485375302663371634433740749781750744136364458591061494303870283828393634179033789064740550017980781317260925771538480299931323791768420861462236431178976601993346954114130438797677012654484168409283271118338570398965911311009082335022460593522080995913669261644367315202030128086666255165421549254127930200196693366384905335244383579750798169063385118039839822333156433252043549232431896238765093602816646193711914401964588912145258045516400610180499330382140474862865622175503314183207026529522245115643165204301739301808240344047865206921844783110493619";s:1:"g";s:617:"22913453542498739351587679639664856992870400001370134675523784914387955771143444917571437755672602988500046796113264805842672819918732572442945319891001413155624746874608973595637299150443023015326933062381925416214430378088998324213270254493852316912687655115745315976037232162037286469731505569162296708698849815888917345038284831130181824975228023218421467353208181389358811631765874415954696258724127120397639098550964799825663331326239274792397246407429506415811807258362151079599569033578071919173833344990717848768176043897116549506982186347999780034352488975732137271158144830900377154823625267922843930480163";}i:3;a:2:{s:1:"p";s:617:"17108582037564624674917207799802832391965005846368564001912347974821312076704202022935078231527320828683510069559020007567337030036847653897258184670166659043776952835342581597567057883537012431671450166955634401920313853950838958877425157189757276240508367052156667477216311297002905488180123637261690402759380674542437629380601702878071821789801803270225500263470954518609603257770968427427507711325567168791246523926693942270053153316006073740979789299514536832553631600448872021864884160673857409747182631139916196743438986143545276713429020032900149638305213353651861654548990616900439392404675443312771396640963";s:1:"g";s:616:"5975220509433032675041067739982972692919188487073925726726373313534662751942478165577276960038244273703352381665589951065977292053614500099134443316919840135540845038879240858995341120504930299860699717125398702129847883991122790294702383642451156914176785997702247519476072621264654943534650803561957687965391725682747412106679696055298814300614513661600544039166554398548785771944233727265781414899110258870106277094923042460709047677122331805345608634843554102871371939362771130643332944065664751524937870301121933464463246140428792009737393899405409293013771077653754980109244592589837015805450647805669046754032";}i:4;a:2:{s:1:"p";s:617:"30717950753282822134060274292481360551691413121828212175823741839241549781801345288079837278336315658072275041792278917609278903215044319053321254942912283926424925303165388602101369690100151597114979236011549040048767798924665432539893102285148132138243288344387551553735318445920954909506524809009977259661816549852869076545111065438920376549122286806153480198930510896590461984138938291299620745126683744010164416765756555097048566964051391776874919866198779721078725961148626312942109765123843522548437856492683402243565586864304705385604772276167357697786949526357219442530907854345605378292997710443788101928509";s:1:"g";s:617:"10664565789660490202298837070717675886736269910227069585599819283749390051779567448569637299937235265670862351367215197727816605187136471289814225238589787798288892630743957045107552613020882669254784592049108026598927346597271935204885557927508364640631111649815601503280096710752780360644355184069964880671356047707747432831698299934227246554005301084080880453975468135327329091037112567370668621377232969391777852701506421877424723612998254707022420880929038255877994522028632025963236345524733702080124131982159125526983451439267827560813655547710499889559501382446978742844869796195915570043693514343922418952540";}i:5;a:2:{s:1:"p";s:617:"17824540401688806758789771896071225083587012319363998191617936849653181551389106695047499662667967291625581739247113239792813655844528068687604946381553759091614945221410205365009632299490330030743034592873488196530343761271503174068102203374839746210075299309889318599726887738428054051601011972157572579321140979949387997453722974702415785332940537370596257985385177683159554405404123424672225807041157719414211000240941151112149989476447852776665859451162933640847402800234226474660637032612891723759060756931730283712399193482935639272951418485408140391847864492821971660080653487293932836946944136521465404250497";s:1:"g";s:617:"16270475540244008116184585752778689991248014144157341857630851928118586042015777493384925564647551896410840985215558245916363762734559266526213847217597869257247057011178185341066439942025102868024300290055851586251224372269673506910096840729969115630538026953603715119989120184962065253802795940639181332522689973724641004788079105051116542692460473554873410716389242666154728393218313118118406398989884581832628532396195574914320097464158289655615576483587557151914583877087002898507007877917751525353738520926876932264221223270925546352675517006263788102948929514039399067600275172739530270181974973828950452821163";}i:6;a:2:{s:1:"p";s:617:"26296541223964919760168059530334570885931534159346927274646606919982025952484337186039418912581476534463653561216509719479381053176684855749980449821690634103712306845089639450245895681254698231346381048999674311066168967221836809132774033058479473511929613700963171492882041969658471628084862296614689763559416767420597105445926395306014712602368798792070456787547357402852952716350973192781222867061265663188204551121616232196786533549406074301166048247937522415623504126765142089891926736558098921482439332224715081568035947703433373054349275731306378072487032600877157066181584066648043385348780258366341381039503";s:1:"g";s:617:"20245064513421081672907499417270373165374993596361839579769428949180631359713525104278983408046767381549351368804724075603972313718652589273580418726681940935429978945328837517669894683202567520983954981482700658614407104539781496091529019707970808126673481202951901341090515405122549648668564031419070573673075692741103463991210517062086632857878380093746773630605663125442075610285516428487568040493243899961471715606477290256637803334729918901038097438118954412644360440903940454111104955970051371388583374743634476943068102699066226605163496367446957915588429891698437584852521630657930214723677944070438116045469";}i:7;a:2:{s:1:"p";s:617:"24022994888213612729867097153159489863796760878636990746219660205649898621390642573759009418891804310813653013832818801183450912563726218725349021897580704338568278000019615459132633821605975626413805907014019193876676494728190737866777588109580505401823207283091078285105989405265851649576741649994378038616418347053183638209158265693304947428873206654237011507823308167792632150344918598864834554245939189283437720190979383402835863441249830065088109408522132789686163566158101743287893869880671902412445418124423229540545176428391408627743403931489063787699934557486715229490493258244148224520887812506822249429539";s:1:"g";s:617:"15678480265412800733944492186437037182707529884326735097121447410399826968420553856830859651354914793482794886843456562720138670995286947463967042610750193460296792282058991180863764589693616599436896718205171675944873415284970267586420972091500234700259041314722311096697012899487002459357488089950393843625900001981078241171710748533509781217310128183350756575104004773859267324503648554413357662859641282012089994022788874891032192582004035250870868552993001550637269383026801304603350993608652909153403397051874534815752300653963021337866508400173775688584459109409363861081393338196432750140305711090376705911521";}i:8;a:2:{s:1:"p";s:617:"17083955432364090280533366102746720945982105621761336600070465958323396972881469403519543155239819620859194370028989288057523170198820482837073270689355245228512567098603210383977491443914341618615645725451024486051612004217893492714245981039604396229635631751833639174614993002993629374228068268504356303017948571496867771413891972482336248648581356279979915549622011422496674683139397429048285638804862404243827650990125026074135379573526469868687788484267220583145333135102887002688284926311346027425969194262182288607685222886823791242675124535943766023129987374186943906004265733055482162823032404897008638709489";s:1:"g";s:617:"12261234691674641709407438861728481101674950650359345083238884715719434368649199286826020022876464290948119474546308321123254175100004821757208768631686271471283892085404640045175987297679723014286459620532482282374024512847784380353023734692492663279003858305861949005817377728600448722524457618798241008130944601573891808345338306588166841117840949087313506761214152652649864023892781683429143355875872143036089635390231181686164167199603978001780011953093051148910850001653642083816866537367199013814853150666286608827942041850714980974747352884836972297673635076130465096348662086839526317882823690060833316121518";}i:9;a:2:{s:1:"p";s:617:"25204476138284467855670453742205091544206927935811391970379875845925341542816814592972482175517776292877803060312282683057673887280171863404039620181938052133263739488514572047094655954023089583401121552716825102824245089603523869015914976008594784258015509292801626580908040067127059423251656372753685608747171457530204828520955350885774522412118938249637383726640228002691450698618877022629430660597324647064876949362319041249591609232234716766223276932543328705703598431803088575036192723955330976791603168213443104658956110289005145211221506492748124722595764125541652261925897188877632144503729500847899162487293";s:1:"g";s:617:"24470380828092171830607640675307269842934271351057990119472060393765189808175375460336691328427923943061209748614966054260866042030491028094628330791617270491451679586070624647214669151124663462616816618278458332102224612471875661847572035426271967106152871750183790750472633379980457073939646744071844097027505130835932272606999975749253911402372736522468536931939555983440411944997387444842287619087631352802755805134214227572364500740868338334180446779244274684101127564951437506337872796885243225511197939032115243566176064416399644452111639287953151152283661969561179612761064215331184337200817410228013012815215";}i:10;a:2:{s:1:"p";s:617:"22849460047804632398448747334192571885220871329972534210954947581951666060547985334167486681856357757460114635134954573658082358845539735278580423082123931373208796139732802045985276620997127798853678505071244613000934377737859392412691661273736740375485316991267484188256664287312744138816442964815805473226385201474782318459805435125108038706696302574616946459702959134346029698514766348904241077025385404804431202010332555268586051143130818532183288892073337677669462830398135627462917042631034659974404647502885769859349150518263217937151139653745940505432896722087326115128679012867920678944411418261860631429193";s:1:"g";s:617:"13348138446721657089630012558844652910382267316024344211317185221773269246392374758072029526288163619976687471148401063666650529131734387772547277912767019892091405085546024081290166317121965135731523404800558013020137490216776128824652409837770063691312561489888304473140055749560988718836503040853002145255793919808930722368419221663001775239907136704227153865398879262468691524381141127515887196789195504406217373337864420211704031143442387747687436399787007564064433407818094211670914708907567291746261122103561160648080311292253951964886079196911189940359203107056306519670126645661147468673028841078212599422387";}i:11;a:2:{s:1:"p";s:617:"31338823808328910030039189736747412767934749985120979774750656232315188517412996431869533670874523236506095344486318916128738510547271487301629733012645126112498494837873510962613906720395105423345696133501168531267479752944739576745897553250620501347859376611724762320770615408466753235707776687064856460812255814585002695810118730421429331410377462334339309659699186654268542620852088199397227812555782980142369915873664366261623799237710733709363641919324417365535560523680225962259801453373866070142295896144627383558885424151975989188203272862741597698359922271892774527924814448590085332431320643929061731101951";s:1:"g";s:616:"9244265426989189771814939991669243957748740903183842164268478744253017075992473802044696109071297007354420472625602806611080450814213109420239453967309288617745014104035838027804629485250918376876630332625045211500185584005538683904806015146917080419014138452138676952964670289110065893199216408172970617769948958057624438113114785977222898946940751719007529545723841152648078690343209939496342721851948377226748909719230993095239015507357234175387231426890464735514048452739457488549618437769362624641802065425556060699697034837970299896246378714455325609840424540997999174950970499493632310488630948722459761331238";}i:12;a:2:{s:1:"p";s:617:"16720011003255706113542533606567817550154977290327341685222505526573898977078683119417076323927302182238875008774846510300284799199809076765861588224343304072595369156757416312139864889452521559749463663197267698729151348390397049479376093343572901918439800962638271229803825595288317054627390900627955191106470683028331619882250925001777457287598880159325943026403028710302505474738862997006103128487776056340534495054468394659034381740575225073994349667872488974021301049946013876074350344727733532691108462203697035662350166633970402791313885464164756357492157962521289407696476321940071562093155602895661489660727";s:1:"g";s:616:"8392549857641312164454309373940435723590421663279978069555127083582677257780262498752161403608771364645564865559596200803263820963402481442852937071497875582873453734524770401215851485463814913260581874888729922114937703348851445066316990994716597429391207315680448738459977536648358752488744579272567717490797318379401666836389388815269231571648020465125802739997512741984174379317449696467694331951860453172686792834397700517360054637428943005447586488819050418799440935988665824222808271742893820938468194415642476156380577849705310979308145356389925732064483915429084436934935530619828894853018765861416844776438";}i:13;a:2:{s:1:"p";s:617:"18875760971083209961885190059598721536385876257385725374837530129382586086243382935243973016095834416470415049985931441352969506342859331487451321440644185970762508184028359569305280339801922408612236736096586209436455066098437157049757171836542290377568267264629176969075668301397417797762391880806604540802358357273422189043950195254062471915353959389101213594915524766080852049810468225847178041179462795804709284087874701166025765058651052595190693164918437491064045608634977527209186371829864710057268355405434016180724414588828894423442390301185665478042155226826512674948772583334977420644109748745496717956161";s:1:"g";s:616:"7831956897688961168585556861828822320686818447121831468325331650719661818670456229905256692890429862578945073402841774396892137360518705835947989741723445501270103038310934960720438693310516616091846310929399159391021583737179951182014058853520535002225341000259003057782221326379046777635654033845038695143831406214163177624050429118303678368949300283954340675165271848269749284009942183037928288215934744269230891498878411296154350712230783593506210329194220505403024776317988240018183929230323644668404305143872615370553030474103851064003677655379017189993119048579440984740754303375459978660957509505078490657995";}i:14;a:2:{s:1:"p";s:617:"28395820039579334836161387898649960674439247233622326211768280334782373271489931817979170890916055413302754245705557686741053065719308409823785829762995052524756698071971324411047312398267937917755702206261019714309083266666414013819615504480631886547648812227018792688441405307391232086908175633468071220469138604413592100312699652255608890441454528772318259437737566237789142089147587149245666808919002145823882578568437856570025104248895416549110129209195950707772095941939502533593689204857946981366537873479013251033128358611814923150665511824175891786378056975816035141738553582850943558631898695157518195312479";s:1:"g";s:617:"16427696982631268353903581225487755231705825946830980554789105372858716026038249111748904084081293969196895304847211869328781733531414281143425893004105097751232768970984365526090081727509403174570678697235610442079339105174193043899078868617483572838448847050555823164133758660962030044720163750716900891345546349794702104874846983027182159351657363294959859277476894577221808034066234414030408976510603071601513517363788768298684299375453231513250932016545163534328516215349904742837283723209984958135686659791911743400514495756511965490801110027623968106155034268853690378943253875810016843764682678137792177387441";}i:15;a:2:{s:1:"p";s:617:"16895876560966846422580484060632250344028279991597239700516020270083505598828800684402957155723638097932477009949561754503437018270655438745051104890013072510900387354248033926081481144447977165881754984892587524293467054670099323627271126243617375076230412683004370870720615709833281491587978704142630411596015418966637316097621942031121320633348486629505904113642825954743114590462937823539960421789947873999540484355570332714664178766388598601416594705788731741720803815778148149915425982758373977150668814201314016383576950334588270980042692711517774085697988618241677212947115800722377405490644578427754272325391";s:1:"g";s:617:"12562425989524907011004691194930986388586219858834665734575703272928936583401256775823265404348532608420240136127635564158186788142328847636504871057962904215117688239061667196573670142209844922877950379017542816985916147729138565271594417564432973234862372784752905433168074513343092968302846347041479914197331038856875369435991929275281451056919524358717865600391488606051625691960488484376362242765534345818340338768105915246819027304718641846705039474566934921726821449830829026173348866560596158471286618187646399500911928214808061786090706638481164230762304017836419687357912810324817426437138236086098747016365";}i:16;a:2:{s:1:"p";s:617:"23592516043230669381503209490463912141922639479894331542046867222724097666751148038610606011023871126488378139347032265001525086624363691819566899874833940140774643220129869846896515297232189140046162539824550174277368181841675294015687041610499572801215455220349891926229111228496773169280096432503725426296044037202286060887783039639522594117165502962065742480408868757768838322362817278441563946363935999706919254014616515903798417454432404825037513060873405178641053793336989996203721941343359406537926727709530631693065497367776349495501129472988620241004182664916330461587088288889551735860187055513147589776493";s:1:"g";s:617:"17357673844145177985350497915290742733468722287987801951177917367151312063340417933200596968143253358846521516037627485604196935838705991263693782128577977709815774507145803116356994495454865663246386089298609158258807885879398788921730122192063919930212770027132626149464443611825908303647374448825352684868098359426367908573139014507718513977629877766985377237524984172786250947660639174591036609831051955804915387372318428626310296812710753916023514838653465725580626928490042758170754692218386311983461067928388581645238515980737145748441346604551781747077785610383458653905239486828967469096880969795814241762575";}i:17;a:2:{s:1:"p";s:617:"21562752817967258993738108906070579852039284843199885400956208534323430625671418204128340587893746628147431644603790908199613136574754933913669343614603320177523451846097320277092600327653947194375390514003381380358695023465638052714820184091922966583876523596682349437357201109301308068214108864523456588480732651538356551882147183933343705677706433918043334160712384815884738870777020254836544550884904493519865517553323545274678672504574933053194683269178875640249625236659968381130308537583795589786484046391067710957489457666862306475754083459177269427077232481488264522791483632575447236274170676788449453054921";s:1:"g";s:617:"13279794357248225509268913538229148538165475069688936294580710760692619281482036517026872782539307727254420990210098545082069190602873006562154189669783694568358461408837175649218652220054674691087268179615232683465153579526387421315074008948599907085908216891149444162354267958924947208835973759341257881529439709224745462220138240933234290694196662053395846738948018071824632382236962943562507267190805674962625665753157699500275526405757056345749165899750806752377097857904380121265291644313347878017446362553944043862600781821033710406992613690878474651267128632826192153111804588684259077012631873975836172554671";}i:18;a:2:{s:1:"p";s:617:"23417496789833357562672978663019776511350475549993441033999842954607242935212201031177981126608192726681624256142944646964904043397803054432307081104126067134609549096882870571668507906471183209340875647777583501325231659669003773894230363951801663030831715910008600763835254655919490884334756073413369232416903958581403112233968734299630803767064369833523088084720247752560471992092988134943153629918414448683818715382811469577322425419540944846275781757188812631747645756254548348427432379275629846811194041724729581004054697881971598136398819432205891530514514726611596081712980455525677515953671132309404250071199";s:1:"g";s:617:"20801071262499851595618900578716319162176934003597174772636998352276398183882683316341580810228964692272006726151949111073090755703941623831598136461709241110761094009335679988218697376766403851957621931308873298652901263458555140525167016139424806902200273871261469449585864822112230671772272721833668808110440729098213448660334235171526815362020901986446409677613239293176635891891319223839386130383508566659068285370921370541204738605732883427996902307444317957800998331868014970214411060587106746040466748722317070439516836852348646076122345442869711806916396726025974030365623397644963075893322652883715123188707";}i:19;a:2:{s:1:"p";s:617:"26655296424058595179986310167103331472267584754721747665583558010617583798047063548558461532129138907195342606110500349726687564826777141466985678647752168685567480284858181931720530105350597193647594741653262467426123591472855807433972434979985325772504767253260906629707641042348493651989852298534933743195004975569908108431911918638926288237978982598438700759037925271408599142662922835078178738643272649728478247566871859792919842613041352050717122901728364945875378901071105043291927088234618466029720808811991185259823221295116563650637764805660046730198012519725055260313657762658163200991646911578427368876981";s:1:"g";s:616:"3450823033011284474361537763550411076975443192933065649612167536169211540041636498142282627876628156505178333636935643072260250740502145734190044105686943952320477597940678735631410435736451636301010458696341853562923909108829395191132711128551212911250649213549680593026315051719575199856616040525994791083856219112881366064925789959328272385929709200935493143170907071110731944588385661252268822128197419702714537239233622482980084952685844765339934318859731546823250794044127845644768022363051861287357902125164259399180047661173479655586363283681496036348778999849460527637675466013111833098388040937586686177315";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/256.dhp b/Vendor/phpRPC/dhparams/256.dhp new file mode 100644 index 00000000..f03b53c5 --- /dev/null +++ b/Vendor/phpRPC/dhparams/256.dhp @@ -0,0 +1 @@ +a:50:{i:0;a:2:{s:1:"p";s:77:"73832814678298170902979872884647941029284901545874925549746124366827544612339";s:1:"g";s:77:"51476058807219506610998206277345283936107915931731587440850063953203701691435";}i:1;a:2:{s:1:"p";s:77:"76972593405890136659846148581539967395400916262754679122033512090683295261283";s:1:"g";s:77:"40536177953614732865121461574338976193053929823454386769938537329223229736419";}i:2;a:2:{s:1:"p";s:77:"90678222772517737182669060100267690524517282587753173849354776070207136203987";s:1:"g";s:77:"51295217023324020085270197655410071441653549099982249142115152656556847133535";}i:3;a:2:{s:1:"p";s:78:"112035122549801288782735656181280913656716016217876691011809129186010432958739";s:1:"g";s:77:"54371647042380146023378995284862875333915973077834564744526683766342076225283";}i:4;a:2:{s:1:"p";s:77:"62194158582069859477188305359117210570164466813769290906395340312924423091867";s:1:"g";s:77:"45661079503690430027932894824979383218303184398768700725140595279401162955627";}i:5;a:2:{s:1:"p";s:78:"109887746949716562289488448980116120835960943658798588241040366306248937186427";s:1:"g";s:77:"40672948438740970862493667894582355273445817592820961034026786923017405088605";}i:6;a:2:{s:1:"p";s:77:"82856294712020982243609092866618447605083422559355627663514629271554457332707";s:1:"g";s:77:"34416040662169956671456751385517722858193479998165430251652844004160138167335";}i:7;a:2:{s:1:"p";s:77:"91504228250396371847303553559751396185779666715439286732407466045990416051879";s:1:"g";s:77:"39857698433618226727810093242453642286951247805632328011233975273133854259843";}i:8;a:2:{s:1:"p";s:77:"78914515436533736321800021501068621041000513624431796114155043029970882928863";s:1:"g";s:77:"37699575057133597258692445612773858685876622718395748221455772617196222142535";}i:9;a:2:{s:1:"p";s:77:"99887264459001756020085033457071600892669533881405206061916150024685965253607";s:1:"g";s:77:"38578248010462555085958074389688939528012418780656386569766828292349114252043";}i:10;a:2:{s:1:"p";s:77:"71982351514272312570866502020135229955879457662805899747226636086639670593607";s:1:"g";s:77:"54577099835257042103340960450024007160493073561557576008109301120391117266123";}i:11;a:2:{s:1:"p";s:78:"111348005627100700173841228663272359096490475124040160395478639652684669000219";s:1:"g";s:77:"31457852095708016675951983917720277445060540653267088126635758197134362138891";}i:12;a:2:{s:1:"p";s:77:"92953401211845673182089220656569865148723807400500147073569037899535512033323";s:1:"g";s:77:"41697366699394586852286014598140272134473146487972754852099109223623378584697";}i:13;a:2:{s:1:"p";s:78:"115301894620266352952032164020027501572840286962376521701145557816371554998767";s:1:"g";s:77:"32871160431857151288198737173860718706139469895659824990992316603505757759857";}i:14;a:2:{s:1:"p";s:77:"96343471923498879084781358157613313091411861663579598008154784412360514421723";s:1:"g";s:77:"55471240482349354180574404954922529811817125590976473056110888054444317488871";}i:15;a:2:{s:1:"p";s:77:"60729504492067278584961924278016428606161139264005501826188762335152973539579";s:1:"g";s:77:"56444400025969977990713140047023590088408912184719130874280347851728019320481";}i:16;a:2:{s:1:"p";s:78:"113900325385355187838261275529566875388679911394853338488557608315621335675047";s:1:"g";s:77:"30375972193127924942262888540925064582100876646765197303659879193919125525653";}i:17;a:2:{s:1:"p";s:77:"81095496549283199450987632777601843345505533571552820491363946821274768596407";s:1:"g";s:77:"51869176606892317236374313168422430251338346091156761852451813909920509557627";}i:18;a:2:{s:1:"p";s:78:"101594484068704391452871318220948198964937558656012060633086457558349057524139";s:1:"g";s:77:"36521940857765148936706502186673044141636067645496695747248640910066892220227";}i:19;a:2:{s:1:"p";s:78:"113344409968890085710229548598885666582507318886231068563168211690913303412443";s:1:"g";s:77:"32565192853647007661066738760059232931455020519838477513190586740622229447869";}i:20;a:2:{s:1:"p";s:78:"100865157741942714006835672578320572215808688934162933948109189253969530975559";s:1:"g";s:77:"31353399506013880294099022097074882435311645322088758615920268562945159134875";}i:21;a:2:{s:1:"p";s:77:"58987748040478408081756831145947205673749409643180447005095787056716058221367";s:1:"g";s:77:"54681552249621678212318335368320692079388532771163109014194315264322059702023";}i:22;a:2:{s:1:"p";s:77:"66835016684038007440000941566894284049036931784409949699003105152793759605219";s:1:"g";s:77:"50881796590678410195198715025013574158095573900962476288005944437157669965905";}i:23;a:2:{s:1:"p";s:77:"68569773570402015506975522611411067971033537591125717654141616891912891462379";s:1:"g";s:77:"32084061487875388589170475560472261801957843058408561030464427927344624397317";}i:24;a:2:{s:1:"p";s:77:"89041088472716011536983496934725702392491528482708037595583928300741866320783";s:1:"g";s:77:"38064663462733312563721773041650262730115051360751432386782313487662169550555";}i:25;a:2:{s:1:"p";s:77:"63506885046592167433260234006962661577294376048832300254801217057060187778567";s:1:"g";s:77:"49889663046133352178991367103241000151089916129350960530695272841039003186923";}i:26;a:2:{s:1:"p";s:78:"112849893518043495404513869737282700616865089034331683427155137156329228907867";s:1:"g";s:77:"51198963761086864384430773699594339100576142234411897622813713340298644162715";}i:27;a:2:{s:1:"p";s:77:"81379543081685837790443157894616584141037060815155365981883579985363608950463";s:1:"g";s:77:"42614776409195525157609422485492905089299192373448738791332101819922775909431";}i:28;a:2:{s:1:"p";s:77:"73245936509718941037107456038166801410799170427973092989082747001086626266419";s:1:"g";s:77:"50625914415280232833987886929254839755338573972368676118496496226311022209679";}i:29;a:2:{s:1:"p";s:78:"113777768884465651623652520617441431650397695440681571689213021935525307889207";s:1:"g";s:77:"53230261964441050208664489018248680823016821086100228556881376058274887677429";}i:30;a:2:{s:1:"p";s:77:"64182686965111979612624371637207151576388157490672453099264795411237003991127";s:1:"g";s:77:"42739113605751145415527077990412533655324276070946090181609734493453094017981";}i:31;a:2:{s:1:"p";s:77:"64389758512247996595870401541350246623588091081581706581580796562736474659979";s:1:"g";s:77:"35027570949311106951646776724538831430146702160360275048978033699268366887959";}i:32;a:2:{s:1:"p";s:77:"80171209426362772759848178439308899617715023764855386038084235620615003353847";s:1:"g";s:77:"43695422597465267267136734648314440541023062173689900067656462758471318476127";}i:33;a:2:{s:1:"p";s:77:"78661796419493527928157412810459909523754144396497390147701511341329482510003";s:1:"g";s:77:"49752898964251876428709802877726537855856916332152631351710777602902687301333";}i:34;a:2:{s:1:"p";s:78:"115526308257340400930726289164227427500977970696409840065400171497064778851303";s:1:"g";s:77:"57455831142226363977301804360103763384570180363822590025633870121824156777509";}i:35;a:2:{s:1:"p";s:77:"99895854914975530338182226257990200078997854990974668036162249218262310892223";s:1:"g";s:77:"35234291282377508941734996504627025488242912267279150273638077828536817312337";}i:36;a:2:{s:1:"p";s:77:"89463065045661035231551266606118011957564752892942638731336758478484586730727";s:1:"g";s:77:"34476840145197409328284674202809241607868307470606051731302010755191365289489";}i:37;a:2:{s:1:"p";s:77:"64624582433843940196782532037106474516282625858188798258052359753710163749987";s:1:"g";s:77:"51907637552590521292421620324219346043776599340727611728777487195410015119421";}i:38;a:2:{s:1:"p";s:77:"78551241184092016983148992408241606401944659592242270145850487925990724687479";s:1:"g";s:77:"46347657232133823282496986294357257279901578280128017968110374222063339245955";}i:39;a:2:{s:1:"p";s:78:"110454815842135026622014358618557565054874733818955200746804642117317104098319";s:1:"g";s:77:"36484417303211228180239343081660681048447119211446094732347020240865174121193";}i:40;a:2:{s:1:"p";s:78:"108632820637647054517954687133925163880485688322613052629730339391168797942159";s:1:"g";s:77:"40936112635569071530887793547822555014118053761125242378490069684895929829529";}i:41;a:2:{s:1:"p";s:77:"77384308083436791525512502830035429654641530154237012658177043914982366384567";s:1:"g";s:77:"55266239559717320485762938784631604896441023536093197675797124339337266057181";}i:42;a:2:{s:1:"p";s:77:"91486076718429369045114077207029983275174180496205286263890757368244392884903";s:1:"g";s:77:"48796657615906031864159766245092760843396983449401480155814650683131578645867";}i:43;a:2:{s:1:"p";s:77:"72102224509363634446570802115759927713162729477388965613331493695110367533179";s:1:"g";s:77:"41338353646772388776408143300172508262741803968432848378357177766068794408805";}i:44;a:2:{s:1:"p";s:77:"94893543718943583226837269269711919605950724153318813366438966165684305916159";s:1:"g";s:77:"38199282927838495009291933322760804607026986374974299862170665602978303904209";}i:45;a:2:{s:1:"p";s:77:"80059845045249334967430326313246226499113423192254298079034172260496369580447";s:1:"g";s:77:"45202772573555806321013920339438762194895562399493007564473327311269546531823";}i:46;a:2:{s:1:"p";s:77:"64583990953768472760679459616315123765296280162588354436500849819674609757387";s:1:"g";s:77:"44955507918033524308531963911022162716703307186357435333598757289790265527719";}i:47;a:2:{s:1:"p";s:77:"83254860662706746455845571422799438616170338867584794032169432243745310866483";s:1:"g";s:77:"45685643686930303771863160720615786661752116869179660967345997698324429835601";}i:48;a:2:{s:1:"p";s:78:"111129822697130897903264343602791707637087284640784825057418415411648814509787";s:1:"g";s:77:"33126138893831271012720592684933302917306863243253992047196592803506800432571";}i:49;a:2:{s:1:"p";s:78:"112628096381776405952312106536719522382375429360429462017871313236853832958303";s:1:"g";s:77:"51091975906557044918432083900571651694499066453285507781185412784968687363375";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/3072.dhp b/Vendor/phpRPC/dhparams/3072.dhp new file mode 100644 index 00000000..424a8811 --- /dev/null +++ b/Vendor/phpRPC/dhparams/3072.dhp @@ -0,0 +1 @@ +a:15:{i:0;a:2:{s:1:"p";s:925:"4315132667335984456963558712492060257344696532540937013667412533700786332247247258786444946331529425538693841794686692621963051684018984641660725584842468599352742337722223201982634595644711492725368912027507353121978199347820593108558415379514513595105258771165222489083806690898826212723823447178708312310015373887298513452146950026717495376030244091940242203446809569885630514161505356898334636153936070047367220821769019996145996674921856277925251065184565233969540332955418598061766148428574177493374340178989369402930754868614979883166971458256934371493708837542870985695478010233708013626835966959313713197362623356634272123467707869487094589087968990428445989462460406369348689022330895916889128558466106229221162192180749978628677142243021374310742307679557586483044238163020079196922979237255175192476288945150100440813256326420527963791569079099711040208151967784056080661234151722826312967586919459049069544595121";s:1:"g";s:925:"2350119018539224581317183252415847335247362909293949583819480136047741271969210563596649306799079103843283712608283697540038743924120135958735013054518494349752063516955891717508379841175911890322417721338576512047885798171488037467431031588786174344182791056606242306674694663506097118828767635753167597448122585958034103275031127729578917036246768917035692891012572814906540367640104398319921957224941616190939982690849656828763901639933734397922127816773424555700200021019174059057777026847966427467057235198647389332182881908470536626080808572135189622957429698028030428044157396315681162976893222692006884962413038607537527910664266091051241366061457243810458757721091006903760284025909160005959237519051794063104050293099371887370635729203845201869557256890658540204361928706031866241870843244741068763076973016656112599802181801697016020371090086607874674384529955316111291655883982681716521633771282897455399026015616";}i:1;a:2:{s:1:"p";s:925:"3661665842190298063828176732846293640919222353827795349002605449065557880062145536666215271148836094458623660611328032195792228919690193380500724986215448719904848955793022993600439169495143330203461054069338359490025694157088096493504605335762051029513597551864863947693713477128581978728520431114298665949113705627108090586184073139382258224813404010706205790642551006296863042075254071665147777776707740858091301988442189198081921256690114717697424548845597164325066843431117108985133946191000161228877154348382442536080406753876146079547573447857543506316262040659783540306099921979385195412728403628469824785302447054055747600216083577156808284736341326726682474972377807552581603315824036960973343372464052392517539250145685441328689733886997264420951036267016242264588569127122203684662610471625628303236191647272486039447610039980545441951351603094273112696986635159781389581049218077713772074296953986550297559008921";s:1:"g";s:925:"2330013033015140718105580780000814417623950544622555681637035317524295725985949517727962022017580560547563293597480791009886152631504784946677322944135615155582592846014602079733324813222482088145642952216221395168852932599656493754737300222260887305133391964292346610726404829045255391259296098591725039219968328706584519797363720774340423627001446486074699770450134070947337857854387198789919314090619138465361996989373011459061160925315340539701819845358607233491365039690895811239620227497070217116286298965147073584201527403505009593615264975257954666738146127058521902348882467540296125841019084888051918146042420278637339312514698888677245842128922453684441718030263138973029024870038115729105821493725577229509289318197508146609933674599620814192772205023194161979027879633561410655349209310980358414894722460169598481382405650803898146510326139881914420114730680235864699472699337179513801157570860074154514000403217";}i:2;a:2:{s:1:"p";s:925:"4620590045169368554532593574486202350245249389315730607028389240974807061808989952188740674157236839851469650650497483374139797687030615339039402226480050369784359208554913778269157347633279686389091589520171218211153475774540415272645552458706556134264327307561935711474110720994428353060180736512077595956321907309914463979874348215571655054910359837251879109577142329727462223158307264068910944642564267328731048817042467565187797605740572389597584518183277729416430429630091936961437746628672624310534088245570212333926703546043476499624595458682817300820597092118377346583224950405123201291176579571288281289104180962553921641572678604773303321625513910966201143598343781696119013034400887449687812871458717959883805006700972858977252426902453658446267639459438200247621387492006492376809433765553636040874894552140340528827784386517413645617181947670553072125045523316044242271231323303187364368484947845489395421734929";s:1:"g";s:925:"4366118718728026129585368339757372747812283277679825792704429091458791780869289357307128615576667018996813659099222894673691023756762981972867802440998213988459504727363294037678614751628490500713830852051760642762831242205244282977478949802790510566492875314319012587861033111945258477032234584165020634787063563060226904559488259306239403942858014394292642228798899319433517328106045603152714304240613974941203373109764879019335121960200008382571226974231358956539289857770194403260628288818158346951295856345578190002005441993276348035896883906778534112627726343274478915237297608006692168477579982259987288186346003808143068013463951511936961124877635383555597808864932642690164727423911499878793170724403696380993997906824723746511442380237096215284266757159081815684624425650789580133463950720950707773341517945032379999366468344661073766262067221609371947035046592874149724312790523190033822151871604750768215833346301";}i:3;a:2:{s:1:"p";s:925:"2938996187439733278190929622522349944345060330946373463011322239057071445903273028665349335001895437955186644060767951101216675384067312297743697834773338556625400217742556174036456199954355031134394408805378315265066615370777047296269669781228365702751437327044218920674379042960278113164522885597710245635397480146223856309389521917307236756459113545853621634950936911142251242228542261800588746461446890339913379337949235490176799076102212171841211590921810552092147568351052877446522006565330079402644310865663450779556049843233202465628767590866799950861383808769840495381903661354708277489471381562306610182683334111925952147645515746482205266484657014142278865721433985338001729049063402403614948416123352207951387320155475974153744398545712952250022395899483389410938264851959185383988391347681515064735631000919755110370081239209119611210717600091760641914294069945948628410388786450298574688846037117458099372003627";s:1:"g";s:925:"2188180360592475474255511510558254820951280142973747406967025596302429430733726484610414308155762329822727719986011952045080143567144989598532990383934540349664426078338531224748892840652053289950123010405619591397905078626903456138814817195006903802298782223061589795938940654403773897504364770149759015558282613426827768639469348445280997717425425821254531982205265979720559293842189517050726819531061697207390209500076548816157640005607651402255706562491859135623242147151448088299859950249040363472544692449982136960186451329556524342413573462314348428383404582280827585580746192926542393278725777224013196865983526484755349857827193710465770127820637602199711325838042273973465637657021369104329753017416777442203610305126338263203859718497497033721924008342606583384236874030750708458957210268975685066365072240616441632985559271286231364010642310503874912295276279464065613912114646430165631609556704960606196917356495";}i:4;a:2:{s:1:"p";s:925:"3204962240800723816455471772500630089000997534792113265087913534933976812754741314152333161722136535323947418298993649955012010494800707515359305183271567204804336793561943241504957646985792902563473357563351154295683729740121421751902177385001324509438971655716930862114523297055235704266831648792801588667356727807779911488187335905720474875954132537802816473672247617675497279606357395091411459187790088423865644531157986398649668993393419306383003614731055174134147265802542990950181076842959362090886536566361672744257109196212197301596711897255025124713698133763282484725224264158953521633609828865037504253513222648530444623441214553533356064814153695805473899049725283546166491312381083067579387836842892134578905238980750575603676463825053338003879697106285582414982603208225997483259925008443212949824045922036211598364431099546267769245715271619696571301564489744087831121278703474351166052668283302487804660723399";s:1:"g";s:925:"2478210824019551512320915125791813539617224957203021574806979249207018870886399224961077393046503339639638016501910140228410535010543227950645082702730670128355633599633043853389737970884200828312283306402427477457013888098152394453630875646221684016198476297387503877720665978254224708974837278936309165678785757023904855038581289350871058547109434639163447822004571482221163644264512696822041373244545734333000574397644794101152145506432007404691930795867589553966229970199464105294872145069453531632860004871327511300984654195341632795521954496300167312104321888325452986799014818028629496909381762367856301721729884500546156599040930590095260641171169582643120839660452666595703196302210006721682874519760535561899529892956153506747158975716774130631381604630449687840599933523401758295813794558297239292235091793389815370710029502740492588285871904916835615638686399306444319652719565021842372271724191724564878652899605";}i:5;a:2:{s:1:"p";s:925:"3858495699596293898688375773110502441666969420477863823398805799498715509641562514051656731242905221702517081547027427844096728462563747228147262855326430782781133768087051811345578632161234632529176390004908409005592450781741043991144437364416255263991536844100492335985214082240310081219687923906385177494626411448945508588432558284500479260995206412930429039508366816784869690714512146751344758083063138616759346381314079908598351217466487073343070055106516938750299547561712449231665818370557327336756144407998326862734127162566508972390201780064268781728836864341723391269404459991801391241300508727898273827505495076344038735675175327462642474409362152783304320466458748710388940666897294271020065195620828010332760249112589154219333978627293681202156105282137065180043669859728816043574692794562625562528990196961932065149331559939634377062532299875002483921931262911101879746604320555198841530133860397746299378909171";s:1:"g";s:925:"2886770992828075697537865453212345955877233763458923987749867122711936037323569999431920041463158985162167680556614923476438031572260453739278044543413267437317254963067126570493942182096870591545209873122677040821918637446656321776278694479543818356320243755830549186685055812353557718440720576848387587878449845543328582856033075009617490657544568050050627565735736537270305317220182851115960039436216682573899064906440041083076258169673094384007249539021638076358510803567039584750818577942782544780707619050944193479637205469754870583309276257546564407814918646615385884198525006539391582468689218016193841581859343402584321850321179203289140890633308745187336976456718386359814499595610986638615944560401277989413598915531901666808033711396337479563958570717739601600436466348932010006348163460342190614134424271117916987578687455994528258348706062007249333872007231347444454900634426076055451830224745288581360845627478";}i:6;a:2:{s:1:"p";s:925:"5130943436634738151705983389375848779869639921630081642526416959069902317114236046229660665455811266490019114464604946115159213191020031168168934260240370208638654661224411266801294059930023003906358110167332559834781729140290434226060866720241002885723300338170136670588251919750642109993266694093638580072006610971738091420452065294660969649783031963891317158100456532483035292435217535729908840133045505215372042519294173893500103351214593883943376369844040124039643965754086308458900341243079112441910048778603970492763910684557407948355396339668534357389653826573386393829228181277223985599852219898165629315031588362818823320107829227064897785017442539383052775003927202548433739462447033947909704568378992953469486988508785729088846061201035920027461970780780005619342436344516177296666848839057209008013560985064308437927467930182007480635819670195139144192726361522119994919747844325562336361309373139438239770340527";s:1:"g";s:924:"260934354532320981603346232635496122387716858013756396769540150915775328937528977396744326608481588479441907495821544047901506468212289539823406565234667220744710916377135092907432145546725586575114564276697681144703692013998160742003993464829802606364074051703138197052383691108529469174089994578471577368442017913387128969303763416195571202078647334505305658123832338834320953526264258001677880912206470170147306962815949002226615725629876836187127422017883188599155347419412766452003248835237735383926323738507826527365200159082942467837860566008919490947094664770207577205258215568849415857873018813254495827577038620419781260925766984307393735044861803885064315173715497646285752656365376330908367814242240442396593775595814974738181268072163021064089047877008188717956674409081793607850233146167883025620608270429316190958126029128628146623463833608957824959491480916435770824635224049032746305841209922133966435713575";}i:7;a:2:{s:1:"p";s:925:"3998840508039755798914320501014490629633052238467381119305554316434989486292068483947090716493975560622301669729373235071025195401078218707185420229393875101630399207091215056995992392328139307281469826040928322742255751493207399051987012084305120865669683305722438138119183724588731142858758353815441063774921032770684639251029994539546020279344296398617212421068732532036375421965908920123116181078143585688105962725633632132975138406008174984532184852949383093432062210148181318477580417338770460510155595650601653410411127159435659493085820168746161620985855719309306349364850268313653433450566430609172187269909560999133704305458710444090927702514998592430411602512950950677351211101786937984336899535946914086866004703969257088260831279147313068118927684780067602116963127114169381639014582713965741737756250918519458049220786586497590905817765259053986430610205459529957290191421398536494800885250298043501610812086059";s:1:"g";s:925:"2057658023315995837814244302674473620221265305450883707220933348948320037525210388745649180389426087096994265870161669866990950147659456065103511412373045200462918715811677244100468295446635609971623835314211125623908520420064733901198155337704396419102815759539371784037536019669543759503815444881029800352829496591835802768152878613096427522151951742326629173003090596367204419211777304661019230236712647127510964074174767247775500850831099969972081398582452465813485109958498709530160165023164241692106229959616650039604984445666426834802188289028501595761306529808221137567116017979084922372919440488146672329182636452142505034221383623140884633533656641179188863902408723787496018605874598641384694800760826997534273409829898340972241507784345241343119164153030997554682570323583980126844499905435883099703450893660347945613657017744862281043902594543525498698273068656471269751607765332642113390293039115043238564103012";}i:8;a:2:{s:1:"p";s:925:"3052587646542902635517226086530951609778282038835979836249050671063535821665881064115534194204580934832939396328177556330734842749443237143248792953029921041776669549143453117786515142880425148009081292117059998939563969347201402547392105917250085128493129385727535383102647220914444263467589044844337906239611382825797699113671584199753687591287631042586031195659928551456680508412407670669265264088757923152615347875842767338023502709093266175409535257184444620178546734871467900590765277006865565930758293589914804946915189387085191740529942130147830492793703181070245326162092621723033190789966782425551751916096436898391698804721111476077819753921137870698340323664493890573693833039924707736103693436805757466587652144690484910903191505956908906533026489365552879965712849384865313762910366975745166199472841164150446248515130746369706711873108862393430213900655618183304463659316938365139115981162958182988581222516927";s:1:"g";s:925:"1528970316478521813353997032259747601735191992648561865246322395311799713363100683965723354220895113167576481333105953735058063391855371198236588067407381815001036506237172664629862905959335540447703914728848630930034014414897925940698068311756073899855838490954565219020692805027055726873359828123353015856374380126481052959369002908628607232632399137305471086503099495978391740843530399808236564911758061281813986256460744423707435462682152330795942459476567607367164628721363594929691377187884244564552802877253956518878163768915048398159522668854881683427429061145351151903554349930235654986427715339756801878218559049944808960309764150281309751390601707948395300869715492190359748972888505045582622937580005700313037128036774300920485981598441497630716284566747825244929014090865919371992307502418429354359868713615948277531724520475602562297248371114923521826670568579338836795789101865793989006496968085530346267918952";}i:9;a:2:{s:1:"p";s:925:"5531849879715624114545398644990869738005678685505540581620042935370633299520260313401427768894146216872345400617660584943174470760956880835234467871497601411655568407303235347829600176104883692713487675318046495160134259363627993949633466784575181041587431530962681787466582441133960809822774283217984130286952934282805180703291046761605129877507724814121136198583199545178203257717235268348901238327943885189227904444196292052543399633947624052389642080706804402135633670642032342495348069576043782932720813101062926203420693682305253390383204671688886280531577438389453577025982803872867504594741277557443656199282929180417954184489501788428410224813973812875429988763466872540945881435267196803982267101116870704184342151713958770562162236127406870017210783442933149316190678070324462159427454290303869639001018013226081887979930030978578604010432508341116317743577984812733454143165340372816341180317379877319200301319667";s:1:"g";s:925:"2917203507661957440212871046481478943727282842611244779763790996317687687796653644637232299359266378464863671571808560817232238482565725501100973646925473408457779074219592120515053181961738402943826605763153695887609945228222137505734408414619308585763571774670754039876344991582623796377907891591585728148008903192190841789422084781332813849714793603695928341589810634401241616185097559026709733935153380643027522004141273257092132215475778754534758221475473429898883941849856488515465149480083332210865241632308051267913594510037802419825916838542556176217263933025009075909913259028976931672933709617760701659850089187121050442463220999583880976029754820397051904842386028835760327721598037944871605455638114393194929619554005022189733574969109237418204065654064456677392819888022252866367583881778675828738176280257941491838252446519301369815272120687557955763759094560889666704564956244599447217316300475463318513732796";}i:10;a:2:{s:1:"p";s:925:"3780562069767071462751322994770531351248326639139746208661386875034130015506630130354418097645520065657264914599050724477554706479661847220716768382857055005905302806412621168013005582588626824922052982755725555701387925243647831685319030524024371191569096439197899084877369353216936786922609541760719345429409766670866201565199261221853312704476568218496413509455308603318378296585201025188261985236431551746143598777692007988149131442040972036431906297580587606656327482072932384415225423905971270901365306034795404320749074843351064279683995518828679129623086949200669166019135890040877501907773598692818560350813670479817846008080880279105959456444566616656244687337953491906818279020434273168222187571812479012408132683674329632467563988095817585564356500304964862642571724722567217202489476816879092879112960700569233233874053585011615125908594694514165251341082992440179577254889736354944330288242522604298568218134263";s:1:"g";s:925:"1133287961193943111940342976118103953191957737288544130733159585583521695386538531116451012469637228291577079786129597894401720014158983191228672539807231618254286238108067446684551660646160650174057287185737727852149737778835119754106612692045654868897144051639321003403494071891433447103764027502646743853264024332835367920307722291151158519944255275084346803184632183174584156874227281521959717127362792889493841915783229452311712061737832597541029083298577988701022878289226661362663559803846378086132409935377291038042135005772565193607513077196748107849775169080596426552738120866831206312518873271453348551519887940616728190459956271984259492893170174757364668932703190921245410930261770880416605148022192685817806998238703799851284384393863608999974068468543901987557271301629525606959098052879304707973115293685698041864520817193468017063053778347860274934684964825463007204444869127699425044400604879544466093146713";}i:11;a:2:{s:1:"p";s:925:"3068095411998188584974295316826692234024209804719859764484108486572281679715071972548018617288096813401480545524367104865019364141719603211985383019388112559693792867918673138698433559285788103941407025538360390102089759681221369654397361044046355244026937545760739874039629458690284054831150144185217308188816082422196756222298053288160968786145333347037314844621246589018144013343953044545365352430766116812302013752255034493601043513298413210051345468193554254405709248085595245129593291443750091309171217758403287393835473936600741503786458631805856224113637086263988893632533383451766915290972161134332112947134792182158732064375840274215592185596628615489952577220097912306990091072175658705356067742048210386333029866371918286690399669681268420581708391550751044332001829026704722537807437823148325746846108596888514608080975020725871152050625645593846665828851876972185832543501226148782144492486632994901478570353477";s:1:"g";s:924:"159646077674815541181898471066991220537923963782148392287829832362514240966969525519270080706227499541479736397774272092871694088307637303456504900062713028949632514722351864440063698772176239061729207464996707945061729052663143361100233236046404449925208877350949615956983649392618970848410825873036033300136570007232661091399138793011759863976689419880440899963172456623782321164251274211971525927466329495674836200825606797638605022890014528854855363018329634481021113432968961232928182204812380173656975430286379350298654148640494598755820163775986641678506596595022674979754860369451813519030992570439885496972635686145130069609803924536847652164217943217391745627063861047656164990738165079744545323407641370244403751048259215795551277457068123515482374905320163065825080982452050801388367845963408590818221498979145321370138496712399590229047470037324389568512410801751728974904386709610858450879303893490586965176715";}i:12;a:2:{s:1:"p";s:925:"3367777398549863878345148780352792636611560568521571798049082045574910180885005793793126728459986561469235955566557139518336437368333358883318717635927678803535695555323846136098940080055660899782228359404434364204499739606477885672504384363680596103574952129514920432473116170872538969443310045437643992750804155246600739318381291924919382044092161074120741040663613761033649123287522847647043591147210241686928207042782865374261029266594448565161093433189705423188761808597916029005700389907296602885569165456302470201268341211857068535407463170382217821960728467862059761591092988384122498077996964718801898349667875615762194002904054620568439838282971943978910671633779795730872091204472155035861162792711306166527620004280453286569709407237219146368163001733562186610372433135202274242049506939264129559752737618658036336838247421419934890192209984634346973630788615414331951553807993311827232462663277269893274834815771";s:1:"g";s:924:"282566234821537490920271629731450751791326010830798582697602986370304196814692766945954814860495621040028265936431536156879768298268960424693075179327931900024792860752655474492139099296487961820716320660945382657603902779098216755977959044903615939284313278343537748123737565833900347186254806630856242758854544959974682405386328237045158616666490226285723259258560242438631173878709623850577125771772686579589896392478577404691200860585558677662940672521119454346512864214396333163525262056860462309077414777119126023696154521154184782004242582268895380068841711410787973048412003387723653218024570006248657732179556204944548185385219665849088495644860518610339322248090941354949187351195497168258030226507789218244254891196207707938136301397036071407986259710377170196867939904460166199673807049914536675707863908920489544130315256957639292300855511885137578488817087453901342539712110297865118918707118619415424775167895";}i:13;a:2:{s:1:"p";s:925:"3535384272507739371390456127135809600186371214324741418254646290954611392001303754670712294728733042167012780609017296164756809496173833266096270418632868985081715544299268631523609112391637166781088782274258141895327019496527187074403033663813523275310386981896554353497215916757908905790000167941188609984283480670859772957173439728154801756764969458163972781505343070182164319814653992820925111164323411776021534453827602054973434524749158514070173127495515407230002708401984918054805901149617888660796149248646762329259738670964578005232274408294658881682648095451587024978642353217735565744329057331274791772257390900108305959207275594924505491121911140571784508204909027105532907233569037974155947733655073558194831009338166409805336375694237481350665052137267368520421694282722206354086277014005346758155612783267077100275255177466584853168927390561841803896678741077551600950305942328420975221043027695073323234751603";s:1:"g";s:925:"1119627094127766829772500517036991083568576798245595498908286128578771869310573796614318558965773296738305720838059734422117498175277568498453999381892211638822962310789626180531534551448940276333857738877417497428774052153210839843293436387816119465485788462895141683934018108493106429309515246847317086612993115379179025962781724441313149237529166235928244893851718231946382751850142392414570892539596941566408655018573202199515090796201983901641953539712987904042812508073257182740282233206806436874681946401374885573281075164038391538943538739188358560267747478564509764088420575072117739801179730824156119304707225171826233403806127524192427836830907025371222786328472434381076462861211218005577398906174154337267095852996974622601430030358592190085397222144581217030220082685020732184769583309535060349556169532211738543599588804873402286879771608421072017103605372843541753819986226059435555938653678169271805135072704";}i:14;a:2:{s:1:"p";s:925:"4562194176144915101277745005681642835798897873495474402608365237746498633370539910997482478061801133410931468922790595608494725996965036959348492966696919596490096103508729764011492174796198191791155909955522446405625791491856359473844755837078803270025112823181994772241566047803179666255388737745465556951461374666502425494234403038996248077021695256107962233981604735599024291065871109632150139360918869800254974719289688500762129016450664740707011409451726661221355954521623690646442803371069043169161235234437004307481376146993512198303964849240704679431973961042676250710936961739893678332170744300669566464498778887300216296271182576972042027189458709055591030587939226922668108333380026928880780276365283307970658783557815994186092589841511323470715371300115114933930080499531110461367639031194670553552560568219145338631131587315044373227862105549876394176147796261524892767754722603204009262024345120417781993357987";s:1:"g";s:925:"1783063526443200787273402874050505315277582361331137583023716558174565654507897825561438236925691082458055937563291294701190532975370225129732306964365080034548430202086336886848043161734619160097756477070297570704155217306045516212846557646681696236719960634662894256288317478659187183031232562007126356278206248186444217073475086995834637378490918740251676685852817074972991205125364956751685343096061867387727716656368534256629567828308240954068285866099855203072022472167988681527977696446376869763607960806831605221190526541560948897865708484402569295854151464572749555731165228888295734781820361816426917777384572381759890872795386961361866080348000867683127021931442615911255342253637272123698141261912663138878997606751018377263447620039560096755190075892714993610328525690603097687100475706668399890981671741816861639279982388272019437387929568855179248661068150537105516997412483935882350464469157999820932346920856";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/4096.dhp b/Vendor/phpRPC/dhparams/4096.dhp new file mode 100644 index 00000000..501ad34a --- /dev/null +++ b/Vendor/phpRPC/dhparams/4096.dhp @@ -0,0 +1 @@ +a:10:{i:0;a:2:{s:1:"p";s:1233:"583497364515534144620769172000044730923697202031727504127123210239564479942377515134918927524784673980579074340461063538391526339824976232063025052904924470995749954074102702957089466315511530623356782205508248825740639624859740089902822135926045166645045437903927933697296195582696814881142738510663498379289235009495727479310527226263007320787605409676476477501993212002640038117065851293829333612131166916933716569722193363513937135458901235668624388058292432629862283052489837307563350505877460138509873965637006792230289674917658023203501223032739662361448420491881958859596930485891068704262657955024300362541802845350103517222898174052640851695040454504836166630292948661375262574940854275967111471071853533381721303713908516806907549838677153020196484939843082018694927379607360137717235291722860519561948094257242530620881851290634352815110863032193710545113797755493485240688912927875280880745272135687311489219235308680262020676069196477067527653004361116497758712463399308993868628203477781594080634974306163916058933220903803140690960293459749358282932918972189491185206934138125324705008321948673334974315329955486619636903641180912157388909885148546517263298358704668849000317658586232775537242080876793052575872164717";s:1:"g";s:1233:"127968319472475344331077898173865318243419891774158869711828718403058272519395942847739630843783440496570407521226003155993983926846566690798874858577718455391682455892223888282652593207801696315984482994206748236808639469753159247631285968088512433340338448500647218310014726139052545519914995413409746565031526159760387848380067349701191760120575688747503588506736225221765446130332518196101187986453740722500270894816925266412425389536471469381597650467785082390406765429913443213494185648481561518743324935186205282661338295676001165228783434910786281187086626642658036158298936580926944325449474152492970083106102594548633509876112245624678116554682380902585210405140435485164389739462713596222796737961866604089345760320729771435028743520537401721331612703333892591161293038864926815371098779656090361303929418714804579407604727579892304347250984412867344708385548522005435390223733841611446899929639968855580274150749251312698516786442922382658632826376729122687489867685434294153633514532824081517876628181473257432770817442813124369799504124961040791138045479518041848867260535046612877228124634309948497345074597014995577791207765501863118075962822337166339167526666330102483819574318799006786826531261489174152125772534202";}i:1;a:2:{s:1:"p";s:1233:"644095053480099091939297858118510986022393648400040771848173413661472143191699322140393580778380090670032891398559036461541070211706428701541351601818900768330398818096052423231077739122485148413641340967644528288501235057628326779619886675978303145968323618694464033676551692515615682460530416294904707165146157144987891911761808025802411091538918844009954268729819844953069874476050900529268165258481055331546080631033547922767585983393765655588560322256827506194710671637768772870769834318509381421150469657835696842562300393152113399655413282551477993943983874755875008370601615893956270286590833324338386236912861203288076957651978605993345863806728255193575092771952494482786247355235879276588474691115246553942882015825194543304753856233378559305533559337703203990700312254477385660339915073329148910781131702800669269692100691711240004144672213498457817651708910320204007053298973019806994514666211161604549258750171462260682389646997128719501642785472857904319090448452035015310192384694472666994345420665249463182056689421284257367184727426519626237050683000133883319859749913454557109977645943797147207761088834575973395913233371630670280400262776509177911655348771924491186387978628358113653228880012165121850781835748133";s:1:"g";s:1232:"89768691123282200273250835302117971048482773917025710167907764833444870099082491710125785724737126849201414977998097793428716907619355631215464414042029665794351873443581002311352342070262811635855982355133446221245675640049081025694562439753757674961542906344974660712521171173708467699171410627857113329247881584047267375568447173390760619832999450149891575517887784502344444374191979674278777530444755493588772031447750816361643891131010868034955637938063643040258792797050121847588179905543200414522189803497522647940506521080392705055063912326461962382542669924669626783892289923537801933181809583637334195726536873813665338365672744499977500454824015782399115735050243010932135563292304832389356097634421958844359608592817067687298260497048355701221546321392944037624125460251388411565536044959602093101251148713082901120310712110250945846908369537893593889855910577138915381937493103881427691939365101855663162968517484827254803505472068266675648883873179408126913733762685173740771676195913722840849674515884752692489338505861489008608258410033759076296295109067248910573099437033937947587453092321168613438797472805045901054080309928241664811040669679366909370512498557773486141885686117459727194901102461845307908569317600";}i:2;a:2:{s:1:"p";s:1233:"532066646043903430528531198799450191282175598742954618921250001448735653262660514078933937412646564856328300432618349074670575210471137479308656599676782686029867744041341499987217319442585733211108770872807629457693551738273743163912712947991902397196643426249471123290349309622852982951431128523211363481720767632275409727094997652747425555700771203910408057673037946948980015289661972528916471071786814695958220834200499919631633188207596644932186099425834405442983403992952942254049551275570962621513810901783576680109840078393906038555579747674469371579619364205996024551188123841158209735986236108133045601317981547026784181436533153185277324288880485646894594421478688603459165479261860263389086018757182921909991153043223366670612538754356707473045271074357478392653202116322497521243644316279469134695450721130875739701496153521607873295760755658643712384624306497896190995965732533939539036696648605012419766798899358151978186058585681072604170889939882081887687877039553196786539987847117171555789374202715508790677648591509775834020846216973047985050084777424619778972017460676420407835912828488139160909012797820681272024981216651882886167197915950461158262571666050162064889928434160092071622433349237717394286981570903";s:1:"g";s:1232:"88019875487376264806598595177212842685348996819137453891069396270876361332627678497976776584898521161583263213197650880795825901107200678516836793986000818559956235836401420020977196840780591296240289055489684623759281051849436675569974566414464349186834037665098011067297024633109006155906972081508954416530556429749768193864239792490253166528742357729061562213019250198539794737195535209094996535044158932610816334246967178866460038531092201721314640872055917692442887757298906896573704281644069767924051562056098464867189799317199958325251056019942124663808656713656134457210444039223292181732025000379136084470942258525079649944952250491152670202869296763020890767014531251289534932496252825710973791866862020857292162810797821091684253912935784170079547394373669953308727375174305241288914357603751765176389654002208740589896011833020113850756049943560630211773283686863803328093696753873577409164572030208865429768237857155625447721967446539430209254438537200859359258164821236947828318320963877520932615943026573345162336913924436395993083326298556575480690128602849466373950375115049719716275590942926575038366658317860397980294415354782753673696615563230160745561136671629331140944061868442787441624612522802729893757283467";}i:3;a:2:{s:1:"p";s:1233:"624640865987867767216987778458789932847491075900224719877838311942749587191696555082537209810057247919185478634348223780741315957546909458090180531717911688191999329526846600555962065000508819021170102714756948429438721648737316448601804780420441612158994209226255131770594803399997288996003939416523946117016867530503628253748816823450873875385453973144581900301687739073722987515945552803443310402531595814541545187577977368505796408386197398340547063464250373460631392626155464052978092560822082540325765365576339965842818719306496724608929188363903261414902415556654006254232801406980895747585041808294354531554348429999919862150877020145670979592596848846447075213356249432578869930774335639823617193789610082309896552192367995866012240549883616345621459568480420037929052913195278081936958815044325239544082449262392188319862353535913518387672568198494110767287509097955588954933063386463158308071591805893477233574065816771174268570465832008357759812349254524175799285519545046477977667617505357579209790247796018912987245094247419473335965201710883238258536291075156906339370737434861404241686509780076365867254408634199338970593379961068090472072015144456114974956845793333134680626115671837639002307409714290088642141822749";s:1:"g";s:1232:"35191597041194826078562114780735309741604982985754459309396498875763019560692191173444976369639938166654451464209462496790872478339726389561848827197210702807234266970285528968148481205090704325620718921392127415038829344379920313399999013610665878283652899909643113809669797186334512616600176863374919988913482054118933708571797485328542935271364769590869366320928740568596567333625016938554865984246979429032911993244701343036076327077895570105943801518710651167585799950694909721052593057462356318582261615716693241644865070852894386957557579428336821004901863993150157499885441315836629140378243424067292782630058302855623369897584166680378736284119663412143881742140461361306675672118375561684500807533830524476726884266191054694962751113539655435727972521329610732240909280735708228480750930150226583351737696182711639764958097426099554995921762324764968387367006643004037013593837742552778489101189681998263134753899520604701313718970176018289465390649251732561908034755392979210100206706354006448135056428690542195439592042574114357901559386110762176368326458844181123228590640318361686697305408158142536747065528132296806468209807840457105675518612470245610776694393440418377981015311170038436924081564055374311557417607093";}i:4;a:2:{s:1:"p";s:1233:"779953292877005240445360456315811451093989451217452508030860903937948632517232564194001045906512442404742197613232702463671198472445385875490629026457545647187005442021788241311030738017425249356890025141343078528260496749924672452406075112878301736302556131136239278896535599312350677308329009917219230134305610628444344974394549039153542562509186659886824632357316157354854634051235545971442610744661953164839483107009009346767308487792275155082094139336899974160251049700780808146182664975496208843797554327815374841177775475470753571939373950219057601827618515306432330286536605787954416979600982555100385472096930721178791752512391165009133875211243325504566536842828926470993456873318478637441852889757460147342402972838846960221083308995652368217350359415335244963047436742701143102588024677465021067291625650479124825035107916165897366503641946561566575735977405500547013903880111234392336910724291341358824517576159101324393315463915516386113738376991694655518288249372828957784415843462949902880245560891397892739131312020213605637230016009180022550903701034602194339314782797872803409177330851533187493953193297474038559751525473131866371264573532977654516287334052810240609848244155997212833756639636272174820013396312043";s:1:"g";s:1233:"294584733932594868401273947792664024465639212321256126491249920101434779155955057195485698239924329017461116880418431580860690198256687586504932112771781527472902014259770658191419896802154650562294560755398906238871084453999743924751028154628422747846829629577342744556227521070771812923096114099805415935489724190764717281018532343462505964115811767991916636980116921636821712757318995497860585675395280337515465551865043288028388574578233488702804947437573881111837814063218842724966602537516781639806659721586014263202580079042963974436751247205517597185932576168824250675087889692132232635851385770662503832152064206896620142668420989011972190212487528435737892772025331837080715980029846159723498651207016895785824663915902233384231216633900413873894642363848877283294953641356035768665921262293701560382755702158565436541711046082853970334353019909184715426280874888137220636901674190665606039457943452297962490049336271214221544690306494924629862233459637759750174777290138782233739753168070900498570457956229850707058644987113995715716956163428588853996972713370837440713495127681927259759778516099666631791678009695621161317044066516618587362656131183202101424543589024791455207942352815475983543287919183904371032203398339";}i:5;a:2:{s:1:"p";s:1233:"873380532309522498799467076047576421250122925013979664660390100404370691501616536937612181194210215385094308810935516453355032436029463448084830096699391779359746245438975644149556989758362910981654674205999214419876320686094257700096069549948049688283122733439454755828610162659438827932114026255697266960943047298243914159409829140192254875858839248819066768167056622706529514987599954487323063574290224195367474347078198738515038011001166838478656586521264779718412671705536875203786037169126817703863736311251017581772657197321869901340255518927881204882068953687123405069334086588782698178808285142618320087139859152633355749618171526326904396259187880016434290866497808868783791697806208073482750736837746588717407322376245045837690624895530548374670357643053563615977343334778531626732690936180455182800428340931549713296236365125878591019218639946060377486219755483934599502713465029361440021225215190440316806913581079429713281130920337109109968340294505380581259509433693746584299063405276989634968695476794323908106754680577112440836162750947562118744950062391998865341718636027261902570877972713001428190326234549687999438140714044285074849887079302464721442624737482631924677458635638691593298803949298092379596527831341";s:1:"g";s:1233:"758266979649634750053202088910057283279263674287329988444340052724311389269193009783562375537401202888776496447338931775147711904920703696827537283963175676021760865387600870343858294395979209162411359873732107330784778462979646046298376965266583951503187441920319736964543046884576005781229328830643625640871783366283976625042564380610348916186645415586569404224977599824833363040472887288347263098569508253342424423209373267649416084905412233426458631222763815788848444066371125839088516151679822191407136660334337085286564713698597688507583147689563443525745241725604049001370465316856947442952510085242436423219864605864763869175481815324893258776941928679506214789932269935689301480992417308141107873076609787962472466286175746092824143957343107665553282526810645239903262112859746320942900955250909496627942784608117271955850658074366406923494387446533368326132090056539030150773913311392872050216434914799631303309024899984742422197090631532551201284028292062615924708408971882417466702084021943910519367667033612963460400727150084937048056426226974685862850060010300637268188682632116677120260511128669920683716643222316216784775954581071726728409507558648533136253212792396324990814732244668277612263108239074228022837043532";}i:6;a:2:{s:1:"p";s:1233:"820540721170757832244069162337471103623476021288701868127073481020518513764059295767556478640853661563409236622968593726091778348462161731928507571220398659730404245516726938439362479434547886117679293434155700084261057742021144960140652439772307624387556511736993557966682791065844618716738649097502276329615062219346852005641718697097097782883420200607919883986913139144488591155433090758531204379002847725666813781986224875075525417662853261153741581543945607777600697564688846706055314188654847180395320729670567990844583186709378281514284364374502984746208421004209976855078742522453310734735737052136742501777211668640816493194978901543793480749997538280229075960668940280718549909630114855675970884623264971311921109961141316437324535007215935055397677052785648645456667555930612714054437409386635240482069841343284036219292970440424707137408141216995364660839297129208485540357564963189115710411734704844257579489044129249646178130436474309823211871068594090095315504146217773952155598284329651162900872622016533557355773655411235665998996830829344059040931938851410102323668534202404592220853769884490376176406448321479680685841476647314282691628643791285643103333090834485277249291561189117394793678546127171798204363654999";s:1:"g";s:1233:"118438406554222995490123100896296072284476073031088381488498100505936955217546145811103101447658588862960079461001008094514531078825948036459975111330154054589791767944033714605441782562062020628113612970028611082098688775801631829875718508746607497972977201262883699047004148818835420663835134558082957066615924062809011642757377022828878035666649119894745815340510628666091903865601281505273374757023093390516848399591138012630325640069208002561071381333590271743989866484109505989403140432055596491271598758797334321842809180542487085303934698164071964097112522597852061996053697857136401134388466996155470013029782309435510931657620253973452521674683005646717477525282015675525891059896139716992911364488297600566543965925779727906128807922294910498484009364961002440413479277055779323055505652009751985075907895769541993201483122796667893573417690154430534732977024551262494631887093900032773648298216606625817339752505700287724821088277921064166742115930436091595435627279838726210384248484480417510561899496786492261565385112614452310735454140962760476036700738713148978258062283302094173393505567783695903421445729783145650782376241212257460283721766165927127583979756408547158718516467907168314631126296626106399012896760922";}i:7;a:2:{s:1:"p";s:1233:"548880106916124787718235316361844096017242216603144403144526114223097660636847718806216931324619711022631163106062959212363723195381526736692774612020061813829653306315587138945343717432435992013532097990394527621633009800856598983072366070314358447119040980012948724628709116117189707683723307181824637091772814755053282879511298615833481306573426566522411619387127602920750040423798107009014518741868275044792965816427462488022038905991612182102118898508410762260881010537117030246596093467647073714239550895596975301156766220816241309120866613668394836626003142720617951812627374838731012619830807432088483035236114552081985134001686616174564504848954594625921009676332389570256971117088453225374248443883042402429145636745540299177416612931459661220551034168122804916804973490302014018421895277362958656026655451235268564523782734034433508796366066821960530130189148245225555293455679309843404439477749993477957986644877057108538055208598606328427797655589145872355278700781305267826336108224166381248845658241915723389086597462010302103075341521420559474409270384789400219607597088319673340147157104022103303355849529821376234368920767987306905602181039769947710244590335945964599542795685010716255387218781537486891263221112927";s:1:"g";s:1232:"20223802225175087390897343320850575259412414582365900258163921641616379893820296366341965682900284907062971541417669673457029912905561753659662613613090408043698061279146209902763900423769234184733822405191473776496356217897290585702815784533532924728422271924212069389174850591443519005141285468141936966795748739746034248358086369040187336416304433089873610665670760525566546042619321022059403832424205289997775771777077392551377964858245304204808213786438590268481000586378941835211494995867689519660734121997341333890748026237318380388536238585862179559150130910003868306933185293566103091846923761609579853197184300628029650990023543293857997327465196890887099397843846926207481876351313608621717072924306713736639971952766086054530863325280899405617010066755700194504014455444107107295775375562685525186934121122525113890027141897356852125711989263516247264495095845712242968433910070550732088599140024829886653846928059492507359211886677228369134480549783244558011064095569606042620727213670092676737971036510295651529169480281747758154694909538028297129220048405979644814548919795425345058267606850114959452152274444230498221536709933406148397862354884914628348944049381266955798315160936114361289570654433854369533954705453";}i:8;a:2:{s:1:"p";s:1233:"859827209309634451406960567644664073608247843009655590438711626451994237792146991300287173183043087832637627357885878113425166419391451008964253017859106980949574755089062271358548272263403399922978216835737548298249861310607947556415556034302868558998860823948248446165422188547363376777494491479001516098330954311057697326851394720625724257100394328957986761641854606124802840570257773148816822354261738259531039998883429898993869241428003530214497814160450219313370173133235288963953099531623951947942169808487031628056100171564239864604031521909623635333747729708835356234693587117939763260100382872254128184803886900010111804500416269361475869077112596601699591963646940856023853064774037109855507020286576768786457719852203457601105292701917411355358360008180915826892620146216804079957668181231970467450738195144959372918201556192737905591268849748076849450465624438990383848388275522080203010234806683065220626452401491930502782559647732413722125655004274543457237315659249933066729897683797374439150414939169958117731633454400030620745723935086781132522371020701818644268478312923624781333343945370055592257510945893105577926435083566227773496745193530155189970622341845201168222461416348334380933548210599367604096086090031";s:1:"g";s:1233:"230387772378953200845430198621167578746427053857106869552960647982050572318224374962229729318382112349267315650146357511077064239693374841128343219797847769239939047378499174746908607350206935258194400647418437285235785666209175674200174882847856952420858925389347085326991590694347827200509909061693873973915463890445184012205857463974897571179795852429001622101699601936358287818840162748385632350581228272919083408646468775495034986097390583012810402185490450971630710284503910731398608923153350898329021751448849831559422869933412530221683796013852820003288717846727373190487598011276739172626606757714413110493418580840734528671851885868087367383538346546521370562466473234525297808335768819817289553483678988238007207218147310439910350927886998040664415744527590859368946235772414353195300301484941043822716434443980686904246525697288828638259424314558719281240513234226046446424926580782853900132686543224891646005449948001898781977906166963632765136243677729469730024277517040955568038819858727398039755661112182198876426968341181157078405926004559691091955506127027570276433391539963453802988248330864677240591327448955479631777762550975509046811958142442397739295068221957839946052657640258744394034254689987292652633118456";}i:9;a:2:{s:1:"p";s:1233:"888312033166526127955988426442422678810001433938919113768864201691207447938480718447651596351146287878452273934665645649043859986405865705632170182974121295125900973569951205769031511097530139546014516646694527186005154450959470448708609704385453144250688731002305363223573960088284188348397281059466430645442685657932089330915980881062245603052940096217287240951726953877714773688854411975063331656887351628173396825718989000406598772820517406925327492499704674327124273792263395692578753695346195761559571297125107450248914179643699672490810996603297769572128091365013688121379583975298121444209456702623405799745174906419004760101184026174045940728766575978641441869213635347993806018811545320063737880875998517629287431368427977011917627530837172234644438473851135151107087912257495260349195961101296828898638793317970645342060752102752379914647648982128417274843039283608661648219026592816346785321387167878817414981419419109227388794463755064739517746832189499096571596122425045771877069000145569547426530405158751547675856005170654409360257831905487455222746315928001559373872546190045505532925733851120210509137898153408570417636527268501290792622044295041907691504394440632534766052125617415332728563802110065175938856406169";s:1:"g";s:1233:"179940007155666987540991580117873048905237006140702783008925780163608019168731404115337759870972800567200300584668821703145485990166058723838370280255537348989331971098418891506333674538143418541493307265504601442115644860526047208656065911053559381591829532675505389980301754938963454618057645963093135745943859171388965425195072355354734862364577087825126597061480149259128737757766041549277714314756340773240381942891036795710496353770795880255238193193675461414418611062068106108271650728114837783741653035474438882611428736402606930331744059645109969995029237833676333163067205389180550109628679575668654874209389529098631801939745991166555358616979680709353058264948062368326747488955208117566150951474211785455860405703903272401304341357674522616532901106765444186621390538280943833741378449548964875421462545231416352716424331619372720208068714785982701636016598679429739914643836865937850288574299335867496560628657668315502567636043263564061553699381494881150855325182573643444832676577058036350069847284842579105276011204912451316096773591061234269638903316146162987031233087675096574076556129770577395455575930879255275337135879635066597533030050445119968176495966420634121515158768748603982389691514447198255614191166257";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/512.dhp b/Vendor/phpRPC/dhparams/512.dhp new file mode 100644 index 00000000..68bc1b3e --- /dev/null +++ b/Vendor/phpRPC/dhparams/512.dhp @@ -0,0 +1 @@ +a:100:{i:0;a:2:{s:1:"p";s:155:"12635450358293578591800910479487777169852570312773787057842183813945647605523761696818335430966522345697375443936716089896542284956173599541622185697564549";s:1:"g";s:154:"1090854334822591173512321403882655677941000410006358584565839627906165764285596682714148816933751400742491135486102083999660532436748158623509010992217103";}i:1;a:2:{s:1:"p";s:154:"8330760522092340606922532684920340313503428366729540863298817169536290179928809471721822951210171987458145792759861910013392392898179284657620886263899271";s:1:"g";s:154:"6322863474611806100787478309308593694232218046926780926157713238112945658789791537699650366897949272407498804399412240425281933264987477691262814155841388";}i:2;a:2:{s:1:"p";s:154:"8467874047342751270076186270294407678529363428805356804220110177077751064916093040050731559077353309166409798407787828591262171218833842208747332259453521";s:1:"g";s:154:"5298156252329153668622137014101607775181856989956252615676334754324796406326471396781499484185229408185326895046610970301850604221548807384662295609490180";}i:3;a:2:{s:1:"p";s:155:"10026784872744220323680724914118782861052640191389047036503601439573675679926077705354387433852018744814013072404781629568137348655795687816934596058584847";s:1:"g";s:152:"10063798484541132819515158210832792982361584205561672291343208772351650842776011486282636652726979910012481237423361696310602577790362811857800630406902";}i:4;a:2:{s:1:"p";s:154:"7500541218184559328485097477496345783681177646248979806799560614429932165977127468017169371472813198043940205643917781543605453184159881626674120202563821";s:1:"g";s:154:"1020503261486206285757006767534006757324059372861763647088747846559779377341132189129602840152879970678542409250058810084771680171886011520305323008135467";}i:5;a:2:{s:1:"p";s:154:"9421424414532091516477140058802411356679254508253599986943994499257134018040507972559527177142254594456040810388699415500836699209428775701629705371860561";s:1:"g";s:154:"6848477778913663314918103728441691200537498044773698707353425996552338816856928517120881637989820983228451343864443751233482918115252865173481588049824707";}i:6;a:2:{s:1:"p";s:155:"12625090184529797788931372343452146117342437828850959777918103886810506314889293815712889526766165497221632236033223851827026122988601152832751089193361883";s:1:"g";s:155:"10727140325921866071434631280644720707882009137514697813586556234846801257052393459470630845660422299001774260577487303758752061121714260768222777853141984";}i:7;a:2:{s:1:"p";s:155:"12898044345941449918247148733336961514367567256908845520876783894282207825874366689032248149016261412283181183189727919676912955124747513289770528539211973";s:1:"g";s:155:"10413358542022125014673481723329455076572467663802388402671853913744650796933624754409034882623123290639423561484943927800989572190732045719446742609758671";}i:8;a:2:{s:1:"p";s:154:"6777052041803887915352631631866770331853268073456153981835163788577587447533080824375565106867410180683860624984416024143310816156045498552624818782848227";s:1:"g";s:154:"4744373199110323775270810304030071313547127720868525858779013596635157802120581249858087010372177600991104126554407085337043555855358684723544564659511053";}i:9;a:2:{s:1:"p";s:154:"9769160763507178719431472328465896638866070854349262585438598729016988304121111106981091374450169009893186974644229636740814505506061744049970923730299363";s:1:"g";s:154:"5306950778367740573813655888374071857932353520721926940261594787573952929063307075086373819957150491162555430648336446419164220175136517200280804575851945";}i:10;a:2:{s:1:"p";s:154:"9423922356452712235926431203949703505484363837432274466344263270397520246404630427344391380890647616716224065056313395456217365823611766528652509334779731";s:1:"g";s:154:"7284089318298927178369679475673984622736731890983895175801568163798062623992936160960700756266264018534324483109833512513653743438058543564254601022875131";}i:11;a:2:{s:1:"p";s:155:"12158697138595912393903417958876572941964664917580175572374295322020219160425436741258520156480547924156012167437702643658539038327940197818126321370919717";s:1:"g";s:155:"10485764511219481318245074108282617920786103320852119973254883572198484400820180431398785006356928094262884549838937090554887145629516730528770021601199635";}i:12;a:2:{s:1:"p";s:155:"11288262951687963487272915907738107756098899363507394921290195349495485564247336439679451732281925028547373038129368449917374094191854311957106769832324739";s:1:"g";s:155:"10795654841855911955259186695756995006845641223782829032357886836809228255968988341551185869422037966120448459311717587218376381600148084639558977870096502";}i:13;a:2:{s:1:"p";s:154:"8258013926861608902693666790435473901190984397470193086801654424096172395830149441450824019934937921913900532126490754455661483636320695940894486309100319";s:1:"g";s:154:"3008616177637279133031542021757712428009438095597380460281736563913664528107115803598843251661751953577080050168764629090444516020745052468254714596181839";}i:14;a:2:{s:1:"p";s:155:"11160199081808027573810092136307692486080233663688728390187641807815696851217963593844145812064574876563510827726742554179620355048682142887956081871867257";s:1:"g";s:154:"1619837079954439123886151787080634070642968038154229204074646704930777938542872128065694227567105405734861674388284235427031786560892701529567221392315960";}i:15;a:2:{s:1:"p";s:155:"13374835067080888087044052135412597686006650587670271902738259960071812996976288241935082708129322038538611064744176497997876042066574823204776272831138301";s:1:"g";s:155:"13340606588501124076628104969616489544340701319544045041774387943804131532921423414596496104136847181815135596116949133855703919233075041766993096626479925";}i:16;a:2:{s:1:"p";s:155:"10259417180829818855720989528633519911845188087062317995276209738349065624107483004472651091961152483138484988620800791800438426039507470091955049905098653";s:1:"g";s:154:"1049652929312544377789554948223774743652295892011706941762476151999449680073160873173568005327063467021157128914200838440820265756300864573046947221185244";}i:17;a:2:{s:1:"p";s:155:"12197220246712313066260567471862904022363676477669859142286893009035744818051867274541212248368880572818329283821354454749617732729091957316225342433619041";s:1:"g";s:154:"9195882220497133783800026095688409134361538650124393293576388284972490669069409211646836028007865847926082128016363741865516430294771664900425136610454335";}i:18;a:2:{s:1:"p";s:154:"9407346240609426328525325968151151707707014342802748859768109084981503050961487104011635924975034655436053968429389536104159388654521942683831677615143401";s:1:"g";s:153:"269136289076872637342985277973758915672118214120214013887252427702020902794047992188076991724974378053740684811995916618340797583549069883395774393139072";}i:19;a:2:{s:1:"p";s:154:"7198840437082474958207241444655495440658341081388025505383172136119655067017904561231782672226505829024686555846885360605543609008217831214021594962047499";s:1:"g";s:154:"5788294064840240997000762465796620865513656066684696204990143434694734867188136493805370539272824995064240621448505859749288014816751791686163112546388721";}i:20;a:2:{s:1:"p";s:154:"6866194853453717341652339305994187321675925277246174296458603441198214649943543117403779339651067547283653344557161527531330217059862310916864636517316593";s:1:"g";s:154:"5759497540822961789157724255057129836025195265915136491003288014804506784127978064787500439359522257641902804614292542461889892712639086813735742843987220";}i:21;a:2:{s:1:"p";s:155:"13177952285079954289288219353117192697114703824741144116451428873571791737905505015012885197099252856045557518662942292101548687388076187108958765866077683";s:1:"g";s:154:"9673226746946894107616895821956872413994230660337172037720955022401762991975117923943964348541091994823989550807194860840353142963521466169754804620360804";}i:22;a:2:{s:1:"p";s:154:"9726690844491319103464486780397647954048751456431741632228743401184876861409583494228681662837684390382414485868883077196073018443343045173438676499145757";s:1:"g";s:154:"5966967110739915435125301545444105458697696178343475816618093998403883224416672950999788756580845547713539753295669176121976165846909930535567762639907762";}i:23;a:2:{s:1:"p";s:154:"7538490325284511136438120514170901332660801432732962496569525567553027443874560165216900989420584310969224440183000809313672232345892876810847904438727641";s:1:"g";s:154:"7398588641647314497767960339642029855458293475276281320039206004717386057103164853206187216154556795890067697653797260673588174257620930150234941115115435";}i:24;a:2:{s:1:"p";s:154:"8227511957622243129017210866215270808821806440628186306320707299109228484124050243443975192083115132467163269110566007486521957831863442617410859421555047";s:1:"g";s:154:"4645421224570784791175061679645751599175479926670667316335993032125249320593256905424556589769574858326427536748350447673974863425217426168147452888822540";}i:25;a:2:{s:1:"p";s:155:"12969731233552734399451955813691983006489496437250879046404503333930582291424470873903975608202652169345016278675568320752211824525170925811649178464352817";s:1:"g";s:153:"938872877916962648295701614574225970657013623191360283377917514779152480150022786122976960582953179872490158223294764793608858216085744934431578995451202";}i:26;a:2:{s:1:"p";s:154:"7065101156612109850175396041310880729801403367529402357084968849490927526243609086812440603700483174051775685576622326237843679578065068993344357800448217";s:1:"g";s:154:"4937530350574774053213016732051414773210465511366329302510484430930527647927154764700569414698805939709289334712316369800090809356945979615643622500590944";}i:27;a:2:{s:1:"p";s:154:"9253655433153614643720842168059271343705755485679437008857639916129766802372631673001875065759695231827514244486797815745404273060777672453756043236262029";s:1:"g";s:154:"1154118437300934998774227250622044065593929966410917431580654245142293172499153040764142683392788982103025598341743372297052182135492043939517398219789131";}i:28;a:2:{s:1:"p";s:155:"10848941227439606569547554892393736362241960615699022840700246817110328822098080048132085826242837084787893781138643085998469452494458843729328332326851689";s:1:"g";s:154:"6902859949879581005679923246898018564599068520211447542005819640293730028077262822771725498401630419852070831081835541856719611229878798733541142943533883";}i:29;a:2:{s:1:"p";s:154:"9200077333219147793521004610524679062674643522045639269053512698250176480683986701289170789423917221585133322649795623553739174854764029015889572200454847";s:1:"g";s:154:"8977651412120081362159327030461431226433763741949269801239273477011043868326857881822604759965174367075681004085055927709618738280729348684607803671789563";}i:30;a:2:{s:1:"p";s:154:"9845889841943809768314162240613991788670164846635075878467926914087289824203165472268700243871440856079801440647968535378326278137434266496758552114149441";s:1:"g";s:153:"768380127191918588451951538282124996101009829676972691355190870417233807246391392262749483247926691107794065287711515912136355133371195330982913655254406";}i:31;a:2:{s:1:"p";s:155:"10851556038116464699070134743443581537292976439813478958179597826025549256396071124532860998691993456204739775754896353442062816032468483695456073098224443";s:1:"g";s:154:"7154655821774317099112947480129446469943441624481944724248657240117509097398430349434092257615286785331672319149988169019804485357174356309508341925581460";}i:32;a:2:{s:1:"p";s:155:"10869657909548234771846150650291496878012840512716551698067888848900961777039246759408527968486607410691927237604274521227153796970138251173504729332398789";s:1:"g";s:155:"10291105559439086106068351955856024921898095091811071928018974509667715608106121602415100275088724582034560187196479349479678559477870893719603456159195978";}i:33;a:2:{s:1:"p";s:155:"10573437696614927150153411773598147086432503243232815275356047074061503243825728675078417236624432478965385334323514782803366272650302790803029448946823233";s:1:"g";s:154:"7936375668886672118414744836005695357413671975252348835029285378278952434975164206158622984806431933596144888246146817078922796519730755404856725404012843";}i:34;a:2:{s:1:"p";s:155:"13143171580350380026719039436106973235892599539038891512396032568425711518490270801218225503291537102818964594215730219661054646928963320816487254976744691";s:1:"g";s:154:"1836103769949406432524468270712251041529485560856485759774657103122616493367981405292392684433227262493977758149124464359857054953465532851417935109678443";}i:35;a:2:{s:1:"p";s:154:"7817302659432711774678271020951750661333508545555444370199324820069061693710307039108112542055446182951630431053517684537459614899603725855479805738841609";s:1:"g";s:154:"7757617168595337488906483183749388091400069439975888530757208331533789508118297894470372310437202386279701677376282517267115753765256668381319564910810130";}i:36;a:2:{s:1:"p";s:155:"10267638897003329507809180547127091069117459439131395063369822073974994025258244541686493148512939652836981483431348406971826886416596041868882198252892619";s:1:"g";s:154:"6318982256606638444633601562064159489075575174603097104256876934574261058223900542813762735674188095550436482427083800544277529320265932517969479395835823";}i:37;a:2:{s:1:"p";s:155:"12782270167325061135937860317489559265180586717318292561188420849531526268171146656351667953024693325314361045908253754108944361348578267392530709664122899";s:1:"g";s:154:"6991882797209611054389481268465012367881121070327860241481617497353801116278255059623760999675401035064358235967669879053837015278936160705861718207391121";}i:38;a:2:{s:1:"p";s:154:"6731746378775926601744707878575045310304903984312892750608776725022937461467670920174839890356560754884661025202766992467602158995844691889008414344224541";s:1:"g";s:154:"3107823960825199229883719178521718215890020223638296208432989834142924789012938848961473436854962539008488662480251097171768707780434454808586850672001591";}i:39;a:2:{s:1:"p";s:155:"12936328803238672147187839312904518164662082232222521593614447250268808716877423911517851087146464538417134244477088458475508392413636215020245161324258907";s:1:"g";s:154:"7447543722174178404892869118079799709872555147821056050425166323624947980165009189566361641678758361204234599663455436346048698885722709733355889383997433";}i:40;a:2:{s:1:"p";s:154:"6805235710264138935232477664965736357729175546690091123374832408969916363561953404703570650183363313073842129895601843542765271167068143846210532109518801";s:1:"g";s:153:"241967790688726611630572098692470914343503786718983020603841862948415175119950819174453647688760067799745498226298934246248652993245529368369008676676018";}i:41;a:2:{s:1:"p";s:155:"11925844197021754713938625724053020079683404084430371438453593710522808327354502713382757227379820472738869202369687644194388842222036179834354431378938783";s:1:"g";s:154:"7528176863391682294380713557224125923359959500435147592233747105062733195022505163011428173748825139929898679320548103280305894663549403454721549617429358";}i:42;a:2:{s:1:"p";s:154:"9382690276990287517827126224244262351114680532057242635224428485844700880422684769081831064853813380043190717893849784787292907965292841355010043199008079";s:1:"g";s:154:"4417964586244527620278956236372028881588988136518683014571128129892304376472643463030713416286758895907125650825241924308538473496809076762137861615651529";}i:43;a:2:{s:1:"p";s:154:"9471154462532162517766328483693871604313875211507659394402991024218819931898363174393334319225827831532975054544822369032247496657955428463380077541101259";s:1:"g";s:154:"5965538882821744183392517506266542138569200983176623099845801353014368375173891122156750085268413198483559096542177405738857144779702351290712050408559721";}i:44;a:2:{s:1:"p";s:155:"13072215397944695079140981714451652254088635540701039783436079695923305049093068379991778701466866177972543194919692105571905528567819232740033043049638673";s:1:"g";s:155:"10905047221675573837388440719936929080266693676579154214910634308080954138288436777167832801892265852331340567765314113894641600068009717791667699348623183";}i:45;a:2:{s:1:"p";s:154:"7480285736902516363853550609483667417682147640058517333104942696093838232353278893275640726749652243578126305790444323950427003985719449351376634278699607";s:1:"g";s:154:"5759202574113108282378074864789677515288689767373583038782636582841406886112443573385070089778091622751224484977426735366091834116401247133594381805961184";}i:46;a:2:{s:1:"p";s:155:"11210622732047339404024840714095057225603221198681717167542047064110330442742534046349520884675080911296315861922768327935094937187075265506822940835040491";s:1:"g";s:154:"9937445355915956411250765024373279892128473056016564280984522288370978119816479851683244809355434342145980557652327529849111557653417852722522293792146120";}i:47;a:2:{s:1:"p";s:155:"11801310588884178766890310177272733983571198144791811277406602857753312000312219119681403573834767631910269527394416551781151894475252738903890058726926057";s:1:"g";s:153:"115233390078503737760155084175025767812358241323488230712385298533454103554091397194104748384437484257038379362772264874126271752877697308310940114682694";}i:48;a:2:{s:1:"p";s:155:"11529048347164441615241543804181726496687154791825255459491001491738712611956789755646436546778690115202840049658389496893606046846968559040105761862357833";s:1:"g";s:154:"8676718751750512425139622349225124856609904480931707180008538338879230401203724388724735695303409750333477100875898619258877552431088298574108470256276651";}i:49;a:2:{s:1:"p";s:154:"8827072361630078640503677481298714879520924565274494318798943013516047380949992422868188730738867101711789222674209108748980222387508987065854715881696721";s:1:"g";s:153:"710141650554525884265578176992152766513903299812535725888133858445135487452789266334613419128201502959244491496639163675200761790924208942231383545162770";}i:50;a:2:{s:1:"p";s:154:"8630916941594181725869358635738342312528620650119957199177838952748463935323817770626013179178189281017124138873993517599531749107153800962022777179165821";s:1:"g";s:154:"1986336010793498690402481692272896313437282310385967728046494523738961523190690879475912743848248541173027205997086416780584203636037838333529483182130644";}i:51;a:2:{s:1:"p";s:155:"11212951383442456895282126037644720256410394797566689500132827435994463195592391547284657499757312898540967392508953032317946768141214910975547388177983241";s:1:"g";s:154:"9102763753785975341238925269544891354476061894654740774463306793322852969775784700232809270884694129158803996346082108913891287705031439828185656228063664";}i:52;a:2:{s:1:"p";s:155:"12767327655173767525498878790016442622970607684484683803036559177746978436941358536992037285959314311977766975796863190178719754731248258583037178093445689";s:1:"g";s:154:"2321508310733831420610044896604432882237136641393324233389255445534691813740197943289557007047153528108310525898070249540038163869248765133282278627312806";}i:53;a:2:{s:1:"p";s:154:"9392193574475555116112128582962411207901765366075980992046837483678270815467145329834399000077307436597284520617068141836081640163188636250835029441308703";s:1:"g";s:154:"2053414734576510953913507168402536572703774315964363121175715888088663285442201329865875872679876866070636146795229156844380127153406257025394411611466483";}i:54;a:2:{s:1:"p";s:155:"10376053565026787172160955177540422890317275023121997466989774697279488503166878624289513515797363103732517258578762034755462542106414254692746603234671043";s:1:"g";s:154:"3091638708604907776624878044604867414422955026474038166435429554732769040827969143023705222880907519792943547859810547871406751310288694469049761930481334";}i:55;a:2:{s:1:"p";s:155:"12127207345651068820086441964683009352696585515224185465037336419371181638231683584846771580814035091125796069601976365004662474480234541458668882739890721";s:1:"g";s:154:"4438836866160593665451702269753991637431308452920369244447683669705293185053449743730564137227007292403789550790345961175603642284391097450268685443319770";}i:56;a:2:{s:1:"p";s:154:"7611469932440564952211781130439214876690796015869296504681999249251840940704296297777681008004821652510091526923191561988463222032574639564147602004747471";s:1:"g";s:154:"2159962031347381166014669527596408113229438638278373884502632954091486600988300593639831501800781269214755396360742040873940950396505283507866134558622775";}i:57;a:2:{s:1:"p";s:155:"10333552284492177347867767760312106573829849938537225897708798295607254551687795282788443586091756110932272161971955610887088234617195976811351238892296089";s:1:"g";s:154:"9432120129743475799160225256016334679238139039814424474076543995916056734666699428293793667992690869643795593704757276260398200754011455643399669925569067";}i:58;a:2:{s:1:"p";s:154:"9186129481949759777879325927009938672103591565760527415665011657111222110694633491007638694742477745970521733215626485356625921552251305212419767357335373";s:1:"g";s:154:"2964982199072437563747659648788199572625987178442645806407700614788045759520791282226234744641146133332755273683835703308793243169629688414830111305979008";}i:59;a:2:{s:1:"p";s:155:"10797613104193760920872576604739145039329493525174523870041853152276384156721978899427111721321741929488686066256034450841507862907390410840826008764757899";s:1:"g";s:154:"6035241474954122155355449752310815638886484205153452965392586944818152870488968107547112916728102929919731151220028636538954686722015297434712965657407685";}i:60;a:2:{s:1:"p";s:155:"10869947620920150461498689213804104931914857611354385578667238439616260825731378948972250757311923193938060849629181090857995395344904289508598143935730533";s:1:"g";s:153:"481312849012587203492378145862322149972797039844724273303827814567785210878799018651223527634096916030584780553484801818224446855755022386359742338412793";}i:61;a:2:{s:1:"p";s:154:"9231592881895960498562751568063478751369509815551906815114331855768090862166893258661806160199329317482836122183454449679798480059718481696000432015512777";s:1:"g";s:154:"2829892719013480169078067114400764737378051603195046862786323332593085589593735084661704693548639293287833918450999392896600385474647941243068301494417304";}i:62;a:2:{s:1:"p";s:155:"11535970726511268187759588980352242649579274403126372273895202586422537522913796551110927374939006827092569052666629425089018374179426876981117710901583973";s:1:"g";s:153:"720418139015023065849163498841056558473934556153974761688050291079916546264726704214062787471591074325994224916038425383512487158259629457204721553853210";}i:63;a:2:{s:1:"p";s:154:"9861250489623369880082921468628592177502408573205130594265711247497202978021917937037715397969536963237006852718089567889086256038105803931322547406120933";s:1:"g";s:154:"7928607398515301999160672014700122456116839205946040598055281578888827533359690175257847840316486463480345797985196608946959190295352354947490060567259474";}i:64;a:2:{s:1:"p";s:154:"7037162688438216114665334358856972752028696375118432431917708234857066416666136221875422755517254911565532179808653486394916493658234167039740176267876757";s:1:"g";s:154:"2561520364124680347691025622126585934254249847396300180215790279361782291723253986299677678320409185303548420368698893869095720049051592101538317786377366";}i:65;a:2:{s:1:"p";s:154:"7839643405862034358064924109902483930026968378388305680529567643551318111486398801706102322537326685360160402095895265466777644277194315986891593712906963";s:1:"g";s:154:"1754075447965545218123602315590932259411312929973677438266981091131327486934951256423337377824430217299559456308536359696603306575468489620694606039087055";}i:66;a:2:{s:1:"p";s:155:"12276557742146258743545700501290339960587405224847731100110687472244791172620101100818159279506090655569815738514019088680091703230258555911540799511122167";s:1:"g";s:154:"9763861375914985702545750159977496193065161335864817824882497327027580874802416052039447133239579968682408646209369969884977946436819534940176606699371008";}i:67;a:2:{s:1:"p";s:155:"12230683487619319961944453143151691985882065041735379665065641906865391780863710859120672643315553046872854392378120553560533025057025603898136116862293441";s:1:"g";s:154:"6820995666984101001799315333640660517853397812362325663701783101362074754987943224840937197351438492534345149997665796889093780332154865629423497020827741";}i:68;a:2:{s:1:"p";s:155:"11000033292226348930593094035262737806366027110884679994121757708192645734655143882773568769558594544920179117149359550596513178815154309868775410035186063";s:1:"g";s:154:"4136862529753947481457983021388601715848766598496715256706293038171121046049608132082841396600193873750375804495745944144901236241777071843379368664154275";}i:69;a:2:{s:1:"p";s:154:"7932184591100186238463385027146880324850417985223577208693360112110160571988870890366119973622332640258222800907861231078259268751127722069064114137860677";s:1:"g";s:154:"1554704138876266517226317671429037357546114985405447916960643643463787594693776634564098027315293480200461149296363025299708818954818475510231838798211630";}i:70;a:2:{s:1:"p";s:154:"7247101322282048034402027899872237624187875581686127113817087170324333761059623129858201374439632028757144826193998183802269340811926184660871601027538329";s:1:"g";s:153:"419876311823553421268573169216133898499120781788412225525682613256066295537141806360606590621846965864647042488385611805166485002563960603496293345101151";}i:71;a:2:{s:1:"p";s:155:"11142911398132179783773554123504917208536218755896547125640354767247161949984883149299386304638615888680135284173520903886505390416092111250431821534935139";s:1:"g";s:154:"9421238208594055151718951084399404180843115860565558346086952546158235884494503159881996700939897153949279617132763495108273288888130277440160448079145244";}i:72;a:2:{s:1:"p";s:154:"8422680718159927137259727024146506754367065291787361031410637379107607885590191645491292131243858308336644590049873216313480699042782181741026895310726173";s:1:"g";s:154:"3037225857906067024969405118120869481652099716781816854621639587769381797676248760487654420923330399046475888790029324331786276809507475888474809786093936";}i:73;a:2:{s:1:"p";s:154:"7528768306671922054208185893735786263892447977854351454834071543608211520188226424532595091748227597163991455896141393802353880913727252686305028424161729";s:1:"g";s:154:"3931350151921122314780347621781962310133031238916497178404726881167123558977180174914812344106371470279071072405540448395936097566056878790069126677394020";}i:74;a:2:{s:1:"p";s:155:"12030526433315035140469306931173541509436590353351614316003049833737604937265864191109079597264155746863781242435386938773196553243129970574108647558122719";s:1:"g";s:154:"5262551105713048931818840437133090849709297129874432211503996380201846241562025926981819972075908236266338069212044270892600622047959414321970797115421273";}i:75;a:2:{s:1:"p";s:154:"9080171192643214261502891314642398886325946367848695539813162167683393701564678191652727167179846621803625336395576968061663125749886477301402476057199011";s:1:"g";s:153:"709789037747438551471403268717923397174465497703413510328687265086023430744334341908605956975980410030779626052223052305886135189506754645049360807055388";}i:76;a:2:{s:1:"p";s:155:"13357314213295536619231005838964463646886546298482519410136443596212432187577086765634310652333808405384086750529280259788935338817609169763288472875576053";s:1:"g";s:154:"3008308424927763972465840465972683289043134099712501524187518687952997991630181328065646578654263728776643235789250693981259674530838112112997801930783959";}i:77;a:2:{s:1:"p";s:155:"13306050297284487023040709070162991797222204615032140186218147999553682592488789343049675744599654166735159045082795547527989076358395782301307563843028977";s:1:"g";s:155:"10586434249601338827897130612953689058628048902344954419096716484144284946171236587914481571624702816408228904538974499497771977827631330618983799976606289";}i:78;a:2:{s:1:"p";s:154:"9366504107760787554107889797349668086646215031128274756817605248155100041596743704559665807463008332333531511834473256899818275789020152578564909838966939";s:1:"g";s:154:"1296890521931304524803874647584175069243347320269646405477433715522011568052186590990840829333541256081030481999426230636941661307954606245382960948452042";}i:79;a:2:{s:1:"p";s:155:"12370801442581130353098080816654066418563119020397739942200418473089819692358661047391874663049174382551577117787540448439844491154738143099045780558055617";s:1:"g";s:154:"6842040296510517190110590627840671391670907107513510853159788693248967480920130462096308897538750871495832060995658519648610074675887202669120166694080542";}i:80;a:2:{s:1:"p";s:155:"11077894732742539228461178737611889036810177914415299462002747018598080996762211677501351595137719755735664120371063604922683564552553799605879666676828107";s:1:"g";s:154:"6225665728035878018071502041848578377966752563525174352306433083719321102952407547688689903755913174694857601501432370542759467220859644790183397797684019";}i:81;a:2:{s:1:"p";s:155:"13145416241730004319539031165266146823267243986800900249243141299249692643707823654148739035496268454712317187086057636031267290835062035878246528419253971";s:1:"g";s:155:"11050160386771600486586208130647596663138967212707349660963449143590468628618046744668548025343868972693894338641508038837575295198723184300502415519901282";}i:82;a:2:{s:1:"p";s:155:"11611568192755848405358023732007679695516806149908855592995993275357312141733012806119815203057519665797881047495560403615048245840900249485135048857817973";s:1:"g";s:154:"2172894898451447223505998543289583996691401210736051190210176057916495037526136335918007793521262073068109566941968675779870206983436603928903594965384965";}i:83;a:2:{s:1:"p";s:155:"11081251290209313486762589003942067507294386109493000614708203861884888898398271826165859824008399524198445364973890440885137811409580589713737316428932921";s:1:"g";s:154:"2341203960244595837213070499094603366869960798002532578372599738831741047504816215572635049607899579047269831194426528602744165709752396574329560197504887";}i:84;a:2:{s:1:"p";s:154:"9794529356504350260404907807235199976002130997823212274470101635208030092724642485892237240499775678153498741626506100441198709272408997435145522469814611";s:1:"g";s:154:"4344904416955182816773869473067344211044878507239085540617345084857514867492182044106545330382179727507839983152349813760661281772974710240204268429761579";}i:85;a:2:{s:1:"p";s:154:"8179725484707820411949587770938632194412056798385983337040993681088549942564780789402826043416929282601970567097871918694564510170940044087117293841610513";s:1:"g";s:154:"1968397542995586956640270479775802044571639049081148217555793019585806722702582989925336399488001038506518632099733588396335941761339893103671679996093428";}i:86;a:2:{s:1:"p";s:155:"12087064726834740661902750716902641652260658517688573518871909700616089898549798686986902911827362620660139382723084805850119084200144363662168266918678043";s:1:"g";s:155:"10143128949548754892164655340639862222487020558978119369114321136539759978238238549616976854216342914704256587847974237107728402138497359582900931753150340";}i:87;a:2:{s:1:"p";s:154:"7029682085043851174454067777276288756188737504360927396230568096724183584772341319344047251994723113430875282707294543179001234168984646917770014120959747";s:1:"g";s:154:"4793425727317897442176619553703271341958074640466020143773480645279277087286489116954664501609095871678716832290085599924471974813175615478171487329912038";}i:88;a:2:{s:1:"p";s:155:"11751944887853172690320837788719217620434712863775635748903292970090933885012275919749911820430855929141981640859493347105230323356063850671233945242412501";s:1:"g";s:154:"9582409285060411792170252952646051889530300334780762047880884513762363910409695547459901317732986407473204516314483633161449064045710936889521255288095464";}i:89;a:2:{s:1:"p";s:154:"6857242503272628812624198660871703450024969140119354771706428426493307506557602183087871260836964690607891275115676620226659587257083437212153260711770279";s:1:"g";s:154:"4154176614636529038047455462840427597900131364691514918565903217730506684392008642129862713125121528379202819818759480813600225543386651723083282463528910";}i:90;a:2:{s:1:"p";s:155:"13115086998220969838551534574336259426013013813655672434628036372288827799419576677363079570500421375377429272681906309654330290360291887877051639171311351";s:1:"g";s:154:"6891448071394823240466483662164181607435055970033730150995462293778784684581116262176470853429712481202017088873582225144821918813814521448443862620219142";}i:91;a:2:{s:1:"p";s:154:"8510893906328846244399198669826810612145463386143494241344898024159008867802113613038506831355149788338718550470445775096341446065194196232469619078573713";s:1:"g";s:154:"4719394317458501452628803829232227857042955736811107024588547171771101148737656411606180861478202429084115956817397010715814289972388887344042708309814233";}i:92;a:2:{s:1:"p";s:154:"8196571472465634150710357092777366857982237408029060560236952461265863131959217332523315458373970512148516043820292260787541295332849890579530595347949703";s:1:"g";s:154:"3437715159187221214391366230360038167885711577338021347106416964488193295288404157463558405404279208235567951416122490240147818951965891782937248453137469";}i:93;a:2:{s:1:"p";s:154:"8450294490269241183361812103611893228339652390157337597894872109035465793517753716542229018535050043417505545852639183614639954904116126769099901623714911";s:1:"g";s:154:"2888014306503502758072496640166596674896406120299827826475830676072466087934865509880125697107944254828014207864859572201140883165205473601065103936013655";}i:94;a:2:{s:1:"p";s:155:"11703024906185298810265683615912076101571205851245019004095853861674944958540779094519988491697428205927709507267814990927761125062629298343090366806859713";s:1:"g";s:155:"11125881782324660340685567056782318502630553007218646702194031293015361721973968471899663504370476122752833733771740023378392848654883871239424202536963707";}i:95;a:2:{s:1:"p";s:155:"11633995063491596974992159233441627337491540537056061974579863559637399000043290646127303473958433521042069509695166002929024179229815912787160500228543933";s:1:"g";s:154:"5779716859933543679336004575891528709661168013484215512953570366477029110037380705269852102039382480691593905861950267640597260471662190053628708944293792";}i:96;a:2:{s:1:"p";s:155:"10667411102370081426209854218278625522500220146272991772930143668007669641923818842838987021376423579429682884160787015271663155792992067237050696610802803";s:1:"g";s:154:"3279140280644715139321247161992749403889139000835115394739495331799618231418338265792754929717649735647981445732899278350937379309464302481950856909469903";}i:97;a:2:{s:1:"p";s:155:"12262245462256089092233173409023375655175021466746738975484018042510893911713337463824358605982014894541303198417182824980800641603290435497640012365351457";s:1:"g";s:154:"6330963621362363210369473585040347344278962099805211292047845261983817579073921701279060419242132775223605691558296991488834271200429761204699646704066949";}i:98;a:2:{s:1:"p";s:154:"8411654103823275724025827646019581791360301812783543923051336819177700468260635956242747720616517561011101815431131324637960310731981069286216133688130173";s:1:"g";s:154:"1684947649509417239135260806264943252268526876769637194735757909661839491299132255354516845127033345104113796896495486662449701718944268945929267825040670";}i:99;a:2:{s:1:"p";s:154:"7994373833628150530849560920652401745121012535777349068601400269551607703280823889354692441372173043657158510740536487181611790985457287325461732674487519";s:1:"g";s:154:"2448220787443437832886976788088760055780466231459849980968718478131876017940927162384725064179838850731540842678866145729291113545181168269781059181980456";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/768.dhp b/Vendor/phpRPC/dhparams/768.dhp new file mode 100644 index 00000000..9ecaa89f --- /dev/null +++ b/Vendor/phpRPC/dhparams/768.dhp @@ -0,0 +1 @@ +a:80:{i:0;a:2:{s:1:"p";s:232:"1175701041445302708884945410438770138623067783317783382134975004979727959704321238474087887774649148807392806869952586373772996619822483837057669783131284061360637806319674004728682099113918536008368232973412864321898274530817968189";s:1:"g";s:231:"241059629172068314126293770290309301680725940677268507448005614612902261835370942874314458647451521037890594260859348356283043421942966080214069747884768462092667557211293978755476816099194220284716669499047268771469853565628917328";}i:1;a:2:{s:1:"p";s:232:"1160463397158849527701815009148900197203162958966145645294147435088801477477484675803756332910607813978135261745343212153393703549631957403377304943392443243634274835161523289211102958000522891895552407402369897099778261147415171269";s:1:"g";s:231:"980156576150670554745272209446093662673949888301777582456786615364967955309470589404357349856716186753632817170498703268152900072938066234439475476067541450491769594850768658457448054108176835484453712576430139797796209265772663336";}i:2;a:2:{s:1:"p";s:231:"869999655052790320182350879045566736728057927646570055315646015266889408464221761823392111747178285002452996028958821825296263253477667770414607110824676682799212933666255993136017460383512392289933438630148121391233061157366871701";s:1:"g";s:231:"531763689104538271465553319393201608727104812448097152771133836552981504434572817723821778434687427886222311184464695443966276476945314413633593925811893001531543956477544738605170657319973614928713461347939896531084690457109650538";}i:3;a:2:{s:1:"p";s:232:"1104471889917750884804303993065688883460119170192152304973430999181490471008618869217014529124101277320656445061298881090946549506374431201142490220604127775680178415983020357612677183004453511304179415112545948191905746719765023971";s:1:"g";s:231:"719561347460516300588925619954785617290282281788521291729567441358628645361645381334837281113198173842448560915544949877434810676286698239725433272740122624262661895167489136995799620964581060100972409665350810198636958786254747490";}i:4;a:2:{s:1:"p";s:232:"1349145662078107774697800025503472204512905629848848700956023551865702249533990270152932113986569777681227891868121513976119300639330914333691142005444358532420890176900408029727790838187380605103464551821327354724729985768270850191";s:1:"g";s:231:"817085937396555832326475670220555563843648577688094711201174384260146179381647529871294528787843636664507424097114669660596077372446980941338825278574512780193224362876869434622142663392849627956987124787736307353546621253742287509";}i:5;a:2:{s:1:"p";s:232:"1170084364716675098903795547318887975237486234252129979677466784031218735736488597399497927160715706835015347990348654937293942669164759764598645992563931384215893539087431665099853189753569853096609453066475645389548368518437588197";s:1:"g";s:231:"498080361880592469439063638713191901297721661284941285022996514959223564776280647472546017014715813809968461324738999250055959772268068142135772249196678702445566155036883056146139967731957697436506541599654345718063563028972250369";}i:6;a:2:{s:1:"p";s:232:"1147544738129335691604098236730065784788828984596526639862250998945585078140238290443084080683130116915329899951133515821647678968164144342335104557165878713295306253892140879535183775025459645089161687541667257366152969117453678941";s:1:"g";s:231:"412298807319586531927775096039364269362622496539129056371296014789130977236073468174577767813493223094260356964839594735360408897706250447147501482137328257143660304924424450171953125212533826943218368301407163603147920282182596717";}i:7;a:2:{s:1:"p";s:232:"1251459840625677580659022626732309463308468834562009677880364632310999147527635865483353995214612742318909034188785280532570232794971791642859147218442516084809570095064546523413155269683156065581632009652278258806379535582737762439";s:1:"g";s:231:"369275760058498636550821251653721941442653004141698753680557607690072573886381652126744134536579494435975916488308172082808894369383211230497977817487039647983869030944776494172985030680988398447132958596730936802066575679222110687";}i:8;a:2:{s:1:"p";s:232:"1535344116805682251385675308663093365934297896066448534028022589326515570217831815544787810722606137484824036899107844848252172542880816122541957184557662658297375641247937132253125479510107374276342886367827644575164585705594531127";s:1:"g";s:231:"202836557466759687825659737460642134720697159050648974083932411076616195737116617071191469532222258845229927616307896158504996120614481673047823109046745202089921378952041816061571352779203853628752794105619209196352667523917697914";}i:9;a:2:{s:1:"p";s:231:"801113943908138806999867337723460760488142199250918895058021150316660815957495356670553887727269523631199056949598706103957872673978280763594133212715877891856789747790840641401586443741231064114368395492185857995949962876303129819";s:1:"g";s:231:"694309839379795774267237792764059999533089749547084673316777130906803928668917048001170478345436377296099759955259854815454970932669888732648849422308339634969926182612207089556708827147823506521805267697148146750261179747100470567";}i:10;a:2:{s:1:"p";s:232:"1436624515829922564180170325068347664639760966514249926047688645549597081524232509986327946145949801557430435901646275377697865257323915842905395151585185690389154314744548082422917984187888469919698940546837871940455457802508004277";s:1:"g";s:231:"205325877335834092709861971701407633902492068979291865149734239121982052938975442395908996863058497445726401815399250375047854878980218929298866937343194631341284412844415869883011288058945445382098951175546809496258592828861049123";}i:11;a:2:{s:1:"p";s:231:"799258661369648923916854481905584467963020662311600047520263122726594370519134294878197242897014434488291639184983931668610540662986407313612714348657216832542836246974474679372913895615147392935709768202139559220362017676087042633";s:1:"g";s:231:"357496241504622526695256924227070348312584166065591818310495130471771371727676319252239046969554923144431824429107063633022798934376238009863920419615976338892569518919491671554567567595071601125434766044367945437812431577687923968";}i:12;a:2:{s:1:"p";s:232:"1051408107621350416126926966389976088507487923772801072190786195092112727024301845321543595601559395183495596751958829496260061355920165832559530362684335151735209162390479085930229489502392686579399803214956499703143786196204087613";s:1:"g";s:231:"403603290181277813589663904398385576089358601023743478467711998534924767309275480053287177322410214951726276870415986964145557802768512709681770978620460340923362599910613902980015730554712218603641991712678463309015038515702944505";}i:13;a:2:{s:1:"p";s:232:"1383051313976534974297187974892829648111401197280398169875907668864794188173011090159574779998626193323101562395390896954895253755334899465699105444492348571629049556431145697351760735250630906738856446907072009269784313512185855579";s:1:"g";s:232:"1199735749926534010840481862177421035685177726400143336339476245380207334625197545055011590389537565182644918991313407815516855958991889145001076248919695783887819360092481535762046310624503499974634928082949333536057916703190347670";}i:14;a:2:{s:1:"p";s:231:"910410410031466046008336894253730842559542140395295979211229205768982423176207332543996039251025283987942650159091803684000366302121506053327876979040128253072248521267759503496367422588289312994916213434282179649133744633212663987";s:1:"g";s:231:"395333968233767507918263855813385365725937802861175996425345239417614560831767568032540531242363110450207527777984721790110784642570120251382701537646699019465645659295689919040974065325120806449585538344380252947524183463505710118";}i:15;a:2:{s:1:"p";s:232:"1529776512580798243176095530405074419290713556314880892947927990554803460910611713935840752123509682810306593293156433397002521425768945733982728045250387111578481164344007611587021198066250169964931138878655459215861198402408752241";s:1:"g";s:232:"1519445383034831931517483004442912436628806433888857538825450472920479943253898537957628551027851368648480607418026659708334282843471559480798797256421924871804179230900235354724271167196448484462496628734555064125761767269533924788";}i:16;a:2:{s:1:"p";s:232:"1055268106948316845820037199650696972262803907698438854383595488438595533496939565236257936526517867592674209529034768116657200825044331454286057391906528610312326048723296678566840409480856556538022261783249175274722313496460997393";s:1:"g";s:231:"206199432446954854501155354593104258705023646498347422866452068277855761599832823029544119042795306106607255641870488124946938722987479414009442558427811133307239255777567609322375398053036527630800505594868640804750267329497212019";}i:17;a:2:{s:1:"p";s:231:"927107232904572327802253196907414522890401198741432957033542471901660060735503741345053740426201523001385615965320925417307275335888742645568035113779553434911899954660857153019756367569217075991771367419354564510954569387686781801";s:1:"g";s:231:"151190234644925654338468905080174282428312425171620491840896135001550552505285467270405831837663599636842153464661142497087602166399039180218595856073426378582252819789107700342324125115418517879031733765651876530588736801131823295";}i:18;a:2:{s:1:"p";s:232:"1230406903627596355429630307357961966927902661330733966048912828726210489203733166524900751937788479926740629911174130814981095818248169716756507268089985544967870065234054865704635592765032821889963045586853603924313034646459830073";s:1:"g";s:231:"668999769164149606396391905469702907438198195801890018257916180836998246805109153504822600959837956452433436824239329746422896185329845719328738674560224401963220334020504352748647213145516787548177208958659785899244375716592236867";}i:19;a:2:{s:1:"p";s:232:"1343141590028980421073350570601903280290621008374784318649055603896772206627855071664874368580315902485143692539969771358809943653645023853698628652795134155359182055321034854859987485434971478105676770508757702487134643905697728033";s:1:"g";s:232:"1062492326293435934559743139342998676882453034582556699457385659062085223848520214771625029649875938957628105282196786328457477581581392517919765722570685022794786407108203606530037801222131349049104920985866100522223483258865794132";}i:20;a:2:{s:1:"p";s:232:"1098403501638594864875213493901656255041240203343882113522482831939345936346184333653406769548850735726528069984539165555039980566126422074768571246067148292089464329701721589403155070691338254029973734622567828509785817071950605917";s:1:"g";s:231:"310707833062544531467216844645561943098962370578916742760756974233153684446241745616739754688573566249846346213810020620706035698631735705193177208634153280990743680897033291523201037446504027887000748503867934381496920835149838635";}i:21;a:2:{s:1:"p";s:232:"1043838138616929138101811508697535923531994446448500728653891901609619113945535663253153367104375297723741585045382617087805586145467240001020812882375523417325765257159570623394415973410607015885926973240245828769638767158939735823";s:1:"g";s:231:"211284959053982880949257420097104560359997038327161027485101114225857008653586904671967082110943338617508039824126355934406108355113694160236445963650468176887494420082682469687380851945881864137800975727598046593748961975872182006";}i:22;a:2:{s:1:"p";s:231:"909481145780067907589091924270230177315783422840482719065855137220873943019392515645706882821956626647690572635519707871148396286852157642254684138616573098568906464473751784860772188993297829955265667930698434525595917268839160831";s:1:"g";s:231:"411306373730682918768088046461658053886047523482256086504433211926229153450331574028979947269836313494655588335578201035994494545773927011311403549789887334144260346261933762436411397706540542779238658495048143846325391633700408339";}i:23;a:2:{s:1:"p";s:231:"998772161604674730427208474561632709989449061544052364704570742358230797373567794007176639781433176998472046787230276993430790779126524790324206509581430785260876043040417441909101570474744218186298119505360616581421482343304505361";s:1:"g";s:231:"184733937063612803361298769841757157417723900158741181107006790853944625842943795481039244412016877898192770990773813962037207347519355631352186315162236644592559703304341212558034558069171398380113273099853523626005475129103034636";}i:24;a:2:{s:1:"p";s:232:"1211631790987909065279106290645741658732666570591761876339218049687009689063703460852927094478436804703232418641595286790833128247242322236659720330399908817197999763125434214867786755513779482406322331051070406373162250047920250789";s:1:"g";s:231:"133464538617751712105475405020034283166510480141148453432578028498474033289040983933470799356156378878000022691320750490030719324585709132852224359186694804553298879192734852754173248762941163867013509089588026892511564829994204431";}i:25;a:2:{s:1:"p";s:232:"1480888488064451833774956808070244282669247589809971713206520764621641705446162614681155410627412992481879670199414987542533382624645029313151496617517954653413410026066284178008253584891588852045810626847039641755473089536554922773";s:1:"g";s:231:"913189690685537274491321511987396961330148258005655893526179749241633423973343337308946510334297747881793256525675559159610647568566050735753323597640433431964439800847620009583803481087410232791728210821760728996331203279213947272";}i:26;a:2:{s:1:"p";s:232:"1226836596566030285671888769672320821039004799655006554366618638637080790239128907289006853315149550819913671825983025640271041255260358294952167094606385035928653956687684571574517682208206011184632341554573212143424439340894536707";s:1:"g";s:232:"1165167826252532206764102608676934821873844628569091073440126408824517260489370607025426954145855274315912579810136126737938857566389260232456536101214898786965422243604428182899785175865041677120867451350549315484291937166136764004";}i:27;a:2:{s:1:"p";s:232:"1299126867636766047256602510774249303897946838507797326381539542959828986746355819063983912580034597435296309466632887629584754859249612032021106825967545400294837414879858419551447679126128541532092139202509474234237614792211320507";s:1:"g";s:231:"557454771562979112928503109388852680893435316641935992058431451772623760588666541249846163311300085316181790874633653741197111690133694320561807770330887656762203562703745220895210253776537073041329766823041746432316834986737922878";}i:28;a:2:{s:1:"p";s:232:"1126348355679296469364456200534190821415558122462203950222173903971316162001039245110015744494619630001307006082897548431481233236573807001400784395505656822302868325141067593935428572148431711769877790056770349398782273732033932543";s:1:"g";s:231:"992021673708868582769366906807993213154273305041047666103200722689673139917893393228140356075089227443283350105873567260204733321860706890148864345986528697202036125039604459943243445725478860982681407323820119155437657100371338526";}i:29;a:2:{s:1:"p";s:232:"1008634401758053187128277736528417410192034136519415574669256634516119096233828450468977538112572526973392323180933841232544505680400539244347395331585330307268440666331715982213274229183991204285522535330619906085375274079227768459";s:1:"g";s:229:"8760572556759866083474396024852617365462326797230737921542173365405997497535302354545906342115080155661950187754873201977061047090180215735138055522021787946051807192598998411896616854579180955223805032820165391468693386400272571";}i:30;a:2:{s:1:"p";s:232:"1166978258595089617844403001173506915012122138015839804357937568870367230913358081275686767951974838107971386291410611977806257745948360325814106870379818730302342961515325103533493599551258196409588500690548494831769467819283926657";s:1:"g";s:231:"812710962266620243090428292895471184148359621440469875551097327425018412500712903590238262376264809756735213909943793204442223237431481867379981948700612089289422272562312522419823664998813366865358855830307271676644906505385900486";}i:31;a:2:{s:1:"p";s:232:"1302298468784249119897859605635105295493385466221287850101629491320472840125840398596019110842184371846880449698083893020753859720550094093407591344533647559507312410611357312646674683805014786093994912628676036696224037212157184447";s:1:"g";s:231:"554178797388666049055219638833783155765529248078367747326034365212425526271152990752929505555825569368390318252869310697577810339822779922460591657816810807115780260523476282093078547455605388274840263108672842888701583560113414480";}i:32;a:2:{s:1:"p";s:232:"1442931000879495418147830571703209032868629219398975970234579619558717538766726952628317588601304783460127319543298710724327794361540627879606358857914590949147783774965728031895515384676429380074454381434982743851365372673084575821";s:1:"g";s:232:"1243370638952605893651352051161751789940342061323296322682621985360092310205841028660332063743955170031003140637380278930009235738429325643370078390617842484869594029175229248055914742953616388093671357850175664014116837534257901300";}i:33;a:2:{s:1:"p";s:232:"1148631939654604996206773214574552575711307896990934696385104190030217192296044952385521649166190675676640218110404003177982075271795264830578900777976949290319265960261829395103171222603537402278457239415980314123796770451452349777";s:1:"g";s:231:"448023484821032996636639996750542199189362181239231401153219754636555491419612590302217492863117647800708873851242669804470761410341377037489017852304408246918090055485282225739486541777100726481671909427004627146773220357766465353";}i:34;a:2:{s:1:"p";s:232:"1393523907386733639196096063316267020192297325243477671179771572687950474193652521299745572736639931999553943306828133031329380137072125223794530447655767869824129331827371927406431824314926409286092407615670679430786622997473343069";s:1:"g";s:231:"158382239332012361059586498468810507761951071253874327107989888294225407513544700530720873616427478949372862299790858389591473207674049859637536330846828044918745064598396795657590498426743196990965328660346415613444898158459599150";}i:35;a:2:{s:1:"p";s:232:"1222102521241577470283074206070854512365381505703044952665199901251711264414931392126084324385248931164740262398980646038543572389444975748645047292454791849985041434539105121366323608243589248572317936672902512257895791961279944753";s:1:"g";s:231:"169474809564989953084527210878254013750630191626979057975836242572371875202170178801841933921565732612820027939995759973638573492141523255284416678413548269429265856232357410256501085766083506944544506248899177627896120912756013303";}i:36;a:2:{s:1:"p";s:232:"1538598708742095545080369228198463718092167812089180539057575039024868762502691630260434517572758932344173922950898274079386406523439552919172580086565148679698253538312693842622352860900237758454513286076544847373869014109979321933";s:1:"g";s:231:"487925873109303632774725988789554372098246151110994418866475560449103780481232838975655743841665990844058650418668869837797071102539887131618290573262237167406538025787225706255030517039749286358613977923363625043888262053791745638";}i:37;a:2:{s:1:"p";s:232:"1097899884450506484051905559182453553026916821622290305706630776055467106423904840844285706479146578446144665891581111216357975998894809415473529916388666801399881277039020074770237098134085307809567159080620682178430449377712188961";s:1:"g";s:231:"713299421426006881519029802202576054402261377160137162915585056231624159229306230285934068619440801936519514470570753298571802541176133350536243875118339091016873336372808782754280946665027375040616208507565862750376128043447148301";}i:38;a:2:{s:1:"p";s:232:"1444512863731935483894008702225378125585842694087894886366183274520771087738191267827986626161760688063530784261619654246386352435824102332177609005234887329162299752906328015345611754396942570774934472072201469346813666592126095319";s:1:"g";s:230:"71022242294633908238161350667189909739686489589295601215049118314301866007824223582964959139713235801443895454852929563171050201408606095135442608708015241740051890609221031027343612271279397254089991308258936096567240934245572172";}i:39;a:2:{s:1:"p";s:232:"1273921505529135134619471445603766730070275266833637077209371997021121191847495299878557836242176015913055701620097068240553902757712424908402825274359798411845571574397305804394784399551447648769938063688585195177797469676117292707";s:1:"g";s:231:"172283541835681082917921474708343318584309604663465791287861400143479265703505789482265599399730053181227908951029046784839847417910485792238689678397452497349792694795337120509247353125741777608749797251283134349847071985419946945";}i:40;a:2:{s:1:"p";s:232:"1391094208269651754228863172916777407766029968601221814793322964684263639354664514894064147017556309431689085598248754658855730462315479244796403513137082524919056979840050289629913330468113348066024861551070516586953578831954940287";s:1:"g";s:232:"1064795025524333155217046316426725709816790957250825507504827677074388754937495371228984429697045350593451967952162867994241570961967536898334578217100559209235672050677519860167586961789899607637975559733514499823460278430037576476";}i:41;a:2:{s:1:"p";s:232:"1326936468445641417245559449259189655277275904688276735759218876459280665414495776416728982820158299493847435395556882477708348526659451871434133327657573829220249539269158877916024342331304627334533741000563961956005708488896022881";s:1:"g";s:231:"560160325520918160311489004538756330652584142975803146221680066558825151966681835216098707623810048671320310293566100399843705481307636868232976533478296776776351705941749079437351750375489046635461241491940079270860197965945416491";}i:42;a:2:{s:1:"p";s:232:"1218560238812030632047384946207677724376675891003367919894642606676193534699851752823852750039116695047951403361183030635500544410234555075253604602470552567206345873731073012853104591337510965587671909822763481187950084516458148541";s:1:"g";s:232:"1116212605793882361334980508554999764613524510673113925014454336067379611972575174811960004123114872049074376846221629670991490051690110183964326474055506681823977538787010733251705995435908223148341012046785733295266820798998534733";}i:43;a:2:{s:1:"p";s:232:"1217497188427651645518008010219704097963219997072947918220282510627445392004815995384575298457524395356495753067496167745895373477700386523537698186007914458939259790774208461717994689738008876315744224012847133799009218346684830859";s:1:"g";s:231:"770511130507901438600412006983112284630991371571710484001330082877838444871356535886313179170160624860637206210159889225802967508583219897305328840950801900907190541603972767759028215668443657472137164937170393059374657350234172588";}i:44;a:2:{s:1:"p";s:232:"1384805737644402001602699295819222115889640213864823739426626748938803637018791449954061797401595116354246963498875102004687010135881571778446362154004089583318355206463990307092106845161235823666584330910755849289622581381706219763";s:1:"g";s:231:"300549098900728120997184377962666801713866244121245602255994692891031308924882229511798285554574949183744241271474954854124567793780282055959022388578786674058503642047846767669358674513850356363710515458249831883431353751436640473";}i:45;a:2:{s:1:"p";s:232:"1492587067635046724641688792619770082885080916623128596190835123187399555409237704094491882424098429004582220181182619740784070606699855534865664985479518843768489466772177132445303667209841765020506725096570944526583342827976693139";s:1:"g";s:232:"1325875501024611168460651086120280057597417113099909975171178841675907943309975119263343672690373708947175682795213117068208929462717160334883318825145705113989022565051297121267153447173858992622609588411242729579874123397975266138";}i:46;a:2:{s:1:"p";s:231:"906847226862001776111816505493768281038044494397978048283918521997355784196400638087866270344123622589898850349070632444514905302691870958199771371762471423025985936761842533697767348529899029836077448253984658354566967653666300291";s:1:"g";s:231:"736322087778788782539692146029647707897059850806268174498405656773634130296338358454597944410361988992697524598389896851941261557414721510027421303659079837206638916639575833006393233205754151775657992256732326725637747229302979816";}i:47;a:2:{s:1:"p";s:231:"890185901266080927782491491465517354612445249578323933865882607342218018045827339044063305815560761455409394432525412061214187429139579299492400591506581665066538172120639471965430764234311453555561931633194236909247720214805118073";s:1:"g";s:231:"124603950693163204561006130618370613293543114866078188752893479503564944442854829116472795873813395868608031842115370116074318303022427922128279623081129104975610062908095108555177761931096196714149047005610934112009256489171764836";}i:48;a:2:{s:1:"p";s:232:"1022859944913338265513498287914025160760413428632788273312840355167309743967660343293231033751474736710985228291770444169425283751203244350644086644312399632846696705942260278260962694665474670638153088334885364597590329213855838821";s:1:"g";s:226:"9300900657434489047696932947576507254742485851137640945740833346773894336289041369843665650418554527779923950617936614501875553729924367471021774760018370202907818481345597919412260900264979732317184833567650883567557893375062";}i:49;a:2:{s:1:"p";s:231:"847503998296101285006099790915650900236373726614141033690527723241117720398089645943375054063733472277302479655583554156249145819849151070540753896248678323721722706542142778548044002424582998724519091068547416460817463290942699611";s:1:"g";s:231:"331234074300921661629671326001536898454736192468494763379095145727215648933648617862566547316445817232073025874507971645175373540892437914378209189920515870658932521438504082293358796446613855932588162795845812833576149004264344863";}i:50;a:2:{s:1:"p";s:231:"776854996694680870329679766090923197499320601174183889649293954753262824403489810262166219938884720481651530046864995498795712155925117242820332769004044593138155353839210071553589166493553905531071130000245175488500608606205250473";s:1:"g";s:231:"122615309163484352435178123040514525950693264760022890223935351486389853053969215583729800598436270172453250408297048292547495756555972940864549104698760360917270926737887015081447655824274035565458153166275374845431297392097414896";}i:51;a:2:{s:1:"p";s:232:"1014670995663321290921359608373778357137361583080950879880689089887602978213452338329707495620559212973320829485461881514443972718327580018986415671475880393790411550869335287644265510938928754450088809257531645018845849163898576281";s:1:"g";s:231:"226285175444234122973784619180694638633082167482716005469342385327449875897886239234305738740923272773737253575122862208019661137330217557014525226385441537374271233018325429043614739444592408722828918457330769483139912858752454089";}i:52;a:2:{s:1:"p";s:232:"1513169936271423788180663828796897482214859916394590058813086550258563947455823332252203732874362687681400458889518212204992499000169381984431868914565922342454309296824550072503920915320186996860296769236804812815276715833511954449";s:1:"g";s:232:"1245465226405785393052937621442782210068505909794754716840697886490038597351985032447069389595318254694322269386159967688303058763948595197780433162530139509421500448636935611542180856628655340298116911739813872332241561279520583037";}i:53;a:2:{s:1:"p";s:231:"856013253876479059165623628305975849448863358527134908680506386730475791772900044328912984363736340417917938534652131715858635313983806851931477692304414025858982778155821878443831228714625883654404089352024899372025088563084316869";s:1:"g";s:231:"552321690037661308598423371621414370654966204550026610831501356822096243392290173211006773925495007312637920045552352583841618385583528133106087248629846785238349605708729343227241184823126680553458580263594415232887609278033875784";}i:54;a:2:{s:1:"p";s:232:"1334480887559536589949159249692733945384620792290589721623105750400119965602313717796597363544359710470206140367740972924185775527922974878933291445658045025445697156766756880651352317344857640429287980516377747569226931211212491243";s:1:"g";s:231:"831886041645277013617989310710106338581632774794225204139049756217555884181929382441547915129521121883033469509223234782099800019424095140055702151953921493983956381659390147459758077951959258488692700947152076829209345127239827417";}i:55;a:2:{s:1:"p";s:232:"1409778745614943123059960637458872383143362660474711587361838099172264328103771279599449433452471625362257540153827777349113762556225898756006249367026194953264828964987050273980148263779979224131073491468700936532944198371641899977";s:1:"g";s:231:"209776098029275436626677833731169078886117278885071715114505435642385983294326851305920611380028615674022483844583563627952192347687309821075096153883293433371184894010144321609833671939957316414645692604141259818517456628329910873";}i:56;a:2:{s:1:"p";s:231:"987430516189578827941284205088054611661620082263300587768516778434122699181082412846271052727003571281820389873181317063990985395433365942896367875649986698124817476989968806919034781078588254781147833741809007727914947756658579719";s:1:"g";s:231:"698200987352603681412105271807898748738354178489091119603323819681401784039318713333863338169737494530635558313935752562046668296212183293510873749175392352219364557252076204906131397081041002324767066945164857926826022730881675404";}i:57;a:2:{s:1:"p";s:231:"911040560362970417223048893768139389628988085687664013086009222099987221610406175395791423343767969898453296762333521288463623371559741795220949359469991966317300173096203451768448458436821759854332302902207049123095122563165328307";s:1:"g";s:231:"812594270498848930761688601344147752029772770381862776843635538689863728582355800020232123686093611039261541242167974286295835132480307822937387971672370687322097986874325541469317368635346834600976441766125378899144114323921195586";}i:58;a:2:{s:1:"p";s:231:"842219267974145775932989123792894671784125999773632266618794032004279619619519039224988473356968580745314383284533399642966645022341924016346852389496721864434033649276503114432343392698641490910905241779155079674669501466846833029";s:1:"g";s:231:"782544487507669192797122586247172939394023717046277995090644632052579755536328116096809168402110105266197800519534245921413986378461638788404319078240480929658281653750321747004440253112416813029050528374146052783221176298960313565";}i:59;a:2:{s:1:"p";s:232:"1525092809935288563055571570345820919524510847559774771965057561434975140299144568375358794076795210329084288787580378624089653481424466572254329602363278560207486423630141957923693225949486458225166351939026738254383383758746550647";s:1:"g";s:231:"263159922809445009879913179233924861644960413198762736113157873838038016723475464951892708348898454780740614412260641141522795265620349407440290686043887300757338238371334215462378864319590332417281238178704191943671667823961166359";}i:60;a:2:{s:1:"p";s:232:"1028460944421678739403869648025955612818770271689302644136310102933827246458867980827164258058168388339497134835171980844721573217633367276896282397205968182286615164389206641861298761008845793572995845616202743253555140748983244893";s:1:"g";s:231:"819672765703199092579137249865392990239671440769336584897585625379019575251829873924916934853746122876727468334182965088796386124896485109134891396778358088857805529756796787244840685815947720996926500076399919959153319935883154000";}i:61;a:2:{s:1:"p";s:232:"1116618938793971635251620742212333252084112686089695775091783024606337481417063400046973984308140430505905270470079059953893854704527630489326325210312207750227881050817557461457444716365677910986604362917828660471351341858494096857";s:1:"g";s:231:"886495389264431043361764083003188433619726956091423072234161147317167112643474214952357022594163640185279213659123211404675499610319150780444047197146211575454186803578750421194177193308281034306938461424526451109993556092290605627";}i:62;a:2:{s:1:"p";s:231:"797968355931248443337687572785194531681078668525894869616504982246134880136103339282591195913229534010078819186752873549484555106465378939218557464942306392378439519858664609681412161147401140973953299911521409960106976112377369951";s:1:"g";s:231:"640761121637205911582584925273104207639077147629241246006735106298865340150464943301800944597332710902710744600875720127926074244717989293323153036139147904419148401305887127992654239622527132611342941954632024239990149310032901493";}i:63;a:2:{s:1:"p";s:232:"1149737784597196134539684844606836077174184511853637046817912791784871386886645941003768607272989916774461791399081844778712220484980184567429117869606255891575455994880709403094980089125184082083924323339390199617654884285790410503";s:1:"g";s:232:"1039603101125034957436037513842799552783264469564219071603467222335050285123983992701815389502802987632956762276871132501712957623514952496732752114440497953627338896088394375658021187362290850795614408283008309971686190025693722153";}i:64;a:2:{s:1:"p";s:232:"1329797930634761192880862076059880539596186910848560549671049265461292267955242454490202990291540780566466579950852416159337549496195757247640919986667450812966261394943118725669861905621692926696165004880010479874148373172971610213";s:1:"g";s:231:"635837337839928249217276793990419059939905043474162074919430227356353695989613476295402258138887032051601585713030286174494298044263992707036482422495872394392828704770207161110057952905919230753270304119362774387785321873795683546";}i:65;a:2:{s:1:"p";s:232:"1448623913900261434798685222085379218669160577429273882531357393528490254936279125033819527984087800012125045586904590500187521846246409655319426639918743490196370521969556745886851634696767082843480238683377832803357594808338808789";s:1:"g";s:232:"1242441591251870653887844129258287272477292810570170069081695319311953376562545356798018649099374884003456979182728581452667824918519630973802906602011582350683406354751790448752315826286714466252353285493390468597894860032976159350";}i:66;a:2:{s:1:"p";s:232:"1529668939507791128869844490648290764124365901674422927387106692234341029103618077258533057496186461743031022527500511541916188830355814266429015729983198098357862460965845074171515400861687303837201652935516988746262569004563481137";s:1:"g";s:231:"360660974134492254118200341405376185297344709314085805544303296461805947453282575608141632805937006031503783222427477376904080696378020878384062503501827900451149127843292557616537602904756471733366682875566612490823990596275677543";}i:67;a:2:{s:1:"p";s:231:"964349802834715627091836311947560216190347334606515569347370133774200574976490727345212588410713504041991155364894697098411252472334205496527965699231720356863841683017206080615358842110850143586011962642589946348492970286665407969";s:1:"g";s:231:"929730835796228663589459296460175286247231890720354407494506948655435307304668112405072832284354983725176870181434323215671241174830416791009058499007576373683247657428144973843695554591048285334385411320546482122096833997170957438";}i:68;a:2:{s:1:"p";s:232:"1200697114919552440328212662493330951577090633392906181267524661711427686156563810555704977987849019161562995566572698389243095893050851873199166970487411925149684342035613532992590627108705912648804940551798506465761008844124620843";s:1:"g";s:231:"210840229717284786647061522612464250122170021966599147979091696189226789454714560674351814215640043731623851038273701713941465042304615442622261378902191416557966885769781607850757337283990327310991779274500108940892706318414163737";}i:69;a:2:{s:1:"p";s:232:"1505605269824790243792831609706828893984166952005042857668330387295629646099176754803575647869364684706773658989884573187558931362886298063556945978444360603261808118452381586301369212317883353307812109682258121601862761142502891243";s:1:"g";s:232:"1084946940052009414079442134492764126131699233360610931749616742969406318399538846909634709781884746606435633696011708795848205691494703339546378266099151348812964157880959214875332081239995818554049622469426669215553286217171990197";}i:70;a:2:{s:1:"p";s:231:"816293659194156584393426852964866212253294848481848239113280525200956078812795725547016870053079733390521590030205302119472344262085862246534098409593188906922670398233793986685054688205359526482886045473996570950709767907766332287";s:1:"g";s:231:"125543207479359049664289679776762548350219021118060184776896419904091327416143098271532647423069203715703939418436750054904161036732607263073370671224895462307089820071515048928316155155106995471046247116304202948872057424249829306";}i:71;a:2:{s:1:"p";s:231:"937909358947516337782226369107329834813267396990696800064373114984017087896265925553479913936810219544596193425124759913401224821463162739445133029127703779747659708487741259835192876317663968642084022533197690267855480324556527529";s:1:"g";s:231:"578517033963429110326177951658909289407442324189047815722917009976102126212418383103468613086046773738909381129731628643776381606497183416474147511436721740867586571298578391173413176636727370915614428453897927588536871545070706826";}i:72;a:2:{s:1:"p";s:231:"911550272168591326631587048781719864290181926192452902515376445349683296263628887572901987291151834516528416694948433228654143979995488104146391642798141995369742621984998796392603683788185226673225012070762425265022227280304690457";s:1:"g";s:231:"435611523987279849779799983928466846964355559414907696183238122605651893912177175547925756858491577574088472465417508238273767046169709657388574379877072876851067175453958959942263115528642058698110491508470757333448223479152968166";}i:73;a:2:{s:1:"p";s:232:"1402332241612496649303040369601818876241754896465490665184937776221374345017898846195563177922807182568607634848789855347331333564677335684945270608142923662833369689062726669830621769891269806986781199834351242524607209182727362697";s:1:"g";s:231:"788295437611846442150468706453593520179759913221608649431645370830934491660511057392020327584205620415434194214357441850022798625239262202825957968879464188504280320734830085023023361870953080951460626858564454404757439725700161728";}i:74;a:2:{s:1:"p";s:232:"1385588118482316945637342314640019438423845714093498454736894992477851611815122782181701750401675268595756082471037251485773810390075324501594034728931640633416343793046633227949070383016793194462388968861476522738244028507831412807";s:1:"g";s:232:"1051407953951842293497025880784993624653296083738495150909318042975954326467188611760483303718017506605889424046908175461440744704653882860969939760977844939897006735758164931979823290042430064727472581445761138927834062800381857331";}i:75;a:2:{s:1:"p";s:231:"978710653878765138245032780973262837628048824442834741766271800856407798633040866018143219855860066364565173258532133152860794957108413774041864442703022361098911014546932838970841896265536654441302583704650549691544524094461072893";s:1:"g";s:231:"828596696507489340388194242739437030691368481839839233808126012449055532045083652206448595030469705312890921141157727976947093518174537867725716826615058275916344778889368940911120325529008412131628881439241085844298695161516320553";}i:76;a:2:{s:1:"p";s:232:"1207869050442265806743029955005671272145050338468895879407536822447006913893944092569221761456800766031110931886064737811279146170983187046931749573257412308812343263137605940218514764728941135936260457381443965473446727029606288087";s:1:"g";s:231:"901689553109755299724889749491986982699260680669362599014476634410057613935478700557783089065666154315108435551124047123019756359394197131705864747694817007428554108935506622319753907531599531406412261181040137293635457527629166928";}i:77;a:2:{s:1:"p";s:232:"1253843053454842191496073929229960442713137064902092063097530760375305147828977522103815652822832423852327957157323143291242551095036701741131995598289925801806713520933881311587031812516333248233614882790453878318165294686629013069";s:1:"g";s:231:"792544431306829255892236222953864313824441744771937100881849165125912187035049340690583274721296595436406556486333849801845868860653775711166921783066039453091902252131197402979987834131940589379261131585088009418040811296418479470";}i:78;a:2:{s:1:"p";s:231:"888292115983090727383050041245510071901205022923621728740399250824091752574901194082071159280092849203038477423626851997364728759797869144784736703853891927718345111493348065946995574844270360480831713923673933284454590573945117963";s:1:"g";s:230:"33696947092788556772122343063346211890011409922110209522470356049181924373620706813436426151964317250350038187149729733343587721985790920558911543375733639941083283192766726820247487603481905775948491707522483335714118785605159459";}i:79;a:2:{s:1:"p";s:232:"1065050883104106794605549148848582174187670490934739354153582360382562310727039426519192822266718204976225715166151783557831632711336128952563917986548082358394005487114249579063266368998061115536978960094975378583758814372365078093";s:1:"g";s:231:"502815052869438460385725830457308481580545642069196745882872961945446262964900004194947659458399804093287259814745811856081827167061262636484787575169488738796518181394798689913840456698243916045055951843096761093530731109148515060";}} \ No newline at end of file diff --git a/Vendor/phpRPC/dhparams/96.dhp b/Vendor/phpRPC/dhparams/96.dhp new file mode 100644 index 00000000..92349672 --- /dev/null +++ b/Vendor/phpRPC/dhparams/96.dhp @@ -0,0 +1 @@ +a:200:{i:0;a:2:{s:1:"p";s:29:"47738868853409368611448259423";s:1:"g";s:29:"35731344447278389373151857379";}i:1;a:2:{s:1:"p";s:29:"54398515560371522763020384303";s:1:"g";s:29:"20945390328056174207502186797";}i:2;a:2:{s:1:"p";s:29:"67021188426992950294948561547";s:1:"g";s:29:"36939587946899170933046198189";}i:3;a:2:{s:1:"p";s:29:"39859896287770890834674542079";s:1:"g";s:29:"19966841823306563175123220931";}i:4;a:2:{s:1:"p";s:29:"76657699145424535679587536947";s:1:"g";s:29:"20742767732542452380807121413";}i:5;a:2:{s:1:"p";s:29:"65654697177391396856160066287";s:1:"g";s:29:"35809879532657391287512652743";}i:6;a:2:{s:1:"p";s:29:"71927430958542190463081134799";s:1:"g";s:29:"26380996146846587208902265941";}i:7;a:2:{s:1:"p";s:29:"73851341904947983664623532507";s:1:"g";s:29:"39064041849461247852710130779";}i:8;a:2:{s:1:"p";s:29:"75150031586910716586432162263";s:1:"g";s:29:"35111296103975510649443456551";}i:9;a:2:{s:1:"p";s:29:"48280401911664030048950789063";s:1:"g";s:29:"38708265162164817606775753013";}i:10;a:2:{s:1:"p";s:29:"46486903440519245437076708207";s:1:"g";s:29:"36853353883341331838222365225";}i:11;a:2:{s:1:"p";s:29:"71350463299297291211905999367";s:1:"g";s:29:"30011679077810814610369448397";}i:12;a:2:{s:1:"p";s:29:"49244741619315455361043774787";s:1:"g";s:29:"24808662195374590974786927029";}i:13;a:2:{s:1:"p";s:29:"75868764131932808789305748303";s:1:"g";s:29:"23008143271859447381803035283";}i:14;a:2:{s:1:"p";s:29:"43420198456255910520716195903";s:1:"g";s:29:"31396179578286978229414861957";}i:15;a:2:{s:1:"p";s:29:"65808217191785471358210112163";s:1:"g";s:29:"23010755437237062565991743601";}i:16;a:2:{s:1:"p";s:29:"46342915312221934564147401683";s:1:"g";s:29:"32030125422857259700058924785";}i:17;a:2:{s:1:"p";s:29:"64829190293054464121774784203";s:1:"g";s:29:"36833856892751915776286945241";}i:18;a:2:{s:1:"p";s:29:"45607701182765248395197208983";s:1:"g";s:29:"21399768901521056627247192929";}i:19;a:2:{s:1:"p";s:29:"44017242699060517442490417347";s:1:"g";s:29:"34633247284653303079399909831";}i:20;a:2:{s:1:"p";s:29:"53625999794377826447198971007";s:1:"g";s:29:"32287604526928583732085092887";}i:21;a:2:{s:1:"p";s:29:"63810410075798796194546009783";s:1:"g";s:29:"33103148562186353466279530571";}i:22;a:2:{s:1:"p";s:29:"55031538359753114159858892227";s:1:"g";s:29:"23141307673487499531413743651";}i:23;a:2:{s:1:"p";s:29:"69434150571492934132889103167";s:1:"g";s:29:"30086360725418560877456120447";}i:24;a:2:{s:1:"p";s:29:"74441928984373159899495560039";s:1:"g";s:29:"34511570476422028933751385293";}i:25;a:2:{s:1:"p";s:29:"59997318947177039408737791407";s:1:"g";s:29:"37250192862910145086661507129";}i:26;a:2:{s:1:"p";s:29:"64196128255368851154005218607";s:1:"g";s:29:"34000495373771857887090742069";}i:27;a:2:{s:1:"p";s:29:"59826698978200053030157188599";s:1:"g";s:29:"19964494685757012065098346707";}i:28;a:2:{s:1:"p";s:29:"62765736078018217621299172847";s:1:"g";s:29:"24033335135747484383237117689";}i:29;a:2:{s:1:"p";s:29:"51371314509993113368964576327";s:1:"g";s:29:"19894806293471511838941838425";}i:30;a:2:{s:1:"p";s:29:"62760444033308002378100678207";s:1:"g";s:29:"30291867805192457401765510895";}i:31;a:2:{s:1:"p";s:29:"53582209453070233186745035043";s:1:"g";s:29:"23236665247142302972696051523";}i:32;a:2:{s:1:"p";s:29:"58994643014783385857138676539";s:1:"g";s:29:"19937877643250391176571531199";}i:33;a:2:{s:1:"p";s:29:"48263329442960242226140798283";s:1:"g";s:29:"21427830008975221643678133239";}i:34;a:2:{s:1:"p";s:29:"62366601843842296162395153527";s:1:"g";s:29:"35945985312870131030534711981";}i:35;a:2:{s:1:"p";s:29:"72347374730426653226589947339";s:1:"g";s:29:"30316686633846692480439000229";}i:36;a:2:{s:1:"p";s:29:"66889481667385002256595238959";s:1:"g";s:29:"21467091715498685802445826655";}i:37;a:2:{s:1:"p";s:29:"57562601577612410905954202807";s:1:"g";s:29:"34758405076210401215630410679";}i:38;a:2:{s:1:"p";s:29:"63417186170491909088356422467";s:1:"g";s:29:"27136886202422383743778098461";}i:39;a:2:{s:1:"p";s:29:"76651191206554712261477581379";s:1:"g";s:29:"25399251868035504726174067835";}i:40;a:2:{s:1:"p";s:29:"39742911256893192535752596183";s:1:"g";s:29:"29759759175624969510221105241";}i:41;a:2:{s:1:"p";s:29:"53063241966256162112521986887";s:1:"g";s:29:"35220272870226041301738969745";}i:42;a:2:{s:1:"p";s:29:"64221489119473367767687041863";s:1:"g";s:29:"25840669648472436001824430091";}i:43;a:2:{s:1:"p";s:29:"60401269853569313228801931947";s:1:"g";s:29:"22842216079852083701198138345";}i:44;a:2:{s:1:"p";s:29:"50500264110803784895147849703";s:1:"g";s:29:"24516065342693939347117828967";}i:45;a:2:{s:1:"p";s:29:"61164830232419619474067092239";s:1:"g";s:29:"26352350231033249314852022313";}i:46;a:2:{s:1:"p";s:29:"51716169310525088129202326267";s:1:"g";s:29:"26869080532546514878512382181";}i:47;a:2:{s:1:"p";s:29:"62926434851243291755574116583";s:1:"g";s:29:"24702135412242925509885609547";}i:48;a:2:{s:1:"p";s:29:"63865341648786748578166981199";s:1:"g";s:29:"23148109461305702871386177549";}i:49;a:2:{s:1:"p";s:29:"72789069432219090760968655247";s:1:"g";s:29:"31725421034580831033290406407";}i:50;a:2:{s:1:"p";s:29:"70756969409504536529184861863";s:1:"g";s:29:"28734343666595496719979874355";}i:51;a:2:{s:1:"p";s:29:"50630182889501928368854656923";s:1:"g";s:29:"34567091595676569937103243609";}i:52;a:2:{s:1:"p";s:29:"45952510148678487096747574079";s:1:"g";s:29:"37518021674485079101709627061";}i:53;a:2:{s:1:"p";s:29:"42882857287768186855451631287";s:1:"g";s:29:"20526360990737333692515113039";}i:54;a:2:{s:1:"p";s:29:"50265722213854880338572192803";s:1:"g";s:29:"22320422205561467172183532507";}i:55;a:2:{s:1:"p";s:29:"52651538115728879925737034179";s:1:"g";s:29:"36248623767834351043173573133";}i:56;a:2:{s:1:"p";s:29:"71243579853974324810676006923";s:1:"g";s:29:"28678521167624470859587537987";}i:57;a:2:{s:1:"p";s:29:"44881273335703542822440685359";s:1:"g";s:29:"27890696956822713079463093069";}i:58;a:2:{s:1:"p";s:29:"54067724646431918836093765487";s:1:"g";s:29:"38671671346100133896621817829";}i:59;a:2:{s:1:"p";s:29:"77981751845097915350841714947";s:1:"g";s:29:"34109084447631028515541501111";}i:60;a:2:{s:1:"p";s:29:"41299579464656790538826461979";s:1:"g";s:29:"31559494063913514065552276299";}i:61;a:2:{s:1:"p";s:29:"43809367168096446620100258383";s:1:"g";s:29:"31617324402125986291976766901";}i:62;a:2:{s:1:"p";s:29:"41629110951264885953120606759";s:1:"g";s:29:"38406161804958433253138577097";}i:63;a:2:{s:1:"p";s:29:"63026171442062660193639618179";s:1:"g";s:29:"29507934963099337261103958697";}i:64;a:2:{s:1:"p";s:29:"76474084729118955201130431203";s:1:"g";s:29:"32171898945197339371170458907";}i:65;a:2:{s:1:"p";s:29:"78323059288301101312881667667";s:1:"g";s:29:"22199981962969777045604457961";}i:66;a:2:{s:1:"p";s:29:"48377222972554009039385650679";s:1:"g";s:29:"32614444658520497932785811087";}i:67;a:2:{s:1:"p";s:29:"49886103871936238106545100479";s:1:"g";s:29:"21092123691132028297201513947";}i:68;a:2:{s:1:"p";s:29:"43221299503205009879216909999";s:1:"g";s:29:"31490999503942396032305773621";}i:69;a:2:{s:1:"p";s:29:"72675669525257658331735232279";s:1:"g";s:29:"21625394843226904733988215413";}i:70;a:2:{s:1:"p";s:29:"60912699550998182788325971487";s:1:"g";s:29:"37125028105990641824493370751";}i:71;a:2:{s:1:"p";s:29:"41376435625834360066302056723";s:1:"g";s:29:"29184639342437770947343070079";}i:72;a:2:{s:1:"p";s:29:"75911859552795531794906334383";s:1:"g";s:29:"25591480945916785626340759655";}i:73;a:2:{s:1:"p";s:29:"65759239204590801774612362339";s:1:"g";s:29:"26155114179438446049102644089";}i:74;a:2:{s:1:"p";s:29:"65527216814120877501471071123";s:1:"g";s:29:"27930568859450263902637044387";}i:75;a:2:{s:1:"p";s:29:"70810182985925809810433127539";s:1:"g";s:29:"31957160993262417032979556405";}i:76;a:2:{s:1:"p";s:29:"57492899402310837998263313603";s:1:"g";s:29:"35724553374810107964858445377";}i:77;a:2:{s:1:"p";s:29:"43758636413285999568429004427";s:1:"g";s:29:"30488837552241539903120979149";}i:78;a:2:{s:1:"p";s:29:"56692097963982709200889953419";s:1:"g";s:29:"26271804900529999524482515699";}i:79;a:2:{s:1:"p";s:29:"77974047092081361669361958459";s:1:"g";s:29:"39126929749021168284193878989";}i:80;a:2:{s:1:"p";s:29:"78229682156975988879624724559";s:1:"g";s:29:"27911368145178527289382607881";}i:81;a:2:{s:1:"p";s:29:"62126252016749015886820739027";s:1:"g";s:29:"34055396134921086870545958899";}i:82;a:2:{s:1:"p";s:29:"67563355896875957624545837703";s:1:"g";s:29:"37486398928881331284746874917";}i:83;a:2:{s:1:"p";s:29:"50132370870533665921627496387";s:1:"g";s:29:"26059455883840798859750499105";}i:84;a:2:{s:1:"p";s:29:"39725206923751271728960689383";s:1:"g";s:29:"24609684584536618635376545477";}i:85;a:2:{s:1:"p";s:29:"51792948921405546760270684967";s:1:"g";s:29:"25995693514438136367087526063";}i:86;a:2:{s:1:"p";s:29:"55288338303675688577407630103";s:1:"g";s:29:"24223163922736270455212400515";}i:87;a:2:{s:1:"p";s:29:"52150198885087539120531512267";s:1:"g";s:29:"28166775980799901204464193159";}i:88;a:2:{s:1:"p";s:29:"64967370257521870837395382187";s:1:"g";s:29:"30197948617065071104206085765";}i:89;a:2:{s:1:"p";s:29:"57267259723766408733673540247";s:1:"g";s:29:"23386967103059011857791870243";}i:90;a:2:{s:1:"p";s:29:"52627911824296402395179157203";s:1:"g";s:29:"33293309894237358066888235147";}i:91;a:2:{s:1:"p";s:29:"71861809192052150172370739147";s:1:"g";s:29:"31044213605020388625039824137";}i:92;a:2:{s:1:"p";s:29:"70254513909085824681053192543";s:1:"g";s:29:"28798349198845097401709269813";}i:93;a:2:{s:1:"p";s:29:"41403540291961233368774818919";s:1:"g";s:29:"28798985963850612805220493955";}i:94;a:2:{s:1:"p";s:29:"48430431805183902912293107223";s:1:"g";s:29:"31404742280166410839686792815";}i:95;a:2:{s:1:"p";s:29:"51473404191184755474663299999";s:1:"g";s:29:"33843389600977412378505334397";}i:96;a:2:{s:1:"p";s:29:"70565571849996199202961193307";s:1:"g";s:29:"21716627740009390905807789193";}i:97;a:2:{s:1:"p";s:29:"78437005746991951735505214167";s:1:"g";s:29:"26924323797938784922617646411";}i:98;a:2:{s:1:"p";s:29:"43843055850061764331501276463";s:1:"g";s:29:"31987298334225618123314578601";}i:99;a:2:{s:1:"p";s:29:"53682770566445504403330150107";s:1:"g";s:29:"38927064063740890597015961647";}i:100;a:2:{s:1:"p";s:29:"48994954423636463292887914919";s:1:"g";s:29:"32652856528784949016397405041";}i:101;a:2:{s:1:"p";s:29:"44897157586817342996019100247";s:1:"g";s:29:"38840533683921393467308020649";}i:102;a:2:{s:1:"p";s:29:"67538483715108583872805797647";s:1:"g";s:29:"29919536376822345692569617879";}i:103;a:2:{s:1:"p";s:29:"50717592467559574799527034903";s:1:"g";s:29:"21517893190499507102203033779";}i:104;a:2:{s:1:"p";s:29:"70772395177637170507552342367";s:1:"g";s:29:"39434308756454820138634504439";}i:105;a:2:{s:1:"p";s:29:"53445905772090528659325390647";s:1:"g";s:29:"22551665344611641752027006601";}i:106;a:2:{s:1:"p";s:29:"52474468077274345269151992383";s:1:"g";s:29:"33352638404672259758390964327";}i:107;a:2:{s:1:"p";s:29:"67114005106800452560101178583";s:1:"g";s:29:"33084264118243593357598139587";}i:108;a:2:{s:1:"p";s:29:"58754852803087648151383432619";s:1:"g";s:29:"29086302567025374338700003541";}i:109;a:2:{s:1:"p";s:29:"63212231552431384571059657007";s:1:"g";s:29:"35530559402100927792425660111";}i:110;a:2:{s:1:"p";s:29:"42196611473333337298462210787";s:1:"g";s:29:"24592858785758227363491641241";}i:111;a:2:{s:1:"p";s:29:"44047438903651919269497203819";s:1:"g";s:29:"33075102551287629845592080029";}i:112;a:2:{s:1:"p";s:29:"52434265050670307985847764863";s:1:"g";s:29:"29887639044793235583920349563";}i:113;a:2:{s:1:"p";s:29:"54506429692472361223143536003";s:1:"g";s:29:"27693480481313114708529170763";}i:114;a:2:{s:1:"p";s:29:"72845129316148286033002738187";s:1:"g";s:29:"22179932387795580737090272661";}i:115;a:2:{s:1:"p";s:29:"71067088953897971478659333927";s:1:"g";s:29:"21865125582832109553224763593";}i:116;a:2:{s:1:"p";s:29:"50765915006154815563652014379";s:1:"g";s:29:"24925324101591485419008597689";}i:117;a:2:{s:1:"p";s:29:"41796273330675329512689479027";s:1:"g";s:29:"34498285623103961201616530779";}i:118;a:2:{s:1:"p";s:29:"71667652951249290315789870947";s:1:"g";s:29:"28597584821952440893599410119";}i:119;a:2:{s:1:"p";s:29:"40661876296207694113479633203";s:1:"g";s:29:"34618495347559751713231561811";}i:120;a:2:{s:1:"p";s:29:"75584625760448598854619320747";s:1:"g";s:29:"33825371145156064291302499673";}i:121;a:2:{s:1:"p";s:29:"72900646949748701155153254023";s:1:"g";s:29:"39056661372189487534797810227";}i:122;a:2:{s:1:"p";s:29:"39725262448989342209900586647";s:1:"g";s:29:"27012300571607327239173217505";}i:123;a:2:{s:1:"p";s:29:"70291076132593834744489638659";s:1:"g";s:29:"28287870352495913858579279891";}i:124;a:2:{s:1:"p";s:29:"68223492838054012745867773019";s:1:"g";s:29:"29812634632059772397466036447";}i:125;a:2:{s:1:"p";s:29:"53346092907654611928569785007";s:1:"g";s:29:"20380231076764775013716891749";}i:126;a:2:{s:1:"p";s:29:"42269250412327988046698168879";s:1:"g";s:29:"22359387614414132557852459585";}i:127;a:2:{s:1:"p";s:29:"57320431477944067979431873019";s:1:"g";s:29:"36389842917475191481639469737";}i:128;a:2:{s:1:"p";s:29:"53385052160780507951010260483";s:1:"g";s:29:"24906742945156753228249405845";}i:129;a:2:{s:1:"p";s:29:"77319125713145958575993682839";s:1:"g";s:29:"32250111047089288670189735029";}i:130;a:2:{s:1:"p";s:29:"75162993662684965129714771847";s:1:"g";s:29:"25661752946886423597912692337";}i:131;a:2:{s:1:"p";s:29:"45405625268025110880402518087";s:1:"g";s:29:"36319773469129114154499369695";}i:132;a:2:{s:1:"p";s:29:"59088448884756478306290294419";s:1:"g";s:29:"32191641691724471525681426191";}i:133;a:2:{s:1:"p";s:29:"48391361101895671980136152047";s:1:"g";s:29:"28674669966387337925758056971";}i:134;a:2:{s:1:"p";s:29:"60566037922797273575059507943";s:1:"g";s:29:"34215739467127691572238119127";}i:135;a:2:{s:1:"p";s:29:"59514789385135504034490479963";s:1:"g";s:29:"34710883816976378062106378581";}i:136;a:2:{s:1:"p";s:29:"72245746528041664913295702167";s:1:"g";s:29:"38377548355684432345447431019";}i:137;a:2:{s:1:"p";s:29:"77057467563788368450273635347";s:1:"g";s:29:"24241201973162188054931592279";}i:138;a:2:{s:1:"p";s:29:"43584371382806814935291636579";s:1:"g";s:29:"36659077432871194105682472635";}i:139;a:2:{s:1:"p";s:29:"53005996620921200751055268363";s:1:"g";s:29:"39257201959355896039903321299";}i:140;a:2:{s:1:"p";s:29:"42597100015430501275680415787";s:1:"g";s:29:"32728428281570006218679496853";}i:141;a:2:{s:1:"p";s:29:"57712518549539943687407899799";s:1:"g";s:29:"28523188239456579421576097165";}i:142;a:2:{s:1:"p";s:29:"57597321462679122556677087827";s:1:"g";s:29:"24238811025555864703506297729";}i:143;a:2:{s:1:"p";s:29:"52694154096382067677036327499";s:1:"g";s:29:"33003354138724083947013916347";}i:144;a:2:{s:1:"p";s:29:"49168587190281246808731914159";s:1:"g";s:29:"24787429202019511436089021743";}i:145;a:2:{s:1:"p";s:29:"64119909108206836355870531579";s:1:"g";s:29:"32491957206216938161091275705";}i:146;a:2:{s:1:"p";s:29:"50467793876433382124768013347";s:1:"g";s:29:"25130214130640956081967953409";}i:147;a:2:{s:1:"p";s:29:"58411160562120944539229614679";s:1:"g";s:29:"26984522061879150564144369855";}i:148;a:2:{s:1:"p";s:29:"40009347006163207215081987803";s:1:"g";s:29:"35770013420048480039829342671";}i:149;a:2:{s:1:"p";s:29:"70624660658773357720766101463";s:1:"g";s:29:"35824369666376333976531890557";}i:150;a:2:{s:1:"p";s:29:"64341975464068240469532696503";s:1:"g";s:29:"32530921439798458540338308785";}i:151;a:2:{s:1:"p";s:29:"50960275061167921310203607999";s:1:"g";s:29:"32132617625550502941234012677";}i:152;a:2:{s:1:"p";s:29:"56797267799962419081951774167";s:1:"g";s:29:"34288942257253430908202805755";}i:153;a:2:{s:1:"p";s:29:"58074017368865007334964216003";s:1:"g";s:29:"35729271862311203945689979405";}i:154;a:2:{s:1:"p";s:29:"40223717844890578002433478807";s:1:"g";s:29:"29589708703140870455838217981";}i:155;a:2:{s:1:"p";s:29:"46164472770902986360821507539";s:1:"g";s:29:"33305967083143761363730485247";}i:156;a:2:{s:1:"p";s:29:"51440898823119489454011434939";s:1:"g";s:29:"23297809258485493478497527275";}i:157;a:2:{s:1:"p";s:29:"69137161537503320226750697643";s:1:"g";s:29:"29057927675001690950633562415";}i:158;a:2:{s:1:"p";s:29:"70368416471670772916685973187";s:1:"g";s:29:"26999604070693000537404791371";}i:159;a:2:{s:1:"p";s:29:"63337430803646519385776522267";s:1:"g";s:29:"39568994791668376175953012565";}i:160;a:2:{s:1:"p";s:29:"44701686190263648211731573419";s:1:"g";s:29:"37932575585630911059257354979";}i:161;a:2:{s:1:"p";s:29:"67061963534677418365284083843";s:1:"g";s:29:"34424441366959344012129849399";}i:162;a:2:{s:1:"p";s:29:"73686066909490063572068902667";s:1:"g";s:29:"28555084362370984960397877705";}i:163;a:2:{s:1:"p";s:29:"67527858922200909359786778983";s:1:"g";s:29:"30749239501627454371477786151";}i:164;a:2:{s:1:"p";s:29:"61043739066730320355165466543";s:1:"g";s:29:"21595545896109312433802159723";}i:165;a:2:{s:1:"p";s:29:"45334723448893279488516029423";s:1:"g";s:29:"37137146908205066290903839065";}i:166;a:2:{s:1:"p";s:29:"56308214005582002693555810227";s:1:"g";s:29:"24843791296725163102719345885";}i:167;a:2:{s:1:"p";s:29:"67533150567370173925041652007";s:1:"g";s:29:"30782893351115458792404891185";}i:168;a:2:{s:1:"p";s:29:"77141896439196678834655501223";s:1:"g";s:29:"36061461453268822310804404211";}i:169;a:2:{s:1:"p";s:29:"53464136308124898869051497703";s:1:"g";s:29:"21070840867138524281210954559";}i:170;a:2:{s:1:"p";s:29:"43906866776363067808866128183";s:1:"g";s:29:"31371970727448398345771909917";}i:171;a:2:{s:1:"p";s:29:"42951929549489979042061459067";s:1:"g";s:29:"35303481350375126063754180319";}i:172;a:2:{s:1:"p";s:29:"55584206157809351576484752699";s:1:"g";s:29:"27521324978891503871880098457";}i:173;a:2:{s:1:"p";s:29:"64082684138871018024834206363";s:1:"g";s:29:"35430132693162906364375555257";}i:174;a:2:{s:1:"p";s:29:"72274680235256183639513224187";s:1:"g";s:29:"39323298720223462507539214629";}i:175;a:2:{s:1:"p";s:29:"50270465159644897332267799847";s:1:"g";s:29:"32162138971239505380120254023";}i:176;a:2:{s:1:"p";s:29:"71172742562279238052232728379";s:1:"g";s:29:"28087698829250168062118773909";}i:177;a:2:{s:1:"p";s:29:"58279975107815369320968409643";s:1:"g";s:29:"37477871871950017488642962513";}i:178;a:2:{s:1:"p";s:29:"76149833977762808075325714263";s:1:"g";s:29:"33495819233171658198843244729";}i:179;a:2:{s:1:"p";s:29:"78903549728711268080275522043";s:1:"g";s:29:"35575753121439896828664997439";}i:180;a:2:{s:1:"p";s:29:"50246227352468831277581528819";s:1:"g";s:29:"22165161926944506968934210845";}i:181;a:2:{s:1:"p";s:29:"40366543204773291628848006179";s:1:"g";s:29:"37491409231401195990400236255";}i:182;a:2:{s:1:"p";s:29:"52485686141888680631881366979";s:1:"g";s:29:"25008339028119954369958601375";}i:183;a:2:{s:1:"p";s:29:"75310123834070506632175194923";s:1:"g";s:29:"24911739307945577462298528211";}i:184;a:2:{s:1:"p";s:29:"43287453884743355180493459983";s:1:"g";s:29:"37431226064016553223888614739";}i:185;a:2:{s:1:"p";s:29:"72668048134235584782124599179";s:1:"g";s:29:"36083914805133754503902359713";}i:186;a:2:{s:1:"p";s:29:"42587035483492360208542295483";s:1:"g";s:29:"29425547602658008334973977237";}i:187;a:2:{s:1:"p";s:29:"48660742813847790093577802723";s:1:"g";s:29:"22181696030381210296639395281";}i:188;a:2:{s:1:"p";s:29:"43358224144805388273357480587";s:1:"g";s:29:"39214031095936595183935153561";}i:189;a:2:{s:1:"p";s:29:"78569919398561957497150141427";s:1:"g";s:29:"27386092272055272984209278553";}i:190;a:2:{s:1:"p";s:29:"71756187727640118653252286707";s:1:"g";s:29:"23705829101416778657726552921";}i:191;a:2:{s:1:"p";s:29:"51779331839710276181002026347";s:1:"g";s:29:"25380613792873774698286228915";}i:192;a:2:{s:1:"p";s:29:"57342881303922666441386957279";s:1:"g";s:29:"20848819641117789823622350199";}i:193;a:2:{s:1:"p";s:29:"70002251023023159545354683883";s:1:"g";s:29:"36610934624864460295158944359";}i:194;a:2:{s:1:"p";s:29:"44910825886538421594132535403";s:1:"g";s:29:"30512121148739912553086530975";}i:195;a:2:{s:1:"p";s:29:"75997480947050915451016792487";s:1:"g";s:29:"25177189795127991088001819331";}i:196;a:2:{s:1:"p";s:29:"71210454010817147751246783827";s:1:"g";s:29:"24081482543177517821419798409";}i:197;a:2:{s:1:"p";s:29:"48178222020174159336951481379";s:1:"g";s:29:"23875634060583990786793373517";}i:198;a:2:{s:1:"p";s:29:"41053972333108758025596811307";s:1:"g";s:29:"23250518637280344226689511927";}i:199;a:2:{s:1:"p";s:29:"65532547845146082502279866959";s:1:"g";s:29:"21702436153057868635835641145";}} \ No newline at end of file diff --git a/Vendor/phpRPC/pecl/xxtea/CREDITS b/Vendor/phpRPC/pecl/xxtea/CREDITS new file mode 100644 index 00000000..4698d54f --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/CREDITS @@ -0,0 +1,2 @@ +XXTEA PHP extension +Ma Bingyao (andot@coolcode.cn) diff --git a/Vendor/phpRPC/pecl/xxtea/INSTALL b/Vendor/phpRPC/pecl/xxtea/INSTALL new file mode 100644 index 00000000..258fc8a5 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/INSTALL @@ -0,0 +1,66 @@ +Installing of XXTEA PHP package. + +There are many ways to build the package. Below you can find details for most +useful ways of package building: + +1. with PHP +2. with phpize utility +3. under Windows using Microsoft Visual C (.NET or VC6) + +----------------------------------------------------------------------------- +Way 1: Building the package with PHP +----------------------------------------------------------------------------- + +1. Create ext/xxtea folder in the php-source-folder. Copy all files + from the package into created folder. + +2. Run + ./buildconf + to rebuild PHP's configure script. + +3. Compile php with option: + --enable-xxtea to build bundled into PHP module + --enable-xxtea=shared to build dinamycally loadable module + +----------------------------------------------------------------------------- +Way 2: Building the package with phpize utility +----------------------------------------------------------------------------- + +1. Unpack contents of the package. + +2. Run + phpize + script, which will prepare environment for building XXTEA package. + +3. Run + ./configure --enable-xxtea=shared + to generate makefile + +4. Run + make + to build XXTEA extension library. It will be placed into + ./modules folder. + +5. Run + make install + to install XXTEA extension library into PHP + +----------------------------------------------------------------------------- +Way 3: Building the package under Windows using Microsoft Visual C (.NET or VC6) +----------------------------------------------------------------------------- +1. Create ext/xxtea folder in the php-source-folder. Copy all files + from the package into created folder. + +2. Copy php4ts.lib (for PHP4) or php5ts.lib (for PHP5) static library from + your version of PHP into ext/xxtea folder. + +3. Open php_xxtea.sln - solution file under MSVC.NET or php_xxtea.dsw - + workspace file under MSVC6. Try to build Release_php4 (for PHP4) or Release_php5 + (for PHP5) configuration. + +4. Copy php_xxtea.dll from ext/xxtea/Release_php4 or ext/xxtea/Release_php5 + into {extension_dir} folder. Path to {extension_dir} can be found in php.ini + +5. Add line + extension=php_xxtea.dll + into php.ini diff --git a/Vendor/phpRPC/pecl/xxtea/LICENSE b/Vendor/phpRPC/pecl/xxtea/LICENSE new file mode 100644 index 00000000..8d3fa076 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/LICENSE @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + ". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + +This software consists of voluntary contributions made by many +individuals on behalf of the PHP Group. + +The PHP Group can be contacted via Email at group@php.net. + +For more information on the PHP Group and the PHP project, +please see . + +PHP includes the Zend Engine, freely available at +. diff --git a/Vendor/phpRPC/pecl/xxtea/README b/Vendor/phpRPC/pecl/xxtea/README new file mode 100644 index 00000000..4a771bb2 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/README @@ -0,0 +1,28 @@ +XXTEA PHP extension + +What is it? +----------------------------------------------- +This extension based on xxtea library, which provides a set of functions +for encrypt or decrypt data with XXTEA algorithm. + + + +How to install it? +----------------------------------------------- +See INSTALL for installation instructions. + + + +How to use it? +----------------------------------------------- +string xxtea_encrypt(string data, string key) + +Encrypt data using XXTEA algorithm. The key is a 16 bytes(128 bits) string. + +string xxtea_decrypt(string data, string key) + +Decrypt data using XXTEA algorithm. The key is a 16 bytes(128 bits) string. + +string xxtea_info() + +Get the version information. \ No newline at end of file diff --git a/Vendor/phpRPC/pecl/xxtea/config.m4 b/Vendor/phpRPC/pecl/xxtea/config.m4 new file mode 100644 index 00000000..b9a24e66 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/config.m4 @@ -0,0 +1,7 @@ +PHP_ARG_ENABLE(xxtea, xxtea module, +[ --enable-xxtea Enable xxtea module.]) + +if test "$PHP_XXTEA" != "no"; then + PHP_NEW_EXTENSION(xxtea, php_xxtea.c xxtea.c, $ext_shared) + AC_DEFINE(HAVE_XXTEA, 1, [Have XXTEA library]) +fi diff --git a/Vendor/phpRPC/pecl/xxtea/config.w32 b/Vendor/phpRPC/pecl/xxtea/config.w32 new file mode 100644 index 00000000..63ad7168 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/config.w32 @@ -0,0 +1,6 @@ +ARG_ENABLE("xxtea", "xxtea module", "no"); + +if (PHP_XXTEA != "no") { + EXTENSION("xxtea", "php_xxtea.c xxtea.c"); +} + diff --git a/Vendor/phpRPC/pecl/xxtea/php_xxtea.c b/Vendor/phpRPC/pecl/xxtea/php_xxtea.c new file mode 100644 index 00000000..cf0da4b5 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/php_xxtea.c @@ -0,0 +1,193 @@ +/*********************************************************************** + + Copyright 2006-2007 Ma Bingyao + + These sources is free software. Redistributions of source code must + retain the above copyright notice. Redistributions in binary form + must reproduce the above copyright notice. You can redistribute it + freely. You can use it with any free or commercial software. + + These sources is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. Without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + You may contact the author by: + e-mail: andot@coolcode.cn + +*************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#if HAVE_XXTEA +#include "php_xxtea.h" +#include "ext/standard/info.h" /* for phpinfo() functions */ +#include "xxtea.h" + +/* compiled function list so Zend knows what's in this module */ +zend_function_entry xxtea_functions[] = +{ + ZEND_FE(xxtea_encrypt, NULL) + ZEND_FE(xxtea_decrypt, NULL) + ZEND_FE(xxtea_info, NULL) + {NULL, NULL, NULL} +}; + +/* compiled module information */ +zend_module_entry xxtea_module_entry = +{ + STANDARD_MODULE_HEADER, + XXTEA_MODULE_NAME, + xxtea_functions, + ZEND_MINIT(xxtea), + ZEND_MSHUTDOWN(xxtea), + NULL, + NULL, + ZEND_MINFO(xxtea), + XXTEA_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +/* implement standard "stub" routine to introduce ourselves to Zend */ +#if defined(COMPILE_DL_XXTEA) +ZEND_GET_MODULE(xxtea) +#endif + +static xxtea_long *xxtea_to_long_array(unsigned char *data, xxtea_long len, int include_length, xxtea_long *ret_len) { + xxtea_long i, n, *result; + n = len >> 2; + n = (((len & 3) == 0) ? n : n + 1); + if (include_length) { + result = (xxtea_long *)emalloc((n + 1) << 2); + result[n] = len; + *ret_len = n + 1; + } else { + result = (xxtea_long *)emalloc(n << 2); + *ret_len = n; + } + memset(result, 0, n << 2); + for (i = 0; i < len; i++) { + result[i >> 2] |= (xxtea_long)data[i] << ((i & 3) << 3); + } + return result; +} + +static unsigned char *xxtea_to_byte_array(xxtea_long *data, xxtea_long len, int include_length, xxtea_long *ret_len) { + xxtea_long i, n, m; + unsigned char *result; + n = len << 2; + if (include_length) { + m = data[len - 1]; + if ((m < n - 7) || (m > n - 4)) return NULL; + n = m; + } + result = (unsigned char *)emalloc(n + 1); + for (i = 0; i < n; i++) { + result[i] = (unsigned char)((data[i >> 2] >> ((i & 3) << 3)) & 0xff); + } + result[n] = '\0'; + *ret_len = n; + return result; +} + +static unsigned char *php_xxtea_encrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) { + unsigned char *result; + xxtea_long *v, *k, v_len, k_len; + v = xxtea_to_long_array(data, len, 1, &v_len); + k = xxtea_to_long_array(key, 16, 0, &k_len); + xxtea_long_encrypt(v, v_len, k); + result = xxtea_to_byte_array(v, v_len, 0, ret_len); + efree(v); + efree(k); + return result; +} + +static unsigned char *php_xxtea_decrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) { + unsigned char *result; + xxtea_long *v, *k, v_len, k_len; + v = xxtea_to_long_array(data, len, 0, &v_len); + k = xxtea_to_long_array(key, 16, 0, &k_len); + xxtea_long_decrypt(v, v_len, k); + result = xxtea_to_byte_array(v, v_len, 1, ret_len); + efree(v); + efree(k); + return result; +} + +/* {{{ proto string xxtea_encrypt(string data, string key) + Encrypt string using XXTEA algorithm */ +ZEND_FUNCTION(xxtea_encrypt) +{ + unsigned char *data, *key; + unsigned char *result; + xxtea_long data_len, key_len, ret_length; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &data, &data_len, &key, &key_len) == FAILURE) { + return; + } + if (data_len == 0) RETVAL_STRINGL(NULL, 0, 0); + if (key_len != 16) RETURN_FALSE; + result = php_xxtea_encrypt(data, data_len, key, &ret_length); + if (result != NULL) { + RETVAL_STRINGL((char *)result, ret_length, 0); + } else { + RETURN_FALSE; + } +} +/* }}} */ + + +/* {{{ proto string xxtea_decrypt(string data, string key) + Decrypt string using XXTEA algorithm */ +ZEND_FUNCTION(xxtea_decrypt) +{ + unsigned char *data, *key; + unsigned char *result; + xxtea_long data_len, key_len, ret_length; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &data, &data_len, &key, &key_len) == FAILURE) { + return; + } + if (data_len == 0) RETVAL_STRINGL(NULL, 0, 0); + if (key_len != 16) RETURN_FALSE; + result = php_xxtea_decrypt(data, data_len, key, &ret_length); + if (result != NULL) { + RETVAL_STRINGL((char *)result, ret_length, 0); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +ZEND_MINIT_FUNCTION(xxtea) +{ + return SUCCESS; +} + +ZEND_MSHUTDOWN_FUNCTION(xxtea) +{ + return SUCCESS; +} + +ZEND_MINFO_FUNCTION(xxtea) +{ + php_info_print_table_start(); + php_info_print_table_row(2, "xxtea support", "enabled"); + php_info_print_table_row(2, "xxtea module version", XXTEA_VERSION); + php_info_print_table_row(2, "xxtea author", XXTEA_AUTHOR); + php_info_print_table_row(2, "xxtea homepage", XXTEA_HOMEPAGE); + php_info_print_table_end(); +} + +ZEND_FUNCTION(xxtea_info) +{ + array_init(return_value); + add_assoc_string(return_value, "ext_version", XXTEA_VERSION, 1); + add_assoc_string(return_value, "ext_build_date", XXTEA_BUILD_DATE, 1); + add_assoc_string(return_value, "ext_author", XXTEA_AUTHOR, 1); + add_assoc_string(return_value, "ext_homepage", XXTEA_HOMEPAGE, 1); +} + +#endif /* if HAVE_XXTEA */ diff --git a/Vendor/phpRPC/pecl/xxtea/php_xxtea.dsp b/Vendor/phpRPC/pecl/xxtea/php_xxtea.dsp new file mode 100644 index 00000000..1554b900 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/php_xxtea.dsp @@ -0,0 +1,179 @@ +# Microsoft Developer Studio Project File - Name="php_xxtea" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=php_xxtea - Win32 Debug_php5 +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "php_xxtea.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "php_xxtea.mak" CFG="php_xxtea - Win32 Debug_php5" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "php_xxtea - Win32 Debug_php5" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "php_xxtea - Win32 Release_php5" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "php_xxtea - Win32 Debug_php4" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "php_xxtea - Win32 Release_php4" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "php_xxtea - Win32 Debug_php5" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_php5" +# PROP BASE Intermediate_Dir "Debug_php5" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_php5" +# PROP Intermediate_Dir "Debug_php5" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /ZI /W3 /Od /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=1" /D "_MBCS" /Gm /GZ /c /GX +# ADD CPP /nologo /MTd /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /ZI /W3 /Od /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=1" /D "_MBCS" /Gm /GZ /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /out:"Debug_php5\php_xxtea.dll" /incremental:yes /libpath:"../../Release_TS" /debug /pdb:"Debug_php5\php_xxtea.pdb" /pdbtype:sept /subsystem:windows /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /out:"Debug_php5\php_xxtea.dll" /incremental:yes /libpath:"../../Release_TS" /debug /pdb:"Debug_php5\php_xxtea.pdb" /pdbtype:sept /subsystem:windows /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 + +!ELSEIF "$(CFG)" == "php_xxtea - Win32 Release_php5" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_php5" +# PROP BASE Intermediate_Dir "Release_php5" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_php5" +# PROP Intermediate_Dir "Release_php5" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /W3 /O1 /Og /Oi /Os /Oy /GT /G6 /GA /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=0" /D "_MBCS" /GF /Gy /TC /c /GX +# ADD CPP /nologo /MD /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /W3 /O1 /Og /Oi /Os /Oy /GT /G6 /GA /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=0" /D "_MBCS" /GF /Gy /TC /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /out:"Release_php5\php_xxtea.dll" /incremental:no /libpath:"../../Release_TS" /pdbtype:sept /subsystem:windows /opt:ref /opt:icf /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /out:"Release_php5\php_xxtea.dll" /incremental:no /libpath:"../../Release_TS" /pdbtype:sept /subsystem:windows /opt:ref /opt:icf /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 + +!ELSEIF "$(CFG)" == "php_xxtea - Win32 Debug_php4" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_php4" +# PROP BASE Intermediate_Dir "Debug_php4" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_php4" +# PROP Intermediate_Dir "Debug_php4" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /ZI /W3 /Od /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=1" /D "_MBCS" /Gm /GZ /c /GX +# ADD CPP /nologo /MTd /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /ZI /W3 /Od /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=1" /D "_MBCS" /Gm /GZ /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /out:"Debug_php4\php_xxtea.dll" /incremental:yes /libpath:"../../Release_TS" /debug /pdb:"Debug_php4\php_xxtea.pdb" /pdbtype:sept /subsystem:windows /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /out:"Debug_php4\php_xxtea.dll" /incremental:yes /libpath:"../../Release_TS" /debug /pdb:"Debug_php4\php_xxtea.pdb" /pdbtype:sept /subsystem:windows /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 + +!ELSEIF "$(CFG)" == "php_xxtea - Win32 Release_php4" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_php4" +# PROP BASE Intermediate_Dir "Release_php4" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_php4" +# PROP Intermediate_Dir "Release_php4" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /W3 /O1 /Og /Oi /Os /Oy /GT /G6 /GA /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=0" /D "_MBCS" /GF /Gy /TC /c /GX +# ADD CPP /nologo /MD /I "../.." /I "../../main" /I "../../Zend" /I "../../TSRM" /W3 /O1 /Og /Oi /Os /Oy /GT /G6 /GA /D "HAVE_XXTEA" /D "COMPILE_DL_XXTEA" /D "ZTS" /D "NDEBUG" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "ZEND_DEBUG=0" /D "_MBCS" /GF /Gy /TC /c /GX +# ADD BASE MTL /nologo /win32 +# ADD MTL /nologo /win32 +# ADD BASE RSC /l 1033 +# ADD RSC /l 1033 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /out:"Release_php4\php_xxtea.dll" /incremental:no /libpath:"../../Release_TS" /pdbtype:sept /subsystem:windows /opt:ref /opt:icf /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /out:"Release_php4\php_xxtea.dll" /incremental:no /libpath:"../../Release_TS" /pdbtype:sept /subsystem:windows /opt:ref /opt:icf /implib:"$(OutDir)/php_xxtea.lib" /machine:ix86 + +!ENDIF + +# Begin Target + +# Name "php_xxtea - Win32 Debug_php5" +# Name "php_xxtea - Win32 Release_php5" +# Name "php_xxtea - Win32 Debug_php4" +# Name "php_xxtea - Win32 Release_php4" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;def;odl;idl;hpj;bat;asm" +# Begin Source File + +SOURCE=php_xxtea.c +# End Source File +# Begin Group "lib_xxtea" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=xxtea.c +# End Source File +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;inc" +# Begin Source File + +SOURCE=php_xxtea.h +# End Source File +# Begin Group "lib_xxtea" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=xxtea.h +# End Source File +# End Group +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/Vendor/phpRPC/pecl/xxtea/php_xxtea.h b/Vendor/phpRPC/pecl/xxtea/php_xxtea.h new file mode 100644 index 00000000..080c3805 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/php_xxtea.h @@ -0,0 +1,49 @@ +/*********************************************************************** + + Copyright 2006-2007 Ma Bingyao + + These sources is free software. Redistributions of source code must + retain the above copyright notice. Redistributions in binary form + must reproduce the above copyright notice. You can redistribute it + freely. You can use it with any free or commercial software. + + These sources is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. Without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + You may contact the author by: + e-mail: andot@coolcode.cn + +*************************************************************************/ + +#ifndef PHP_XXTEA_H +#define PHP_XXTEA_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_XXTEA +extern zend_module_entry xxtea_module_entry; +#define phpext_xxtea_ptr &xxtea_module_entry + +#define XXTEA_MODULE_NAME "xxtea" +#define XXTEA_BUILD_DATE __DATE__ " " __TIME__ +#define XXTEA_VERSION "1.0.3" +#define XXTEA_AUTHOR "Ma Bingyao" +#define XXTEA_HOMEPAGE "http://www.coolcode.cn/?p=209" + +ZEND_MINIT_FUNCTION(xxtea); +ZEND_MSHUTDOWN_FUNCTION(xxtea); +ZEND_MINFO_FUNCTION(xxtea); + +/* declaration of functions to be exported */ +ZEND_FUNCTION(xxtea_encrypt); +ZEND_FUNCTION(xxtea_decrypt); +ZEND_FUNCTION(xxtea_info); + +#else /* if HAVE_XXTEA */ +#define phpext_xxtea_ptr NULL +#endif + +#endif /* ifndef PHP_XXTEA_H */ diff --git a/Vendor/phpRPC/pecl/xxtea/php_xxtea.sln b/Vendor/phpRPC/pecl/xxtea/php_xxtea.sln new file mode 100644 index 00000000..5f5a5c2f --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/php_xxtea.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "php_xxtea", "php_xxtea.vcproj", "{71165FA5-1EBC-4021-AA17-0CCBC7CD5204}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_php4|Win32 = Debug_php4|Win32 + Debug_php5|Win32 = Debug_php5|Win32 + Release_php4|Win32 = Release_php4|Win32 + Release_php5|Win32 = Release_php5|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Debug_php4|Win32.ActiveCfg = Debug_php4|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Debug_php4|Win32.Build.0 = Debug_php4|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Debug_php5|Win32.ActiveCfg = Debug_php5|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Debug_php5|Win32.Build.0 = Debug_php5|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Release_php4|Win32.ActiveCfg = Release_php4|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Release_php4|Win32.Build.0 = Release_php4|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Release_php5|Win32.ActiveCfg = Release_php5|Win32 + {71165FA5-1EBC-4021-AA17-0CCBC7CD5204}.Release_php5|Win32.Build.0 = Release_php5|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Vendor/phpRPC/pecl/xxtea/php_xxtea.vcproj b/Vendor/phpRPC/pecl/xxtea/php_xxtea.vcproj new file mode 100644 index 00000000..aedf004d --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/php_xxtea.vcproj @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vendor/phpRPC/pecl/xxtea/test/test.php b/Vendor/phpRPC/pecl/xxtea/test/test.php new file mode 100644 index 00000000..071b1789 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/test/test.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/Vendor/phpRPC/pecl/xxtea/xxtea.c b/Vendor/phpRPC/pecl/xxtea/xxtea.c new file mode 100644 index 00000000..a3d956db --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/xxtea.c @@ -0,0 +1,54 @@ +/*********************************************************************** + + Copyright 2006-2007 Ma Bingyao + + These sources is free software. Redistributions of source code must + retain the above copyright notice. Redistributions in binary form + must reproduce the above copyright notice. You can redistribute it + freely. You can use it with any free or commercial software. + + These sources is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. Without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + You may contact the author by: + e-mail: andot@coolcode.cn + +*************************************************************************/ +#include "xxtea.h" + +void xxtea_long_encrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) { + xxtea_long n = len - 1; + xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = 0, e; + if (n < 1) { + return; + } + while (0 < q--) { + sum += XXTEA_DELTA; + e = sum >> 2 & 3; + for (p = 0; p < n; p++) { + y = v[p + 1]; + z = v[p] += XXTEA_MX; + } + y = v[0]; + z = v[n] += XXTEA_MX; + } +} + +void xxtea_long_decrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) { + xxtea_long n = len - 1; + xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = q * XXTEA_DELTA, e; + if (n < 1) { + return; + } + while (sum != 0) { + e = sum >> 2 & 3; + for (p = n; p > 0; p--) { + z = v[p - 1]; + y = v[p] -= XXTEA_MX; + } + z = v[n]; + y = v[0] -= XXTEA_MX; + sum -= XXTEA_DELTA; + } +} diff --git a/Vendor/phpRPC/pecl/xxtea/xxtea.h b/Vendor/phpRPC/pecl/xxtea/xxtea.h new file mode 100644 index 00000000..bcc20672 --- /dev/null +++ b/Vendor/phpRPC/pecl/xxtea/xxtea.h @@ -0,0 +1,47 @@ +/*********************************************************************** + + Copyright 2006-2007 Ma Bingyao + + These sources is free software. Redistributions of source code must + retain the above copyright notice. Redistributions in binary form + must reproduce the above copyright notice. You can redistribute it + freely. You can use it with any free or commercial software. + + These sources is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. Without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + You may contact the author by: + e-mail: andot@coolcode.cn + +*************************************************************************/ + +#ifndef XXTEA_H +#define XXTEA_H + +#include /* for size_t & NULL declarations */ + +#if defined(_MSC_VER) + +typedef unsigned __int32 xxtea_long; + +#else + +#if defined(__FreeBSD__) && __FreeBSD__ < 5 +/* FreeBSD 4 doesn't have stdint.h file */ +#include +#else +#include +#endif + +typedef uint32_t xxtea_long; + +#endif /* end of if defined(_MSC_VER) */ + +#define XXTEA_MX (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z) +#define XXTEA_DELTA 0x9e3779b9 + +void xxtea_long_encrypt(xxtea_long *v, xxtea_long len, xxtea_long *k); +void xxtea_long_decrypt(xxtea_long *v, xxtea_long len, xxtea_long *k); + +#endif diff --git a/Vendor/phpRPC/phprpc_client.php b/Vendor/phpRPC/phprpc_client.php new file mode 100644 index 00000000..569681b4 --- /dev/null +++ b/Vendor/phpRPC/phprpc_client.php @@ -0,0 +1,583 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* PHPRPC Client for PHP. + * + * Copyright: Ma Bingyao + * Version: 3.0 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + * +/* + * Interfaces + * + * $rpc_client = new PHPRPC_Client(); + * $rpc_client->setProxy(NULL); + * $rpc_client->useService('http://www.phprpc.org/server.php'); + * $rpc_client->setKeyLength(1024); + * $rpc_client->setEncryptMode(3); + * $args = array(1, 2); + * echo $rpc_client->invoke('add', &$args); + * echo "
    "; + * $n = 3; + * $args = array(&$n); + * echo $rpc_client->invoke('inc', &$args, true); + * echo "
    "; + * echo $rpc_client->sub(3, 2); + * echo "
    "; + * // error handle + * $result = $rpc_client->mul(1, 2); // no mul function + * if (is_a($result, "PHPRPC_Error")) { + * echo $result->toString(); + * } + */ + + +$_PHPRPC_COOKIES = array(); +$_PHPRPC_COOKIE = ''; +$_PHPRPC_SID = 0; + +if (defined('KEEP_PHPRPC_COOKIE_IN_SESSION')) { + if (isset($_SESSION['phprpc_cookies']) and isset($_SESSION['phprpc_cookie'])) { + $_PHPRPC_COOKIES = $_SESSION['phprpc_cookies']; + $_PHPRPC_COOKIE = $_SESSION['phprpc_cookie']; + } + function keep_phprpc_cookie_in_session() { + global $_PHPRPC_COOKIES, $_PHPRPC_COOKIE; + $_SESSION['phprpc_cookies'] = $_PHPRPC_COOKIES; + $_SESSION['phprpc_cookie'] = $_PHPRPC_COOKIE; + } + register_shutdown_function('keep_phprpc_cookie_in_session'); +} + +class PHPRPC_Error { + var $Number; + var $Message; + function PHPRPC_Error($errno, $errstr) { + $this->Number = $errno; + $this->Message = $errstr; + } + function toString() { + return $this->Number . ":" . $this->Message; + } + function __toString() { + return $this->toString(); + } + function getNumber() { + return $this->Number; + } + function getMessage() { + return $this->Message; + } +} + +class _PHPRPC_Client { + var $_server; + var $_timeout; + var $_output; + var $_warning; + var $_proxy; + var $_key; + var $_keylen; + var $_encryptMode; + var $_charset; + var $_socket; + var $_clientid; + var $_http_version; + var $_keep_alive; + // Public Methods + function _PHPRPC_Client($serverURL = '') { + global $_PHPRPC_SID; + require_once('compat.php'); + //register_shutdown_function(array(&$this, "_disconnect")); + $this->_proxy = NULL; + $this->_timeout = 30; + $this->_clientid = 'php' . rand(1 << 30, 1 << 31) . time() . $_PHPRPC_SID; + $_PHPRPC_SID++; + $this->_socket = false; + if ($serverURL != '') { + $this->useService($serverURL); + } + } + function useService($serverURL, $username = NULL, $password = NULL) { + $this->_disconnect(); + $this->_http_version = "1.1"; + $this->_keep_alive = true; + $this->_server = array(); + $this->_key = NULL; + $this->_keylen = 128; + $this->_encryptMode = 0; + $this->_charset = 'utf-8'; + $urlparts = parse_url($serverURL); + if (!isset($urlparts['host'])) { + if (isset($_SERVER["HTTP_HOST"])) { + $urlparts['host'] = $_SERVER["HTTP_HOST"]; + } + else if (isset($_SERVER["SERVER_NAME"])) { + $urlparts['host'] = $_SERVER["SERVER_NAME"]; + } + else { + $urlparts['host'] = "localhost"; + } + if (!isset($_SERVER["HTTPS"]) || + $_SERVER["HTTPS"] == "off" || + $_SERVER["HTTPS"] == "") { + $urlparts['scheme'] = "http"; + } + else { + $urlparts['scheme'] = "https"; + } + $urlparts['port'] = $_SERVER["SERVER_PORT"]; + } + + if (!isset($urlparts['port'])) { + if ($urlparts['scheme'] == "https") { + $urlparts['port'] = 443; + } + else { + $urlparts['port'] = 80; + } + } + + if (!isset($urlparts['path'])) { + $urlparts['path'] = "/"; + } + else if (($urlparts['path']{0} != '/') && ($_SERVER["PHP_SELF"]{0} == '/')) { + $urlparts['path'] = substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], '/') + 1) . $urlparts['path']; + } + + if (isset($urlparts['query'])) { + $urlparts['path'] .= '?' . $urlparts['query']; + } + + if (!isset($urlparts['user']) || !is_null($username)) { + $urlparts['user'] = $username; + } + + if (!isset($urlparts['pass']) || !is_null($password)) { + $urlparts['pass'] = $password; + } + + $this->_server['scheme'] = $urlparts['scheme']; + $this->_server['host'] = $urlparts['host']; + $this->_server['port'] = $urlparts['port']; + $this->_server['path'] = $urlparts['path']; + $this->_server['user'] = $urlparts['user']; + $this->_server['pass'] = $urlparts['pass']; + } + function setProxy($host, $port = NULL, $username = NULL, $password = NULL) { + if (is_null($host)) { + $this->_proxy = NULL; + } + else { + if (is_null($port)) { + $urlparts = parse_url($host); + if (isset($urlparts['host'])) { + $host = $urlparts['host']; + } + if (isset($urlparts['port'])) { + $port = $urlparts['port']; + } + else { + $port = 80; + } + if (isset($urlparts['user']) && is_null($username)) { + $username = $urlparts['user']; + } + if (isset($urlparts['pass']) && is_null($password)) { + $password = $urlparts['pass']; + } + } + $this->_proxy = array(); + $this->_proxy['host'] = $host; + $this->_proxy['port'] = $port; + $this->_proxy['user'] = $username; + $this->_proxy['pass'] = $password; + } + } + function setKeyLength($keylen) { + if (!is_null($this->_key)) { + return false; + } + else { + $this->_keylen = $keylen; + return true; + } + } + function getKeyLength() { + return $this->_keylen; + } + function setEncryptMode($encryptMode) { + if (($encryptMode >= 0) && ($encryptMode <= 3)) { + $this->_encryptMode = (int)($encryptMode); + return true; + } + else { + $this->_encryptMode = 0; + return false; + } + } + function getEncryptMode() { + return $this->_encryptMode; + } + function setCharset($charset) { + $this->_charset = $charset; + } + function getCharset() { + return $this->_charset; + } + function setTimeout($timeout) { + $this->_timeout = $timeout; + } + function getTimeout() { + return $this->_timeout; + } + function invoke($funcname, &$args, $byRef = false) { + $result = $this->_key_exchange(); + if (is_a($result, 'PHPRPC_Error')) { + return $result; + } + $request = "phprpc_func=$funcname"; + if (count($args) > 0) { + $request .= "&phprpc_args=" . base64_encode($this->_encrypt(serialize_fix($args), 1)); + } + $request .= "&phprpc_encrypt={$this->_encryptMode}"; + if (!$byRef) { + $request .= "&phprpc_ref=false"; + } + $request = str_replace('+', '%2B', $request); + $result = $this->_post($request); + if (is_a($result, 'PHPRPC_Error')) { + return $result; + } + $phprpc_errno = 0; + $phprpc_errstr = NULL; + if (isset($result['phprpc_errno'])) { + $phprpc_errno = intval($result['phprpc_errno']); + } + if (isset($result['phprpc_errstr'])) { + $phprpc_errstr = base64_decode($result['phprpc_errstr']); + } + $this->_warning = new PHPRPC_Error($phprpc_errno, $phprpc_errstr); + if (array_key_exists('phprpc_output', $result)) { + $this->_output = base64_decode($result['phprpc_output']); + if ($this->_server['version'] >= 3) { + $this->_output = $this->_decrypt($this->_output, 3); + } + } + else { + $this->_output = ''; + } + if (array_key_exists('phprpc_result', $result)) { + if (array_key_exists('phprpc_args', $result)) { + $arguments = unserialize($this->_decrypt(base64_decode($result['phprpc_args']), 1)); + for ($i = 0; $i < count($arguments); $i++) { + $args[$i] = $arguments[$i]; + } + } + $result = unserialize($this->_decrypt(base64_decode($result['phprpc_result']), 2)); + } + else { + $result = $this->_warning; + } + return $result; + } + + function getOutput() { + return $this->_output; + } + + function getWarning() { + return $this->_warning; + } + + function _connect() { + if (is_null($this->_proxy)) { + $host = (($this->_server['scheme'] == "https") ? "ssl://" : "") . $this->_server['host']; + $this->_socket = @pfsockopen($host, $this->_server['port'], $errno, $errstr, $this->_timeout); + } + else { + $host = (($this->_server['scheme'] == "https") ? "ssl://" : "") . $this->_proxy['host']; + $this->_socket = @pfsockopen($host, $this->_proxy['port'], $errno, $errstr, $this->_timeout); + } + if ($this->_socket === false) { + return new PHPRPC_Error($errno, $errstr); + } + stream_set_write_buffer($this->_socket, 0); + socket_set_timeout($this->_socket, $this->_timeout); + return true; + } + + function _disconnect() { + if ($this->_socket !== false) { + fclose($this->_socket); + $this->_socket = false; + } + } + + function _socket_read($size) { + $content = ""; + while (!feof($this->_socket) && ($size > 0)) { + $str = fread($this->_socket, $size); + $content .= $str; + $size -= strlen($str); + } + return $content; + } + function _post($request_body) { + global $_PHPRPC_COOKIE; + $request_body = 'phprpc_id=' . $this->_clientid . '&' . $request_body; + if ($this->_socket === false) { + $error = $this->_connect(); + if (is_a($error, 'PHPRPC_Error')) { + return $error; + } + } + if (is_null($this->_proxy)) { + $url = $this->_server['path']; + $connection = "Connection: " . ($this->_keep_alive ? 'Keep-Alive' : 'Close') . "\r\n" . + "Cache-Control: no-cache\r\n"; + } + else { + $url = "{$this->_server['scheme']}://{$this->_server['host']}:{$this->_server['port']}{$this->_server['path']}"; + $connection = "Proxy-Connection: " . ($this->_keep_alive ? 'keep-alive' : 'close') . "\r\n"; + if (!is_null($this->_proxy['user'])) { + $connection .= "Proxy-Authorization: Basic " . base64_encode($this->_proxy['user'] . ":" . $this->_proxy['pass']) . "\r\n"; + } + } + $auth = ''; + if (!is_null($this->_server['user'])) { + $auth = "Authorization: Basic " . base64_encode($this->_server['user'] . ":" . $this->_server['pass']) . "\r\n"; + } + $cookie = ''; + if ($_PHPRPC_COOKIE) { + $cookie = "Cookie: " . $_PHPRPC_COOKIE . "\r\n"; + } + $content_len = strlen($request_body); + $request = + "POST $url HTTP/{$this->_http_version}\r\n" . + "Host: {$this->_server['host']}:{$this->_server['port']}\r\n" . + "User-Agent: PHPRPC Client 3.0 for PHP\r\n" . + $auth . + $connection . + $cookie . + "Accept: */*\r\n" . + "Accept-Encoding: gzip,deflate\r\n" . + "Content-Type: application/x-www-form-urlencoded; charset={$this->_charset}\r\n" . + "Content-Length: {$content_len}\r\n" . + "\r\n" . + $request_body; + fputs($this->_socket, $request, strlen($request)); + while (!feof($this->_socket)) { + $line = fgets($this->_socket); + if (preg_match('/HTTP\/(\d\.\d)\s+(\d+)([^(\r|\n)]*)(\r\n|$)/i', $line, $match)) { + $this->_http_version = $match[1]; + $status = (int)$match[2]; + $status_message = trim($match[3]); + if ($status != 100 && $status != 200) { + $this->_disconnect(); + return new PHPRPC_Error($status, $status_message); + } + } + else { + $this->_disconnect(); + return new PHPRPC_Error(E_ERROR, "Illegal HTTP server."); + } + $header = array(); + while (!feof($this->_socket) && (($line = fgets($this->_socket)) != "\r\n")) { + $line = explode(':', $line, 2); + $header[strtolower($line[0])][] =trim($line[1]); + } + if ($status == 100) continue; + $response_header = $this->_parseHeader($header); + if (is_a($response_header, 'PHPRPC_Error')) { + $this->_disconnect(); + return $response_header; + } + break; + } + $response_body = ''; + if (isset($response_header['transfer_encoding']) && (strtolower($response_header['transfer_encoding']) == 'chunked')) { + $s = fgets($this->_socket); + if ($s == "") { + $this->_disconnect(); + return array(); + } + $chunk_size = (int)hexdec($s); + while ($chunk_size > 0) { + $response_body .= $this->_socket_read($chunk_size); + if (fgets($this->_socket) != "\r\n") { + $this->_disconnect(); + return new PHPRPC_Error(1, "Response is incorrect."); + } + $chunk_size = (int)hexdec(fgets($this->_socket)); + } + fgets($this->_socket); + } + elseif (isset($response_header['content_length']) && !is_null($response_header['content_length'])) { + $response_body = $this->_socket_read($response_header['content_length']); + } + else { + while (!feof($this->_socket)) { + $response_body .= fread($this->_socket, 4096); + } + $this->_keep_alive = false; + $this->_disconnect(); + } + if (isset($response_header['content_encoding']) && (strtolower($response_header['content_encoding']) == 'gzip')) { + $response_body = gzdecode($response_body); + } + if (!$this->_keep_alive) $this->_disconnect(); + if ($this->_keep_alive && strtolower($response_header['connection']) == 'close') { + $this->_keep_alive = false; + $this->_disconnect(); + } + return $this->_parseBody($response_body); + } + function _parseHeader($header) { + global $_PHPRPC_COOKIE, $_PHPRPC_COOKIES; + if (preg_match('/PHPRPC Server\/([^,]*)(,|$)/i', implode(',', $header['x-powered-by']), $match)) { + $this->_server['version'] = (float)$match[1]; + } + else { + return new PHPRPC_Error(E_ERROR, "Illegal PHPRPC server."); + } + if (preg_match('/text\/plain\; charset\=([^,;]*)([,;]|$)/i', $header['content-type'][0], $match)) { + $this->_charset = $match[1]; + } + if (isset($header['set-cookie'])) { + foreach ($header['set-cookie'] as $cookie) { + foreach (preg_split('/[;,]\s?/', $cookie) as $c) { + list($name, $value) = explode('=', $c, 2); + if (!in_array($name, array('domain', 'expires', 'path', 'secure'))) { + $_PHPRPC_COOKIES[$name] = $value; + } + } + } + $cookies = array(); + foreach ($_PHPRPC_COOKIES as $name => $value) { + $cookies[] = "$name=$value"; + } + $_PHPRPC_COOKIE = join('; ', $cookies); + } + if (isset($header['content-length'])) { + $content_length = (int)$header['content-length'][0]; + } + else { + $content_length = NULL; + } + $transfer_encoding = isset($header['transfer-encoding']) ? $header['transfer-encoding'][0] : ''; + $content_encoding = isset($header['content-encoding']) ? $header['content-encoding'][0] : ''; + $connection = isset($header['connection']) ? $header['connection'][0] : 'close'; + return array('transfer_encoding' => $transfer_encoding, + 'content_encoding' => $content_encoding, + 'content_length' => $content_length, + 'connection' => $connection); + } + function _parseBody($body) { + $body = explode(";\r\n", $body); + $result = array(); + $n = count($body); + for ($i = 0; $i < $n; $i++) { + $p = strpos($body[$i], '='); + if ($p !== false) { + $l = substr($body[$i], 0, $p); + $r = substr($body[$i], $p + 1); + $result[$l] = trim($r, '"'); + } + } + return $result; + } + function _key_exchange() { + if (!is_null($this->_key) || ($this->_encryptMode == 0)) return true; + $request = "phprpc_encrypt=true&phprpc_keylen={$this->_keylen}"; + $result = $this->_post($request); + if (is_a($result, 'PHPRPC_Error')) { + return $result; + } + if (array_key_exists('phprpc_keylen', $result)) { + $this->_keylen = (int)$result['phprpc_keylen']; + } + else { + $this->_keylen = 128; + } + if (array_key_exists('phprpc_encrypt', $result)) { + $encrypt = unserialize(base64_decode($result['phprpc_encrypt'])); + require_once('bigint.php'); + require_once('xxtea.php'); + $x = bigint_random($this->_keylen - 1, true); + $key = bigint_powmod(bigint_dec2num($encrypt['y']), $x, bigint_dec2num($encrypt['p'])); + if ($this->_keylen == 128) { + $key = bigint_num2str($key); + } + else { + $key = pack('H*', md5(bigint_num2dec($key))); + } + $this->_key = str_pad($key, 16, "\0", STR_PAD_LEFT); + $encrypt = bigint_num2dec(bigint_powmod(bigint_dec2num($encrypt['g']), $x, bigint_dec2num($encrypt['p']))); + $request = "phprpc_encrypt=$encrypt"; + $result = $this->_post($request); + if (is_a($result, 'PHPRPC_Error')) { + return $result; + } + } + else { + $this->_key = NULL; + $this->_encryptMode = 0; + } + return true; + } + function _encrypt($str, $level) { + if (!is_null($this->_key) && ($this->_encryptMode >= $level)) { + $str = xxtea_encrypt($str, $this->_key); + } + return $str; + } + function _decrypt($str, $level) { + if (!is_null($this->_key) && ($this->_encryptMode >= $level)) { + $str = xxtea_decrypt($str, $this->_key); + } + return $str; + } +} + +if (function_exists("overload") && version_compare(phpversion(), "5", "<")) { + eval(' + class PHPRPC_Client extends _PHPRPC_Client { + function __call($function, $arguments, &$return) { + $return = $this->invoke($function, $arguments); + return true; + } + } + overload("phprpc_client"); + '); +} +else { + class PHPRPC_Client extends _PHPRPC_Client { + function __call($function, $arguments) { + return $this->invoke($function, $arguments); + } + } +} +?> \ No newline at end of file diff --git a/Vendor/phpRPC/phprpc_date.php b/Vendor/phpRPC/phprpc_date.php new file mode 100644 index 00000000..cb9a2809 --- /dev/null +++ b/Vendor/phpRPC/phprpc_date.php @@ -0,0 +1,522 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* PHPRPC_Date Class for PHP. + * + * Copyright: Ma Bingyao + * Version: 1.2 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + */ + +class PHPRPC_Date { + +// public fields + + var $year = 1; + var $month = 1; + var $day = 1; + var $hour = 0; + var $minute = 0; + var $second = 0; + var $millisecond = 0; + +// constructor + + function PHPRPC_Date() { + $num = func_num_args(); + $time = false; + if ($num == 0) { + $time = getdate(); + } + if ($num == 1) { + $arg = func_get_arg(0); + if (is_int($arg)) { + $time = getdate($arg); + } + elseif (is_string($arg)) { + $time = getdate(strtotime($arg)); + } + } + if (is_array($time)) { + $this->year = $time['year']; + $this->month = $time['mon']; + $this->day = $time['mday']; + $this->hour = $time['hours']; + $this->minute = $time['minutes']; + $this->second = $time['seconds']; + } + } + +// public instance methods + + function addMilliseconds($milliseconds) { + if (!is_int($milliseconds)) return false; + if ($milliseconds == 0) return true; + $millisecond = $this->millisecond + $milliseconds; + $milliseconds = $millisecond % 1000; + if ($milliseconds < 0) { + $milliseconds += 1000; + } + $seconds = (int)(($millisecond - $milliseconds) / 1000); + $millisecond = (int)$milliseconds; + if ($this->addSeconds($seconds)) { + $this->millisecond = (int)$milliseconds; + return true; + } + else { + return false; + } + } + + function addSeconds($seconds) { + if (!is_int($seconds)) return false; + if ($seconds == 0) return true; + $second = $this->second + $seconds; + $seconds = $second % 60; + if ($seconds < 0) { + $seconds += 60; + } + $minutes = (int)(($second - $seconds) / 60); + if ($this->addMinutes($minutes)) { + $this->second = (int)$seconds; + return true; + } + else { + return false; + } + } + + function addMinutes($minutes) { + if (!is_int($minutes)) return false; + if ($minutes == 0) return true; + $minute = $this->minute + $minutes; + $minutes = $minute % 60; + if ($minutes < 0) { + $minutes += 60; + } + $hours = (int)(($minute - $minutes) / 60); + if ($this->addHours($hours)) { + $this->minute = (int)$minutes; + return true; + } + else { + return false; + } + } + + function addHours($hours) { + if (!is_int($hours)) return false; + if ($hours == 0) return true; + $hour = $this->hour + $hours; + $hours = $hour % 24; + if ($hours < 0) { + $hours += 24; + } + $days = (int)(($hour - $hours) / 24); + if ($this->addDays($days)) { + $this->hour = (int)$hours; + return true; + } + else { + return false; + } + } + + function addDays($days) { + if (!is_int($days)) return false; + $year = $this->year; + if ($days == 0) return true; + if ($days >= 146097 || $days <= -146097) { + $remainder = $days % 146097; + if ($remainder < 0) { + $remainder += 146097; + } + $years = 400 * (int)(($days - $remainder) / 146097); + $year += $years; + if ($year < 1 || $year > 9999) return false; + $days = $remainder; + } + if ($days >= 36524 || $days <= -36524) { + $remainder = $days % 36524; + if ($remainder < 0) { + $remainder += 36524; + } + $years = 100 * (int)(($days - $remainder) / 36524); + $year += $years; + if ($year < 1 || $year > 9999) return false; + $days = $remainder; + } + if ($days >= 1461 || $days <= -1461) { + $remainder = $days % 1461; + if ($remainder < 0) { + $remainder += 1461; + } + $years = 4 * (int)(($days - $remainder) / 1461); + $year += $years; + if ($year < 1 || $year > 9999) return false; + $days = $remainder; + } + $month = $this->month; + while ($days >= 365) { + if ($year >= 9999) return false; + if ($month <= 2) { + if ((($year % 4) == 0) ? (($year % 100) == 0) ? (($year % 400) == 0) : true : false) { + $days -= 366; + } + else { + $days -= 365; + } + $year++; + } + else { + $year++; + if ((($year % 4) == 0) ? (($year % 100) == 0) ? (($year % 400) == 0) : true : false) { + $days -= 366; + } + else { + $days -= 365; + } + } + } + while ($days < 0) { + if ($year <= 1) return false; + if ($month <= 2) { + $year--; + if ((($year % 4) == 0) ? (($year % 100) == 0) ? (($year % 400) == 0) : true : false) { + $days += 366; + } + else { + $days += 365; + } + } + else { + if ((($year % 4) == 0) ? (($year % 100) == 0) ? (($year % 400) == 0) : true : false) { + $days += 366; + } + else { + $days += 365; + } + $year--; + } + } + $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); + $day = $this->day; + while ($day + $days > $daysInMonth) { + $days -= $daysInMonth - $day + 1; + $month++; + if ($month > 12) { + if ($year >= 9999) return false; + $year++; + $month = 1; + } + $day = 1; + $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); + } + $day += $days; + $this->year = $year; + $this->month = $month; + $this->day = $day; + return true; + } + + function addMonths($months) { + if (!is_int($months)) return false; + if ($months == 0) return true; + $month = $this->month + $months; + $months = ($month - 1) % 12 + 1; + if ($months < 1) { + $months += 12; + } + $years = (int)(($month - $months) / 12); + if ($this->addYears($years)) { + $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $months, $this->year); + if ($this->day > $daysInMonth) { + $months++; + $this->day -= $daysInMonth; + } + $this->month = (int)$months; + return true; + } + else { + return false; + } + } + + function addYears($years) { + if (!is_int($years)) return false; + if ($years == 0) return true; + $year = $this->year + $years; + if ($year < 1 || $year > 9999) return false; + $this->year = $year; + return true; + } + + function after($when) { + if (!is_a($when, 'PHPRPC_Date')) { + $when = PHPRPC_Date::parse($when); + } + if ($this->year < $when->year) return false; + if ($this->year > $when->year) return true; + if ($this->month < $when->month) return false; + if ($this->month > $when->month) return true; + if ($this->day < $when->day) return false; + if ($this->day > $when->day) return true; + if ($this->hour < $when->hour) return false; + if ($this->hour > $when->hour) return true; + if ($this->minute < $when->minute) return false; + if ($this->minute > $when->minute) return true; + if ($this->second < $when->second) return false; + if ($this->second > $when->second) return true; + if ($this->millisecond < $when->millisecond) return false; + if ($this->millisecond > $when->millisecond) return true; + return false; + } + + function before($when) { + if (!is_a($when, 'PHPRPC_Date')) { + $when = new PHPRPC_Date($when); + } + if ($this->year < $when->year) return true; + if ($this->year > $when->year) return false; + if ($this->month < $when->month) return true; + if ($this->month > $when->month) return false; + if ($this->day < $when->day) return true; + if ($this->day > $when->day) return false; + if ($this->hour < $when->hour) return true; + if ($this->hour > $when->hour) return false; + if ($this->minute < $when->minute) return true; + if ($this->minute > $when->minute) return false; + if ($this->second < $when->second) return true; + if ($this->second > $when->second) return false; + if ($this->millisecond < $when->millisecond) return true; + if ($this->millisecond > $when->millisecond) return false; + return false; + } + + function equals($when) { + if (!is_a($when, 'PHPRPC_Date')) { + $when = new PHPRPC_Date($when); + } + return (($this->year == $when->year) && + ($this->month == $when->month) && + ($this->day == $when->day) && + ($this->hour == $when->hour) && + ($this->minute == $when->minute) && + ($this->second == $when->second) && + ($this->millisecond == $when->millisecond)); + } + + function set() { + $num = func_num_args(); + $args = func_get_args(); + if ($num >= 3) { + if (!PHPRPC_Date::isValidDate($args[0], $args[1], $args[2])) { + return false; + } + $this->year = (int)$args[0]; + $this->month = (int)$args[1]; + $this->day = (int)$args[2]; + if ($num == 3) { + return true; + } + } + if ($num >= 6) { + if (!PHPRPC_Date::isValidTime($args[3], $args[4], $args[5])) { + return false; + } + $this->hour = (int)$args[3]; + $this->minute = (int)$args[4]; + $this->second = (int)$args[5]; + if ($num == 6) { + return true; + } + } + if (($num == 7) && ($args[6] >= 0 && $args[6] <= 999)) { + $this->millisecond = (int)$args[6]; + return true; + } + return false; + } + + function time() { + return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); + } + + function toString() { + return sprintf('%04d-%02d-%02d %02d:%02d:%02d.%03d', + $this->year, $this->month, $this->day, + $this->hour, $this->minute, $this->second, + $this->millisecond); + } + +// magic method for PHP 5 + + function __toString() { + return $this->toString(); + } + +// public instance & static methods + + function dayOfWeek() { + $num = func_num_args(); + if ($num == 3) { + $args = func_get_args(); + $y = $args[0]; + $m = $args[1]; + $d = $args[2]; + } + else { + $y = $this->year; + $m = $this->month; + $d = $this->day; + } + $d += $m < 3 ? $y-- : $y - 2; + return ((int)(23 * $m / 9) + $d + 4 + (int)($y / 4) - (int)($y / 100) + (int)($y / 400)) % 7; + } + + function dayOfYear() { + static $daysToMonth365 = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365); + static $daysToMonth366 = array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366); + $num = func_num_args(); + if ($num == 3) { + $args = func_get_args(); + $y = $args[0]; + $m = $args[1]; + $d = $args[2]; + } + else { + $y = $this->year; + $m = $this->month; + $d = $this->day; + } + $days = PHPRPC_Date::isLeapYear($y) ? $daysToMonth365 : $daysToMonth366; + return $days[$m - 1] + $d; + } + +// public static methods + + function now() { + $date = new PHPRPC_Date(); + return $date; + } + + function today() { + $date = PHPRPC_Date::now(); + $date->hour = 0; + $date->minute = 0; + $date->second = 0; + return $date; + } + + function parse($dt) { + if (is_a($dt, 'PHPRPC_Date')) { + return $dt; + } + if (is_int($dt)) { + return new PHPRPC_Date($dt); + } + $shortFormat = '(\d|\d{2}|\d{3}|\d{4})-([1-9]|0[1-9]|1[012])-([1-9]|0[1-9]|[12]\d|3[01])'; + if (preg_match("/^$shortFormat$/", $dt, $match)) { + $year = intval($match[1]); + $month = intval($match[2]); + $day = intval($match[3]); + if (PHPRPC_Date::isValidDate($year, $month, $day)) { + $date = new PHPRPC_Date(false); + $date->year = $year; + $date->month = $month; + $date->day = $day; + return $date; + } + else { + return false; + } + } + $longFormat = $shortFormat . ' (\d|0\d|1\d|2[0-3]):(\d|[0-5]\d):(\d|[0-5]\d)'; + if (preg_match("/^$longFormat$/", $dt, $match)) { + $year = intval($match[1]); + $month = intval($match[2]); + $day = intval($match[3]); + if (PHPRPC_Date::isValidDate($year, $month, $day)) { + $date = new PHPRPC_Date(false); + $date->year = $year; + $date->month = $month; + $date->day = $day; + $date->hour = intval($match[4]); + $date->minute = intval($match[5]); + $date->second = intval($match[6]); + return $date; + } + else { + return false; + } + } + $fullFormat = $longFormat . '\.(\d|\d{2}|\d{3})'; + if (preg_match("/^$fullFormat$/", $dt, $match)) { + $year = intval($match[1]); + $month = intval($match[2]); + $day = intval($match[3]); + if (PHPRPC_Date::isValidDate($year, $month, $day)) { + $date = new PHPRPC_Date(false); + $date->year = $year; + $date->month = $month; + $date->day = $day; + $date->hour = intval($match[4]); + $date->minute = intval($match[5]); + $date->second = intval($match[6]); + $date->millisecond = intval($match[7]); + return $date; + } + else { + return false; + } + } + return false; + } + + function isLeapYear($year) { + return (($year % 4) == 0) ? (($year % 100) == 0) ? (($year % 400) == 0) : true : false; + } + + function daysInMonth($year, $month) { + if (($month < 1) || ($month > 12)) { + return false; + } + return cal_days_in_month(CAL_GREGORIAN, $month, $year); + } + + function isValidDate($year, $month, $day) { + if (($year >= 1) && ($year <= 9999)) { + return checkdate($month, $day, $year); + } + return false; + } + + function isValidTime($hour, $minute, $second) { + return !(($hour < 0) || ($hour > 23) || + ($minute < 0) || ($minute > 59) || + ($second < 0) || ($second > 59)); + } +} +?> \ No newline at end of file diff --git a/Vendor/phpRPC/phprpc_server.php b/Vendor/phpRPC/phprpc_server.php new file mode 100644 index 00000000..22eebf53 --- /dev/null +++ b/Vendor/phpRPC/phprpc_server.php @@ -0,0 +1,496 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* PHPRPC Server for PHP. + * + * Copyright: Ma Bingyao + * Version: 3.0 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + * +/* + * Interfaces + * + * function add($a, $b) { + * return $a + $b; + * } + * function sub($a, $b) { + * return $a - $b; + * } + * function inc(&$n) { + * return $n++; + * } + * include('phprpc_server.php'); + * $server = new PHPRPC_Server(); + * $server->add(array('add', 'sub')); + * $server->add('inc'); + * $server->setCharset('UTF-8'); + * $server->setDebugMode(true); + * $server->start(); + * + */ + +class PHPRPC_Server { + var $callback; + var $charset; + var $encode; + var $ref; + var $encrypt; + var $enableGZIP; + var $debug; + var $keylen; + var $key; + var $errno; + var $errstr; + var $functions; + var $cid; + var $buffer; + // Private Methods + function addJsSlashes($str, $flag) { + if ($flag) { + $str = addcslashes($str, "\0..\006\010..\012\014..\037\042\047\134\177..\377"); + } + else { + $str = addcslashes($str, "\0..\006\010..\012\014..\037\042\047\134\177"); + } + return str_replace(array(chr(7), chr(11)), array('\007', '\013'), $str); + } + function encodeString($str, $flag = true) { + if ($this->encode) { + return base64_encode($str); + } + else { + return $this->addJsSlashes($str, $flag); + } + } + function encryptString($str, $level) { + if ($this->encrypt >= $level) { + $str = xxtea_encrypt($str, $this->key); + } + return $str; + } + function decryptString($str, $level) { + if ($this->encrypt >= $level) { + $str = xxtea_decrypt($str, $this->key); + } + return $str; + } + function sendHeader() { + header("HTTP/1.1 200 OK"); + header("Content-Type: text/plain; charset={$this->charset}"); + header("X-Powered-By: PHPRPC Server/3.0"); + header('P3P: CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"'); + header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); + } + function getRequestURL() { + if (!isset($_SERVER['HTTPS']) || + $_SERVER['HTTPS'] == 'off' || + $_SERVER['HTTPS'] == '') { + $scheme = 'http'; + } + else { + $scheme = 'https'; + } + $host = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + $path = $_SERVER['SCRIPT_NAME']; + return $scheme . '://' . $host . (($port == 80) ? '' : ':' . $port) . $path; + } + function sendURL() { + if (SID != "") { + $url = $this->getRequestURL(); + if (count($_GET) > 0) { + $url .= '?' . strip_tags(SID); + foreach ($_GET as $key => $value) { + if (strpos(strtolower($key), 'phprpc_') !== 0) { + $url .= '&' . $key . '=' . urlencode($value); + } + } + } + $this->buffer .= "phprpc_url=\"" . $this->encodeString($url) . "\";\r\n"; + } + } + function gzip($buffer) { + $len = strlen($buffer); + if ($this->enableGZIP && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip,deflate')) { + $gzbuffer = gzencode($buffer); + $gzlen = strlen($gzbuffer); + if ($len > $gzlen) { + header("Content-Length: $gzlen"); + header("Content-Encoding: gzip"); + return $gzbuffer; + } + } + header("Content-Length: $len"); + return $buffer; + } + function sendCallback() { + $this->buffer .= $this->callback; + echo $this->gzip($this->buffer); + ob_end_flush(); + restore_error_handler(); + if (function_exists('restore_exception_handler')) { + restore_exception_handler(); + } + exit(); + } + function sendFunctions() { + $this->buffer .= "phprpc_functions=\"" . $this->encodeString(serialize_fix(array_keys($this->functions))) . "\";\r\n"; + $this->sendCallback(); + } + function sendOutput($output) { + if ($this->encrypt >= 3) { + $this->buffer .= "phprpc_output=\"" . $this->encodeString(xxtea_encrypt($output, $this->key)) . "\";\r\n"; + } + else { + $this->buffer .= "phprpc_output=\"" . $this->encodeString($output, false) . "\";\r\n"; + } + } + function sendError($output = NULL) { + if (is_null($output)) { + $output = ob_get_clean(); + } + $this->buffer .= "phprpc_errno=\"{$this->errno}\";\r\n"; + $this->buffer .= "phprpc_errstr=\"" . $this->encodeString($this->errstr, false) . "\";\r\n"; + $this->sendOutput($output); + $this->sendCallback(); + } + function fatalErrorHandler($buffer) { + if (preg_match('/(.*?) error<\/b>:(.*?)
    debug) { + $errstr = preg_replace('/<.*?>/', '', $match[2]); + } + else { + $errstr = preg_replace('/ in .*<\/b>$/', '', $match[2]); + } + + $buffer = "phprpc_errno=\"{$errno}\";\r\n" . + "phprpc_errstr=\"" . $this->encodeString(trim($errstr), false) . "\";\r\n" . + "phprpc_output=\"\";\r\n" . + $this->callback; + $buffer = $this->gzip($buffer); + } + return $buffer; + } + function errorHandler($errno, $errstr, $errfile, $errline) { + if ($this->debug) { + $errstr .= " in $errfile on line $errline"; + } + if (($errno == E_ERROR) or ($errno == E_CORE_ERROR) or + ($errno == E_COMPILE_ERROR) or ($errno == E_USER_ERROR)) { + $this->errno = $errno; + $this->errstr = $errstr; + $this->sendError(); + } + else { + if (($errno == E_NOTICE) or ($errno == E_USER_NOTICE)) { + if ($this->errno == 0) { + $this->errno = $errno; + $this->errstr = $errstr; + } + } + else { + if (($this->errno == 0) or + ($this->errno == E_NOTICE) or + ($this->errno == E_USER_NOTICE)) { + $this->errno = $errno; + $this->errstr = $errstr; + } + } + } + return true; + } + function exceptionHandler($exception) { + $this->errno = $exception->getCode(); + $this->errstr = $exception->getMessage(); + if ($this->debug) { + $this->errstr .= "\nfile: " . $exception->getFile() . + "\nline: " . $exception->getLine() . + "\ntrace: " . $exception->getTraceAsString(); + } + $this->sendError(); + } + function initErrorHandler() { + $this->errno = 0; + $this->errstr = ""; + set_error_handler(array(&$this, 'errorHandler')); + if (function_exists('set_exception_handler')) { + set_exception_handler(array(&$this, 'exceptionHandler')); + } + } + function call($function, &$args) { + if ($this->ref) { + $arguments = array(); + for ($i = 0; $i < count($args); $i++) { + $arguments[$i] = &$args[$i]; + } + } + else { + $arguments = $args; + } + return call_user_func_array($function, $arguments); + } + function getRequest($name) { + $result = $_REQUEST[$name]; + if (get_magic_quotes_gpc()) { + $result = stripslashes($result); + } + return $result; + } + function getBooleanRequest($name) { + $var = true; + if (isset($_REQUEST[$name])) { + $var = strtolower($this->getRequest($name)); + if ($var == "false") { + $var = false; + } + } + return $var; + } + function initEncode() { + $this->encode = $this->getBooleanRequest('phprpc_encode'); + } + function initRef() { + $this->ref = $this->getBooleanRequest('phprpc_ref'); + } + function initCallback() { + if (isset($_REQUEST['phprpc_callback'])) { + $this->callback = base64_decode($this->getRequest('phprpc_callback')); + } + else { + $this->callback = ""; + } + } + function initKeylen() { + if (isset($_REQUEST['phprpc_keylen'])) { + $this->keylen = (int)$this->getRequest('phprpc_keylen'); + } + else if (isset($_SESSION[$this->cid])) { + $session = unserialize(base64_decode($_SESSION[$this->cid])); + if (isset($session['keylen'])) { + $this->keylen = $session['keylen']; + } + else { + $this->keylen = 128; + } + } + else { + $this->keylen = 128; + } + } + function initClientID() { + $this->cid = 0; + if (isset($_REQUEST['phprpc_id'])) { + $this->cid = $this->getRequest('phprpc_id'); + } + $this->cid = "phprpc_" . $this->cid; + } + function initEncrypt() { + $this->encrypt = false; + if (isset($_REQUEST['phprpc_encrypt'])) { + $this->encrypt = $this->getRequest('phprpc_encrypt'); + if ($this->encrypt === "true") $this->encrypt = true; + if ($this->encrypt === "false") $this->encrypt = false; + } + } + function initKey() { + if ($this->encrypt == 0) { + return; + } + else if (isset($_SESSION[$this->cid])) { + $session = unserialize(base64_decode($_SESSION[$this->cid])); + if (isset($session['key'])) { + $this->key = $session['key']; + require_once('xxtea.php'); + return; + } + } + $this->errno = E_ERROR; + $this->errstr = "Can't find the key for decryption."; + $this->encrypt = 0; + $this->sendError(); + } + function getArguments() { + if (isset($_REQUEST['phprpc_args'])) { + $arguments = unserialize($this->decryptString(base64_decode($this->getRequest('phprpc_args')), 1)); + ksort($arguments); + } + else { + $arguments = array(); + } + return $arguments; + } + function callFunction() { + $this->initKey(); + $function = strtolower($this->getRequest('phprpc_func')); + if (array_key_exists($function, $this->functions)) { + $function = $this->functions[$function]; + $arguments = $this->getArguments(); + $result = $this->encodeString($this->encryptString(serialize_fix($this->call($function, $arguments)), 2)); + $output = ob_get_clean(); + $this->buffer .= "phprpc_result=\"$result\";\r\n"; + if ($this->ref) { + $arguments = $this->encodeString($this->encryptString(serialize_fix($arguments), 1)); + $this->buffer .= "phprpc_args=\"$arguments\";\r\n"; + } + } + else { + $this->errno = E_ERROR; + $this->errstr = "Can't find this function $function()."; + $output = ob_get_clean(); + } + $this->sendError($output); + } + function keyExchange() { + require_once('bigint.php'); + $this->initKeylen(); + if (isset($_SESSION[$this->cid])) { + $session = unserialize(base64_decode($_SESSION[$this->cid])); + } + else { + $session = array(); + } + if ($this->encrypt === true) { + require_once('dhparams.php'); + $DHParams = new DHParams($this->keylen); + $this->keylen = $DHParams->getL(); + $encrypt = $DHParams->getDHParams(); + $x = bigint_random($this->keylen - 1, true); + $session['x'] = bigint_num2dec($x); + $session['p'] = $encrypt['p']; + $session['keylen'] = $this->keylen; + $encrypt['y'] = bigint_num2dec(bigint_powmod(bigint_dec2num($encrypt['g']), $x, bigint_dec2num($encrypt['p']))); + $this->buffer .= "phprpc_encrypt=\"" . $this->encodeString(serialize_fix($encrypt)) . "\";\r\n"; + if ($this->keylen != 128) { + $this->buffer .= "phprpc_keylen=\"{$this->keylen}\";\r\n"; + } + $this->sendURL(); + } + else { + $y = bigint_dec2num($this->encrypt); + $x = bigint_dec2num($session['x']); + $p = bigint_dec2num($session['p']); + $key = bigint_powmod($y, $x, $p); + if ($this->keylen == 128) { + $key = bigint_num2str($key); + } + else { + $key = pack('H*', md5(bigint_num2dec($key))); + } + $session['key'] = str_pad($key, 16, "\0", STR_PAD_LEFT); + } + $_SESSION[$this->cid] = base64_encode(serialize($session)); + $this->sendCallback(); + } + function initSession() { + @ob_start(); + ob_implicit_flush(0); + session_start(); + } + function initOutputBuffer() { + @ob_start(array(&$this, "fatalErrorHandler")); + ob_implicit_flush(0); + $this->buffer = ""; + } + // Public Methods + function PHPRPC_Server() { + require_once('compat.php'); + $this->functions = array(); + $this->charset = 'UTF-8'; + $this->debug = false; + $this->enableGZIP = false; + } + function add($functions, $obj = NULL, $aliases = NULL) { + if (is_null($functions) || (gettype($functions) != gettype($aliases) && !is_null($aliases))) { + return false; + } + if (is_object($functions)) { + $obj = $functions; + $functions = get_class_methods(get_class($obj)); + $aliases = $functions; + } + if (is_null($aliases)) { + $aliases = $functions; + } + if (is_string($functions)) { + if (is_null($obj)) { + $this->functions[strtolower($aliases)] = $functions; + } + else if (is_object($obj)) { + $this->functions[strtolower($aliases)] = array(&$obj, $functions); + } + else if (is_string($obj)) { + $this->functions[strtolower($aliases)] = array($obj, $functions); + } + } + else { + if (count($functions) != count($aliases)) { + return false; + } + foreach ($functions as $key => $function) { + $this->add($function, $obj, $aliases[$key]); + } + } + return true; + } + function setCharset($charset) { + $this->charset = $charset; + } + function setDebugMode($debug) { + $this->debug = $debug; + } + function setEnableGZIP($enableGZIP) { + $this->enableGZIP = $enableGZIP; + } + function start() { + while(ob_get_length() !== false) @ob_end_clean(); + $this->initOutputBuffer(); + $this->sendHeader(); + $this->initErrorHandler(); + $this->initEncode(); + $this->initCallback(); + $this->initRef(); + $this->initClientID(); + $this->initEncrypt(); + if (isset($_REQUEST['phprpc_func'])) { + $this->callFunction(); + } + else if ($this->encrypt != false) { + $this->keyExchange(); + } + else { + $this->sendFunctions(); + } + } +} + +PHPRPC_Server::initSession(); +?> \ No newline at end of file diff --git a/Vendor/phpRPC/xxtea.php b/Vendor/phpRPC/xxtea.php new file mode 100644 index 00000000..b22f68fb --- /dev/null +++ b/Vendor/phpRPC/xxtea.php @@ -0,0 +1,134 @@ + | +| | +| This file may be distributed and/or modified under the | +| terms of the GNU General Public License (GPL) version | +| 2.0 as published by the Free Software Foundation and | +| appearing in the included file LICENSE. | +| | +\**********************************************************/ + +/* XXTEA encryption arithmetic library. + * + * Copyright: Ma Bingyao + * Version: 1.6 + * LastModified: Apr 12, 2010 + * This library is free. You can redistribute it and/or modify it under GPL. + */ +if (!extension_loaded('xxtea')) { + function long2str($v, $w) { + $len = count($v); + $n = ($len - 1) << 2; + if ($w) { + $m = $v[$len - 1]; + if (($m < $n - 3) || ($m > $n)) return false; + $n = $m; + } + $s = array(); + for ($i = 0; $i < $len; $i++) { + $s[$i] = pack("V", $v[$i]); + } + if ($w) { + return substr(join('', $s), 0, $n); + } + else { + return join('', $s); + } + } + + function str2long($s, $w) { + $v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3)); + $v = array_values($v); + if ($w) { + $v[count($v)] = strlen($s); + } + return $v; + } + + function int32($n) { + while ($n >= 2147483648) $n -= 4294967296; + while ($n <= -2147483649) $n += 4294967296; + return (int)$n; + } + + function xxtea_encrypt($str, $key) { + if ($str == "") { + return ""; + } + $v = str2long($str, true); + $k = str2long($key, false); + if (count($k) < 4) { + for ($i = count($k); $i < 4; $i++) { + $k[$i] = 0; + } + } + $n = count($v) - 1; + + $z = $v[$n]; + $y = $v[0]; + $delta = 0x9E3779B9; + $q = floor(6 + 52 / ($n + 1)); + $sum = 0; + while (0 < $q--) { + $sum = int32($sum + $delta); + $e = $sum >> 2 & 3; + for ($p = 0; $p < $n; $p++) { + $y = $v[$p + 1]; + $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $z = $v[$p] = int32($v[$p] + $mx); + } + $y = $v[0]; + $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $z = $v[$n] = int32($v[$n] + $mx); + } + return long2str($v, false); + } + + function xxtea_decrypt($str, $key) { + if ($str == "") { + return ""; + } + $v = str2long($str, false); + $k = str2long($key, false); + if (count($k) < 4) { + for ($i = count($k); $i < 4; $i++) { + $k[$i] = 0; + } + } + $n = count($v) - 1; + + $z = $v[$n]; + $y = $v[0]; + $delta = 0x9E3779B9; + $q = floor(6 + 52 / ($n + 1)); + $sum = int32($q * $delta); + while ($sum != 0) { + $e = $sum >> 2 & 3; + for ($p = $n; $p > 0; $p--) { + $z = $v[$p - 1]; + $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $y = $v[$p] = int32($v[$p] - $mx); + } + $z = $v[$n]; + $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $y = $v[0] = int32($v[0] - $mx); + $sum = int32($sum - $delta); + } + return long2str($v, true); + } +} +?> \ No newline at end of file diff --git a/alias.php b/alias.php new file mode 100644 index 00000000..073ea271 --- /dev/null +++ b/alias.php @@ -0,0 +1,40 @@ + +// +---------------------------------------------------------------------- + +// 系统类库映射定义 +return [ + 'Think\App' => CORE_PATH . 'App.php', + 'Think\Log' => CORE_PATH . 'Log.php', + 'Think\Log\Driver\File' => CORE_PATH . 'Log/Driver/File.php', + 'Think\Config' => CORE_PATH . 'Config.php', + 'Think\Route' => CORE_PATH . 'Route.php', + 'Think\Exception' => CORE_PATH . 'Exception.php', + 'Think\Model' => CORE_PATH . 'Model.php', + 'Think\Db' => CORE_PATH . 'Db.php', + 'Think\Db\Driver' => CORE_PATH . 'Db/Driver.php', + 'Think\Template' => CORE_PATH . 'Template.php', + 'Think\Error' => CORE_PATH . 'Error.php', + 'Think\Cache' => CORE_PATH . 'Cache.php', + 'Think\Cache\Driver\File' => CORE_PATH . 'Cache/Driver/File.php', + 'Think\Tag' => CORE_PATH . 'Tag.php', + 'Think\Session' => CORE_PATH . 'Session.php', + 'Think\Cookie' => CORE_PATH . 'Cookie.php', + 'Think\Controller' => CORE_PATH . 'Controller.php', + 'Think\View' => CORE_PATH . 'View.php', + 'Think\Url' => CORE_PATH . 'Url.php', + 'Think\Verify' => CORE_PATH . 'Verify.php', + 'Think\Debug' => CORE_PATH . 'Debug.php', + 'Think\Input' => CORE_PATH . 'Input.php', + 'Think\Parser' => CORE_PATH . 'Parser.php', + 'Think\Lang' => CORE_PATH . 'Lang.php', + 'Think\Filter' => CORE_PATH . 'Filter.php', + 'Think\Oauth' => CORE_PATH . 'Oauth.php', +]; diff --git a/base.php b/base.php new file mode 100644 index 00000000..7f744082 --- /dev/null +++ b/base.php @@ -0,0 +1,232 @@ + +// +---------------------------------------------------------------------- + +if(version_compare(PHP_VERSION,'5.4.0','<')) die('require PHP > 5.4.0 !'); +define('MAGIC_QUOTES_GPC', false); + +// 版本信息 +define('THINK_VERSION', '4.0beta'); +// 系统常量 +defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/'); +defined('LIB_PATH') or define('LIB_PATH', THINK_PATH.'Library/'); +defined('TRAIT_PATH') or define('TRAIT_PATH', THINK_PATH.'Traits/'); +defined('CORE_PATH') or define('CORE_PATH', LIB_PATH.'Think/'); +defined('ORG_PATH') or define('ORG_PATH', LIB_PATH.'Org/'); +defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); +defined('RUNTIME_PATH') or define('RUNTIME_PATH', realpath(APP_PATH).'/Runtime/'); +defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'Data/'); +defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'Log/'); +defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Temp/'); +defined('VENDOR_PATH') or define('VENDOR_PATH', THINK_PATH.'Vendor/'); +defined('EXT') or define('EXT', '.php'); +defined('APP_DEBUG') or define('APP_DEBUG', false); // 是否调试模式 + +// 环境常量 +define('MEMORY_LIMIT_ON', function_exists('memory_get_usage')); +define('IS_CGI', strpos(PHP_SAPI, 'cgi') === 0 ? 1 : 0); +define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0); +define('IS_CLI', PHP_SAPI=='cli' ? 1 : 0); +define('IS_AJAX', (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false); +define('NOW_TIME', $_SERVER['REQUEST_TIME']); +define('REQUEST_METHOD', $_SERVER['REQUEST_METHOD']); +define('IS_GET', REQUEST_METHOD =='GET' ? true : false); +define('IS_POST', REQUEST_METHOD =='POST' ? true : false); +define('IS_PUT', REQUEST_METHOD =='PUT' ? true : false); +define('IS_DELETE', REQUEST_METHOD =='DELETE' ? true : false); + +// 获取多语言变量 +function L($name){ + return Think\Lang::get($name); +} + +// 获取配置参数 +function C($name='',$range='') { + return Think\Config::get($name,$range); +} + +// 获取输入数据 支持默认值和过滤 +function I($key,$default='',$filter='') { + if(strpos($key,'.')) { // 指定参数来源 + list($method,$key) = explode('.',$key); + }else{ // 默认为自动判断 + $method = 'param'; + } + return Think\Input::$method($key,$filter,$default); +} + +/** + * 记录时间(微秒)和内存使用情况 + * @param string $label 记录标签 + * @return void + */ +function G($label) { + Think\Debug::remark($label); +} + +/** + * 实例化一个没有模型文件的Model + * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User + * @param string $tablePrefix 表前缀 + * @param mixed $connection 数据库连接信息 + * @return Model + */ +function M($name='', $tablePrefix='',$connection='') { + return Think\Loader::table($name,['table_prefix'=>$tablePrefix,'connection'=>$connection]); +} + +/** + * 实例化Model + * @param string $name Model名称 + * @param string $layer 业务层名称 + * @return object + */ +function D($name='',$layer='Model') { + return Think\Loader::model($name,$layer); +} + +/** + * 实例化数据库类 + * @param array $config 数据库配置参数 + * @param boolean $lite 是否lite连接 + * @return object + */ +function db($config=[],$lite=false) { + return Think\Db::instance($config,$lite); +} + +/** + * 实例化控制器 格式:[模块/]控制器 + * @param string $name 资源地址 + * @param string $layer 控制层名称 + * @return object + */ +function A($name,$layer='Controller') { + return Think\Loader::controller($name,$layer); +} + +/** + * 调用模块的操作方法 参数格式 [模块/控制器/]操作 + * @param string $url 调用地址 + * @param string|array $vars 调用参数 支持字符串和数组 + * @param string $layer 要调用的控制层名称 + * @return mixed + */ +function R($url,$vars=[],$layer='Controller') { + return Think\Loader::action($url,$vars,$layer); +} + +/** + * 导入所需的类库 同java的Import 本函数有缓存功能 + * @param string $class 类库命名空间字符串 + * @param string $baseUrl 起始路径 + * @param string $ext 导入的文件扩展名 + * @return boolean + */ +function import($class, $baseUrl = '', $ext= EXT ) { + return Think\Loader::import($class,$baseUrl,$ext); +} + +/** + * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面 + * @param string $class 类库 + * @param string $ext 类库后缀 + * @return boolean + */ +function vendor($class, $ext=EXT) { + return Think\Loader::import($class, VENDOR_PATH, $ext); +} + +/** + * 快速导入Traits + * @param string $class trait库 + * @param string $ext 类库后缀 + * @return boolean + */ +function T($class,$ext=EXT){ + return Think\Loader::import($class, TRAIT_PATH, $ext); +} + +/** + * 抛出异常处理 + * @param string $msg 异常消息 + * @param integer $code 异常代码 默认为0 + * @return void + */ +function E($msg, $code=0) { + throw new Think\Exception($msg, $code); +} + +/** + * 浏览器友好的变量输出 + * @param mixed $var 变量 + * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 + * @param string $label 标签 默认为空 + * @return void|string + */ +function dump($var, $echo=true, $label=null) { + return Think\Debug::dump($var,$echo,$label); +} + +/** + * 渲染输出Widget + * @param string $name Widget名称 + * @param array $data 传人的参数 + * @return void + */ +function W($name, $data=[]) { + echo Think\Loader::action($name,$data,'Widget'); +} + +/** + * 缓存管理 + * @param mixed $name 缓存名称,如果为数组表示进行缓存设置 + * @param mixed $value 缓存值 + * @param mixed $options 缓存参数 + * @return mixed + */ +function S($name,$value='',$options=null) { + static $cache = null; + if(is_array($options)){// 缓存操作的同时初始化 + $cache = Think\Cache::connect($options); + }elseif(is_array($name)) { // 缓存初始化 + $cache = Think\Cache::connect($name); + return $cache; + }elseif(is_null($cache)) {// 自动初始化 + $cache = Think\Cache::connect(); + } + if(''=== $value){ // 获取缓存 + return $cache->get($name); + }elseif(is_null($value)) { // 删除缓存 + return $cache->rm($name); + }else { // 缓存数据 + if(is_array($options)) { + $expire = isset($options['expire'])?$options['expire']:NULL; //修复查询缓存无法设置过期时间 + }else{ + $expire = is_numeric($options)?$options:NULL; //默认快捷缓存设置过期时间 + } + return $cache->set($name, $value, $expire); + } +} + +/** + * 字符串命名风格转换 + * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 + * @param string $name 字符串 + * @param integer $type 转换类型 + * @return string + */ +function parse_name($name, $type=0) { + if ($type) { + return ucfirst(preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name)); + } else { + return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); + } +} diff --git a/convention.php b/convention.php new file mode 100644 index 00000000..d68f2ee1 --- /dev/null +++ b/convention.php @@ -0,0 +1,65 @@ + +// +---------------------------------------------------------------------- + +// 惯例配置文件 +return [ + 'app_debug' => true, // 调试模式 + 'app_status' => 'debug',// 调试模式状态 + 'var_module' => 'm', // 模块变量名 + 'var_group' => 'g', // 分组变量名 + 'var_controller' => 'c', // 控制器变量名 + 'var_action' => 'a', // 操作变量名 + 'var_pathinfo' => 's', // PATHINFO变量名 用于兼容模式 + 'pathinfo_fetch' => 'ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL', + 'pathinfo_depr' => '/', // pathinfo分隔符 + 'require_module' => true, // 是否显示模块 + 'default_module' => 'index', // 默认模块名 + 'require_group' => false, // 控制器是否需要分组 + 'default_group' => '', // 默认分组名 + 'require_controller' => true, // 是否显示控制器 + 'default_controller' => 'index', // 默认控制器名 + 'default_action' => 'index', // 默认操作名 + 'action_suffix' => '', // 操作方法后缀 + 'url_model' => 1, // URL模式 + 'base_url' => $_SERVER["SCRIPT_NAME"], // 基础URL路径 + 'url_html_suffix' => '.html', + 'url_params_bind' => false, // url变量绑定 + 'exception_tmpl' => THINK_PATH.'Tpl/think_exception.tpl',// 异常页面的模板文件 + 'error_tmpl' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认错误跳转对应的模板文件 + 'success_tmpl' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认成功跳转对应的模板文件 + 'default_ajax_return' => 'JSON', // 默认AJAX 数据返回格式,可选JSON XML ... + 'default_jsonp_handler' => 'jsonpReturn', // 默认JSONP格式返回的处理方法 + 'var_jsonp_handler' => 'callback', + + /* 错误设置 */ + 'error_message' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效 + 'error_page' => '', // 错误定向页面 + 'show_error_msg' => false, // 显示错误信息 + + /* 数据库设置 */ + 'database' => [ + 'type' => 'mysql', // 数据库类型 + 'dsn' => '', // + 'hostname' => 'localhost', // 服务器地址 + 'database' => '', // 数据库名 + 'username' => 'root', // 用户名 + 'password' => '', // 密码 + 'hostport' => '', // 端口 + 'params' => [], // 数据库连接参数 + 'charset' => 'utf8', // 数据库编码默认采用utf8 + 'prefix' => '', // 数据库表前缀 + 'debug' => false, // 数据库调试模式 + 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'rw_separate' => false, // 数据库读写是否分离 主从式有效 + 'master_num' => 1, // 读写分离后 主服务器数量 + 'slave_no' => '', // 指定从服务器序号 + ], +]; diff --git a/start.php b/start.php new file mode 100644 index 00000000..f415b7a3 --- /dev/null +++ b/start.php @@ -0,0 +1,56 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +//-------------------------- +// ThinkPHP 引导文件 +//-------------------------- + +// 加载基础文件 +require __DIR__.'/base.php'; +require CORE_PATH.'Loader.php'; + +// 注册自动加载 +Loader::register(); +// 导入系统别名 +Loader::addMap(include THINK_PATH.'alias.php'); +// 加载应用类 +//require CORE_PATH.'App.php'; +// 加载错误类 +//require CORE_PATH.'Error.php'; + +// 注册错误和异常处理机制 +register_shutdown_function(['Think\Error','appShutdown']); +set_error_handler(['Think\Error','appError']); +set_exception_handler(['Think\Error','appException']); + +// 导入系统惯例 +Config::load(THINK_PATH.'convention.php'); + +// 初始化操作可以在应用的公共文件中处理 下面只是示例 +//--------------------------------------------------- +// 日志初始化 +Log::init(['type'=>'File','log_path'=> LOG_PATH]); + +// 缓存初始化 +Cache::connect(['type'=>'File','temp'=> CACHE_PATH]); +//------------------------------------------------------ + +// 启动session +if(!IS_CLI) { + Session::init(['prefix'=>'think','auto_start'=>true]); +} +if(is_file(APP_PATH.'build.php')) { // 自动化创建脚本 + Create::build(include APP_PATH.'build.php'); +} +// 执行应用 +App::run();