rabin 7 лет назад
Сommit
a0b005e838
100 измененных файлов с 19594 добавлено и 0 удалено
  1. 14 0
      LICENSE
  2. 92 0
      README.md
  3. 136 0
      boot.php
  4. 2 0
      build/boot.php
  5. BIN
      build/dever.phar
  6. 63 0
      config/base.php
  7. 14 0
      config/dyna.php
  8. 49 0
      config/env/localhost/cache.php
  9. 63 0
      config/env/localhost/database.php
  10. 21 0
      config/env/localhost/debug.php
  11. 219 0
      config/env/localhost/default.php
  12. 82 0
      config/env/localhost/host.php
  13. 34 0
      config/env/online/cache.php
  14. 27 0
      config/env/online/database.php
  15. 21 0
      config/env/online/debug.php
  16. 56 0
      config/env/online/host.php
  17. 62 0
      config/html/index.html
  18. 0 0
      config/index.html
  19. 38 0
      config/lang/zh-cn.php
  20. 6 0
      config/route.php
  21. 92 0
      config/web/plant.nginx.conf
  22. 462 0
      dever
  23. 3 0
      include.php
  24. 7 0
      vendor/autoload.php
  25. 36 0
      vendor/composer.json
  26. 413 0
      vendor/composer/ClassLoader.php
  27. 21 0
      vendor/composer/LICENSE
  28. 74 0
      vendor/composer/autoload_classmap.php
  29. 10 0
      vendor/composer/autoload_files.php
  30. 12 0
      vendor/composer/autoload_namespaces.php
  31. 10 0
      vendor/composer/autoload_psr4.php
  32. 59 0
      vendor/composer/autoload_real.php
  33. 199 0
      vendor/composer/installed.json
  34. 3 0
      vendor/dever-main/framework/README.md
  35. 25 0
      vendor/dever-main/framework/composer.json
  36. 1193 0
      vendor/dever-main/framework/dever.php
  37. 210 0
      vendor/dever-main/framework/src/Dever/Cache/Handle.php
  38. 11 0
      vendor/dever-main/framework/src/Dever/Cache/Store.php
  39. 97 0
      vendor/dever-main/framework/src/Dever/Cache/Store/Memcache.php
  40. 83 0
      vendor/dever-main/framework/src/Dever/Cache/Store/Redis.php
  41. 54 0
      vendor/dever-main/framework/src/Dever/Check/Load.php
  42. 41 0
      vendor/dever-main/framework/src/Dever/Config/Lang.php
  43. 209 0
      vendor/dever-main/framework/src/Dever/Config/Load.php
  44. 166 0
      vendor/dever-main/framework/src/Dever/Config/Project.php
  45. 51 0
      vendor/dever-main/framework/src/Dever/Data/Migration.php
  46. 1422 0
      vendor/dever-main/framework/src/Dever/Data/Model.php
  47. 101 0
      vendor/dever-main/framework/src/Dever/Data/Mongo/Connect.php
  48. 485 0
      vendor/dever-main/framework/src/Dever/Data/Mongo/Store.php
  49. 234 0
      vendor/dever-main/framework/src/Dever/Data/Mysql/Connect.php
  50. 390 0
      vendor/dever-main/framework/src/Dever/Data/Mysql/Store.php
  51. 30 0
      vendor/dever-main/framework/src/Dever/Data/Opt.php
  52. 169 0
      vendor/dever-main/framework/src/Dever/Data/Pdo/Connect.php
  53. 501 0
      vendor/dever-main/framework/src/Dever/Data/Pdo/Store.php
  54. 120 0
      vendor/dever-main/framework/src/Dever/Data/Service.php
  55. 739 0
      vendor/dever-main/framework/src/Dever/Data/Sql.php
  56. 494 0
      vendor/dever-main/framework/src/Dever/Data/Store.php
  57. 7 0
      vendor/dever-main/framework/src/Dever/Debug/Log.php
  58. 245 0
      vendor/dever-main/framework/src/Dever/Debug/Process.php
  59. 46 0
      vendor/dever-main/framework/src/Dever/File/Path.php
  60. 169 0
      vendor/dever-main/framework/src/Dever/Http/Input.php
  61. 243 0
      vendor/dever-main/framework/src/Dever/Http/Output.php
  62. 232 0
      vendor/dever-main/framework/src/Dever/Http/Url.php
  63. 1419 0
      vendor/dever-main/framework/src/Dever/Img/Handle.php
  64. 657 0
      vendor/dever-main/framework/src/Dever/Page/Main.php
  65. 806 0
      vendor/dever-main/framework/src/Dever/Routing/Load.php
  66. 108 0
      vendor/dever-main/framework/src/Dever/Routing/Route.php
  67. 72 0
      vendor/dever-main/framework/src/Dever/Routing/Step.php
  68. 213 0
      vendor/dever-main/framework/src/Dever/Routing/Uri.php
  69. 299 0
      vendor/dever-main/framework/src/Dever/Security/Api.php
  70. 164 0
      vendor/dever-main/framework/src/Dever/Security/Internal.php
  71. 157 0
      vendor/dever-main/framework/src/Dever/Security/String.php
  72. 76 0
      vendor/dever-main/framework/src/Dever/Server/Rpc.php
  73. 425 0
      vendor/dever-main/framework/src/Dever/Server/Swoole.php
  74. 207 0
      vendor/dever-main/framework/src/Dever/Session/Save.php
  75. 1222 0
      vendor/dever-main/framework/src/Dever/Template/Compile.php
  76. 10 0
      vendor/dever-main/framework/src/Dever/Template/Parse.php
  77. 574 0
      vendor/dever-main/framework/src/Dever/Template/Parse/Dom.php
  78. 676 0
      vendor/dever-main/framework/src/Dever/Template/View.php
  79. 343 0
      vendor/dever-main/framework/src/Dever/Upload/Upload.php
  80. 16 0
      vendor/erusev/parsedown/.travis.yml
  81. 20 0
      vendor/erusev/parsedown/LICENSE.txt
  82. 1528 0
      vendor/erusev/parsedown/Parsedown.php
  83. 57 0
      vendor/erusev/parsedown/README.md
  84. 18 0
      vendor/erusev/parsedown/composer.json
  85. 8 0
      vendor/erusev/parsedown/phpunit.xml.dist
  86. 74 0
      vendor/erusev/parsedown/test/CommonMarkTest.php
  87. 159 0
      vendor/erusev/parsedown/test/ParsedownTest.php
  88. 5 0
      vendor/erusev/parsedown/test/TestParsedown.php
  89. 3 0
      vendor/erusev/parsedown/test/bootstrap.php
  90. 18 0
      vendor/erusev/parsedown/test/data/aesthetic_table.html
  91. 4 0
      vendor/erusev/parsedown/test/data/aesthetic_table.md
  92. 21 0
      vendor/erusev/parsedown/test/data/aligned_table.html
  93. 4 0
      vendor/erusev/parsedown/test/data/aligned_table.md
  94. 9 0
      vendor/erusev/parsedown/test/data/atx_heading.html
  95. 17 0
      vendor/erusev/parsedown/test/data/atx_heading.md
  96. 1 0
      vendor/erusev/parsedown/test/data/automatic_link.html
  97. 1 0
      vendor/erusev/parsedown/test/data/automatic_link.md
  98. 12 0
      vendor/erusev/parsedown/test/data/block-level_html.html
  99. 16 0
      vendor/erusev/parsedown/test/data/block-level_html.md
  100. 8 0
      vendor/erusev/parsedown/test/data/code_block.html

+ 14 - 0
LICENSE

@@ -0,0 +1,14 @@
+Apache License
+Copyright 2016-2017 Dever(dever.cc)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

+ 92 - 0
README.md

@@ -0,0 +1,92 @@
+dever是一个php框架,与众不同。
+
+这是一个面向开发者的框架,在这里,你可以抛弃一切束缚,不需要写让人头疼的后台系统,不需要学习模板引擎,不需要额外的写接口,没有MVC(即使dever最终的编译结果是MVC模式)。
+
+你只需要开发你的业务,写好你的业务逻辑即可,你可以专心研究你的算法、你的架构。你甚至可以把你的业务打包,上传给dever,共享给其他dever开发者。
+
+
+1、安装:
+<pre>
+git clone https://github.com/dever-main/workspace
+cd workspace
+chmod +x dever
+</pre>
+
+2、初始化:
+<pre>
+./dever init
+OR
+./dever install init
+</pre>
+注意:初始化也支持composer安装,但是dever类库并未上传至github。
+
+3、配置:
+<pre>
+3.1、请把web/data/目录及其子目录设置为可写
+3.2、请修改config/localhost下的几个配置文件,当然你的服务器也可以配置server,随意设置DEVER_SERVER的值,默认值是localhost
+</pre>
+
+4、dever包管理:
+dever自带很多业务包,都是基于dever开发的:
+
+通用的后台系统(manage)
+
+微信管理(weixin)
+
+oauth2.0客户端(oauth)
+
+博客系统(blog)
+
+小型cms系统(cms)
+
+
+目前的包管理器中,只有manage开放给大家下载,后续会将所有包开放:
+
+dever自带的后台管理组件,所有项目都可以通过这个后台来进行管理业务数据,而你的项目是不需要做额外的事情的。
+
+安装manage:
+<pre>
+./dever install manage
+</pre>
+
+测试并访问manage:
+<pre>
+http://localhost/workspace/web/package/manage
+</pre>
+
+后台的默认管理员:
+<pre>
+账号:DMC@dever.cc
+密码:admin_123
+</pre>
+
+安装demo:
+<pre>
+./dever install demo
+</pre>
+
+测试并访问demo:
+<pre>
+http://localhost/workspace/web/application/demo
+</pre>
+
+装好demo之后,请到你的manage后台中查看一下是否安装了这个demo项目
+
+5、composer包管理:
+dever还支持composer,导入你所需要的包。
+
+初始化:
+<pre>
+./dever install composer
+</pre>
+
+更新:
+<pre>
+./dever up composer
+</pre>
+
+后续将使用dever开通官网:dever.cc以及coden.top代码交流社区。
+
+也会尽快开放wiki和教程。
+
+感谢您的关注!

+ 136 - 0
boot.php

@@ -0,0 +1,136 @@
+<?php
+/*
+|--------------------------------------------------------------------------
+| utf-8
+|--------------------------------------------------------------------------
+*/
+header('Content-Type: text/html; charset=utf-8');
+
+if(!defined('DEVER_PROJECT'))
+{
+	define('DEVER_PROJECT', 'default');
+}
+/*
+|--------------------------------------------------------------------------
+| date rpc
+|--------------------------------------------------------------------------
+*/
+date_default_timezone_set("PRC");
+/*
+|--------------------------------------------------------------------------
+| start time
+|--------------------------------------------------------------------------
+*/
+define('DEVER_START', microtime());
+/*
+|--------------------------------------------------------------------------
+| DEVER time
+|--------------------------------------------------------------------------
+*/
+define('DEVER_TIME', $_SERVER['REQUEST_TIME']);
+/*
+|--------------------------------------------------------------------------
+| DEVER path
+|--------------------------------------------------------------------------
+*/
+define('DEVER_PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+/*
+|--------------------------------------------------------------------------
+| DEVER project host
+|--------------------------------------------------------------------------
+*/
+if(isset($_SERVER['HTTP_HOST']))
+{
+	$entry = defined('DEVER_ENTRY') ? DEVER_ENTRY : 'index.php';
+	define('DEVER_APP_HOST', 'http://' . $_SERVER['HTTP_HOST'] . ($_SERVER['SCRIPT_NAME'] ? substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], $entry)) : DIRECTORY_SEPARATOR));
+}
+else
+{
+	define('DEVER_APP_HOST', '');
+}
+/*
+|--------------------------------------------------------------------------
+| autoload
+|--------------------------------------------------------------------------
+*/
+if(is_file(DEVER_PATH . 'build/dever.phar1'))
+{
+	require DEVER_PATH . 'build/dever.phar';
+
+	if(is_file(DEVER_PATH . 'composer.json'))
+	{
+		require DEVER_PATH . 'vendor/autoload.php';
+	}
+}
+else
+{
+	require DEVER_PATH . 'vendor/autoload.php';
+}
+/*
+|--------------------------------------------------------------------------
+| init input
+|--------------------------------------------------------------------------
+*/
+Dever\Http\Input::init();
+/*
+|--------------------------------------------------------------------------
+| init config
+|--------------------------------------------------------------------------
+*/
+Dever\Config\Load::init();
+/*
+|--------------------------------------------------------------------------
+| load debug
+|--------------------------------------------------------------------------
+*/
+if(Dever\Config\Load::$global['debug']['error'])
+{
+    /*
+    |----------------------------------------------------------------------
+    | error
+    |----------------------------------------------------------------------
+    */
+  	Dever\Debug\Process::report();
+}
+/*
+|--------------------------------------------------------------------------
+| DEVER app name
+|--------------------------------------------------------------------------
+*/
+if(!defined('DEVER_APP_NAME'))
+{
+	$temp = explode(Dever\Config\Load::$global['base']['path'], DEVER_APP_PATH);
+	define('DEVER_APP_NAME', chop(str_replace(DIRECTORY_SEPARATOR, '_', end($temp)), '_'));
+}
+/*
+|--------------------------------------------------------------------------
+| DEVER header cache
+|--------------------------------------------------------------------------
+*/
+if(isset(Dever\Config\Load::$global['base']['header-cache']) && Dever\Config\Load::$global['base']['header-cache'] == true)
+{
+	header("Expires: -1");
+	header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
+	header("Pragma: no-cache");
+}
+/*
+|--------------------------------------------------------------------------
+| project register
+|--------------------------------------------------------------------------
+*/
+Dever\Config\Project::register();
+/*
+|--------------------------------------------------------------------------
+| route
+|--------------------------------------------------------------------------
+*/
+$route = new Dever\Routing\Route;
+/*
+|--------------------------------------------------------------------------
+| route run and out
+|--------------------------------------------------------------------------
+*/
+if(!defined('DEVER_DAEMON'))
+{
+	$route->runing()->output();
+}

+ 2 - 0
build/boot.php

@@ -0,0 +1,2 @@
+<?php
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'vendor/autoload.php';

BIN
build/dever.phar


+ 63 - 0
config/base.php

@@ -0,0 +1,63 @@
+<?php
+# 基础配置,此处的配置所有的环境都一样,自动加入到env中
+
+return array
+(
+	# 名称
+	'name' => 'Dever开发框架',
+	# 基本描述
+	'desc' => '专注编程与开发的架构',
+	# copyright
+	'copyright' => '© 2015-2020 dever.cc,Inc. Licensed under MIT license.',
+	# github
+	'github' => 'https://github.com/dever-main',
+	# web
+	'web' => 'http://www.dever.cc/',
+	
+	
+	# 语言包设置
+	'lang' => 'zh-cn',
+	# api是否开启,默认关闭,如果开启,则所有数据接口必须接入api
+	'api' => false,
+	# 版本配置
+	'version' => '1.0.0 Beta',
+	
+	# 模板(assets)的所在目录,默认为html
+	'html' => 'html',
+	
+	# 使用的模板 注意:定义这个之后,将会强制将本项目模板变成这个 定义成数组的话则为pc和手机版
+	//'template' => array('pc', 'm'),
+	
+	# 定义这个之后,将强制将template的目录改为这个,不定义或不填写,则强制使用为template定义
+	//'service' => 'pc',
+
+	# 替换设置 一般用于替换资源,将模板中的(html中的)js等相对url换成绝对url,如果不定义,则默认为../js这样的
+	'replace' => array
+	(
+		'css' => '../css/',
+		'js' => '../js/',
+		'img' => array('../image/', '../img/'),
+		'images' => '../images/',
+		'lib' => '../lib/',
+		'public' => '../public/',
+		'font' => '../fonts/',
+	),
+
+	# url默认参数,所有Maze::url生成的链接都会加上这个参数
+	//'url' => 'loading=content',
+	
+	# 开启url中某个字段加密
+    //'url_encode' => array('id'),
+    # url的原始路径里包含什么字符,则不加密
+    'url_encode_filter' => array('tag'),
+    # 使用加密解密的方法
+    'url_encode_method' => array('Dever::idtostr', 'Dever::strtoid'),
+
+	# 是否启用layout 如启用,填写要替换的class或者id即可,具体效果可参考youtube,只加载部分内容,前端请加载pjax.js
+	//'layout' => '.content',
+	
+	# 是否启用自动过滤功能,必须加载manage包,目前可选的值为:manage(自带的过滤功能,非常简单,小型站点可以开启),bao10jie(必须申请账号)
+	//'filter' => array('manage' => 1,'bao10jie' => '账号'),
+	//'filter' => array('manage' => 1),
+);
+

+ 14 - 0
config/dyna.php

@@ -0,0 +1,14 @@
+<?php
+# 动态配置,可以用于seo配置,请在项目下建立该配置文件
+
+$name = 'VOGUE时尚网';
+return array
+(
+	# 首页 可与route相同
+	'home' => array
+	(
+		//'title' 		=> '时尚图片收藏与分享_分享你的潮流穿搭心经_' . $name,
+		'keyword' 		=> '时尚图片,图片收藏,图片分享,时尚潮流图片,$data[name]',
+		'desc' 			=> 'VOGUE时尚网发现社区,发现、收藏、整理、分享你喜欢的时尚图片、潮流服饰图片和搭配图片,你可以用它收集时尚灵感,保存兴趣图片素材,按喜欢的方式整理成不同的图集,分享你独有的时尚穿搭心经。',
+	)
+);

+ 49 - 0
config/env/localhost/cache.php

@@ -0,0 +1,49 @@
+<?php
+# 缓存配置,一共有四级缓存:mysql数据库缓存、data数据缓存、html页面模板缓存、load加载器缓存
+return array
+(
+	# 启用mysql数据库缓存,这个缓存是根据表名自动生成,dever::load形式和service的all、one形式均自动支持,无需手动添加
+	'mysql' => 0,
+	# 启用页面缓存 会根据当前的url来生成缓存,相当于页面静态化。
+	'html' => 0,
+	# 启用数据级别缓存 这个缓存是程序员自定义的:Dever::cache('name', 'value', 3600);
+	'data' => 3600,
+	# 启用load加载器缓存
+	'load' => 3600,
+
+	# 缓存精细控制,可以根据缓存的key(mysql为表名、service为小写类名,规则是模糊匹配),来控制每一条缓存
+	'load_key' => array
+	(
+		# 定义缓存名为auth.data的缓存时间
+		'auth.data' => 200,
+	),
+	
+	# 缓存清理的参数名,值为clear
+	'clear' => 'dever_cache',
+
+	# 是否启用key失效时间记录,启用之后,将会记录每个key的失效时间
+	'expire' => true,
+
+	# 缓存类型
+	'type' => 'memcache',//memcache、redis
+
+	# 缓存保存方式,支持多个数据源、多台缓存服务器
+	'store' => array
+	(
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11211',
+			'weight' => 100,
+		),
+
+		/*
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11212',
+			'weight' => 100,
+		),
+		*/
+	),
+);

+ 63 - 0
config/env/localhost/database.php

@@ -0,0 +1,63 @@
+<?php
+
+return array
+(
+	# default database config
+	'default' => array
+	(
+		'type' => 'pdo',
+		'host' => array
+		(
+			'read' => 'localhost:3306',
+			'update' => 'localhost:3306',
+		),
+		'database' => 'dever',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8',
+		# 持久化服务器,只负责保存数据,跟读写分离差不多,但可以更换不同的数据库类型
+		/*
+		'save' => array
+		(
+			'type' => 'pdo',
+			'host' => 'localhost:3306',
+			'database' => 'dever_test',
+			'username' => 'root',
+			'password' => '123456',
+			'charset' => 'utf8',
+		),
+
+		# 迁移旧的数据库服务器,具体迁移规则请到old目录中定义
+		'old' => array
+		(
+			'type' => 'pdo',
+			'host' => 'localhost:3306',
+			'database' => 'mazephp',
+			'username' => 'root',
+			'password' => '123456',
+			'charset' => 'utf8',
+		)
+		*/
+	),
+
+
+/*
+	'manage' => array
+	(
+		'type' => 'mysql',
+		'host' => 'localhost:3306,localhost:3306',//read,update
+		'database' => 'dever',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8'
+	)
+
+	array
+	(
+		'type' => 'mongo',
+		'host' => '127.0.0.1:27017',
+		'database' => 'farm',
+	),
+*/
+	
+);

+ 21 - 0
config/env/localhost/debug.php

@@ -0,0 +1,21 @@
+<?php
+
+return array
+(
+	# 开启错误提示 生产环境建议禁止
+	'error' => true,
+	
+	# 开始日志记录 暂时无效
+	'log' => true,
+
+	# 开始访问报告
+	# 生产环境建议禁止或添加ip限制,多个ip用逗号隔开
+	# 如禁止,值为false,下述shell也将失效
+	# 值为2,则开启强制模式,任何输出都将打印debug
+	'request' => Dever::ip(),
+
+	# 设定打印访问报告的指令,值为request
+	'shell' => 'dever_debug',
+	# 以上指令,请通过&dever_debug=request来执行,如果你想设置断点或者打印当前业务逻辑下的sql,请直接用Dever::debug();打印数据
+
+);

+ 219 - 0
config/env/localhost/default.php

@@ -0,0 +1,219 @@
+<?php
+# 集成项目的大部分配置,此为默认设置。环境不同,以下的配置也有可能不同,可以根据项目名建立配置文件
+
+# 基本配置
+$config['base'] = array
+(
+	# 项目部署的相对路径(部署在服务器的根目录,如果不定义DEVER_PROJECT_NAME,则本项必须启用并有效)
+	'path' => DIRECTORY_SEPARATOR . 'workspace' . DIRECTORY_SEPARATOR,
+
+	# 访问assets目录的物理路径
+	'assets' => DEVER_APP_PATH . 'assets' . DIRECTORY_SEPARATOR,
+
+	# 访问data目录的物理路径
+	'data' 	=> DEVER_PATH . 'web' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR,
+
+	# 访问当前项目目录的物理路径,如果项目和dever类库在一个目录中,则为DEVER_PATH,如果不在,则为DEVER_APP_PATH,当然也可随意更改,这里目前只影响合并操作
+	'workspace' => DEVER_PATH,
+
+	# 是否启用静态资源域名动态化,启用之后,静态资源的域名将动态加载,适合使用多个域名或publish启用
+	'assets_domain' => true,
+	
+	# 定义api的token明文,如果和其他业务有合作,建议使用系统自带的接口api,自带加密解密程序。
+	'token' => 'dever_api_2016',
+	
+	# 是否启用nocache,如果是互动类的项目且主域增加了cdn,建议开启
+	'header-cache' => false,
+
+	# 关闭自助建表,生产环境建议开启,开启之后无法对数据表进行更新操作
+	//'create' => true,
+	
+	# 是否开启强制刷新页面缓存,值为$_GET的key值
+	'template-cache' => 'dever_template_cache',
+	
+	# 是否开启手动更改模板,允许通过$_GET的方式来更改当前模板,值为$_GET的key值,默认关闭
+	//'template' => 'dever_template',
+	
+	# 开启用户触发cron,主要用于无法加到系统计划任务的虚拟主机,必须安装manage组件,谨慎开启,会稍微影响程序执行效率
+	//'cron' => true,
+	
+	# 是否开启mysql自助优化功能,开启后,会记录所有where条件和order的字段,可以方便的在后台进行分析、增加索引,必须安装manage组件
+	'opt' => true,
+	
+	# 是否开启sql自动优化,将sql中的select * 转换为 select a,b形式,将sql中的where条件按照索引从左到右自动排序,必须打开上述的opt选项,数据量大时建议打开。
+	//'sql' => true,
+
+	# publish 是否发布,此项开启后,系统不会检测service(意味着不用将service打包上线),适合生产环境,并能对代码起到一定的加密保护。
+	//'publish' => true,
+);
+
+# 数据库配置
+$config['database'] = array
+(
+	'type' => 'pdo',
+	'host' => array
+	(
+		'read' => 'localhost:3306',
+		'update' => 'localhost:3306',
+	),
+	'database' => 'dever',
+	'username' => 'root',
+	'password' => '123456',
+	'charset' => 'utf8',
+	# 持久化服务器,只负责保存数据,跟读写分离差不多,但可以更换不同的数据库类型
+	/*
+	'save' => array
+	(
+		'type' => 'pdo',
+		'host' => 'localhost:3306',
+		'database' => 'dever_test',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8',
+	),
+
+	# 迁移旧的数据库服务器,具体迁移规则请到old目录中定义
+	'old' => array
+	(
+		'type' => 'pdo',
+		'host' => 'localhost:3306',
+		'database' => 'mazephp',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8',
+	)
+	
+	# 换成mongodb
+	array
+	(
+		'type' => 'mongo',
+		'host' => '127.0.0.1:27017',
+		'database' => 'farm',
+	),
+	*/
+);
+
+# 缓存配置
+$config['cache'] = array
+(
+	# 启用mysql数据库缓存,这个缓存是根据表名自动生成,dever::load形式和service的all、one形式均自动支持,无需手动添加
+	'mysql' => 0,
+	# 启用页面缓存 会根据当前的url来生成缓存,相当于页面静态化。
+	'html' => 0,
+	# 启用数据级别缓存 这个缓存是程序员自定义的:Dever::cache('name', 'value', 3600);
+	'data' => 3600,
+	# 启用load加载器缓存
+	'load' => 3600,
+
+	# 缓存精细控制,可以根据缓存的key(mysql为表名、service为小写类名,规则是模糊匹配),来控制每一条缓存
+	'load_key' => array
+	(
+		# 定义缓存名为auth.data的缓存时间
+		'auth.data' => 200,
+	),
+	
+	# 缓存清理的参数名,值为clear
+	'clear' => 'dever_cache',
+
+	# 是否启用key失效时间记录,启用之后,将会记录每个key的失效时间
+	'expire' => true,
+
+	# 缓存类型
+	'type' => 'memcache',//memcache、redis
+
+	# 缓存保存方式,支持多个数据源、多台缓存服务器
+	'store' => array
+	(
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11211',
+			'weight' => 100,
+		),
+
+		/*
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11212',
+			'weight' => 100,
+		),
+		*/
+	),
+);
+
+# debug配置
+$config['debug'] = array
+(
+	# 开启错误提示 生产环境建议禁止
+	'error' => true,
+	
+	# 开始日志记录 暂时无效
+	'log' => true,
+
+	# 开始访问报告
+	# 生产环境建议禁止或添加ip限制,多个ip用逗号隔开
+	# 如禁止,值为false,下述shell也将失效
+	# 值为2,则开启强制模式,任何输出都将打印debug
+	'request' => Dever::ip(),
+
+	# 设定打印访问报告的指令,值为request
+	'shell' => 'dever_debug',
+	# 以上指令,请通过&dever_debug=request来执行,如果你想设置断点或者打印当前业务逻辑下的sql,请直接用Dever::debug();打印数据
+
+);
+
+$host = DEVER_APP_HOST;
+$assets = $host . 'assets/';
+# host 设置
+$config['host'] = array
+(
+	# 跟域名
+	'base' 	=> $host,
+
+	# cookie 域名
+	'cookie' => '',
+	
+	# assets网络路径,会自动将assets替换为assets/模板
+	'assets' => $assets,
+	# public
+	'public' => $assets . 'public/',
+
+	# 后台管理系统的assets路径
+	'manage' => $host . 'web/package/manage/assets/default/',
+	
+	# 合并之后的网络路径,填写之后自动合并资源,不填写则不合并,适合把资源放到云端
+	'merge' => $host . 'web/data/assets/' . DEVER_PROJECT . '/',
+	
+	# 上传系统的上传路径的域名(不带action)
+	'upload'=> $host . 'web/package/upload/?save',
+	# 上传系统的访问域名
+	'image'	=> $host . 'web/data/upload/',
+	
+	# 是否启用代理功能
+	'proxy' => $host . 'web/application/plant/main/?data.proxy?',
+
+	# 内部接口定义,Dever::load将自动转为这个配置,替换掉data/project/default.php里的数据
+	'api' => array
+	(
+		//'module' => 'http://192.168.33.10/workspace/web/application/earth/module/?',
+		//'upload' => 'http://192.168.33.10/workspace/web/package/upload/?',
+		'test' => array('http://192.168.33.10/workspace/web/package/upload/', '/src/'),
+		'test1' => 'http://test',
+		'test2' => '/src/',
+	),
+
+	'api_server' => array
+	(
+		'type' => 'tcp',
+	
+		# 以下为tcp模式特有的配置
+		# 是否使用后台运行
+		//'backend' => 1,
+		# 以下为swoole的配置
+		'worker_num' => 1,
+
+	),
+);
+
+return $config;

+ 82 - 0
config/env/localhost/host.php

@@ -0,0 +1,82 @@
+<?php
+
+# 本配置文件会根据部署位置的不同而修改,此处请自行修改
+
+$local = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
+
+# 本地可用这个
+$host = 'http://'.$local . Dever::$global['base']['path'];
+
+# 定义assets的域名
+$assets = DEVER_APP_HOST . 'assets/';
+if(DEVER_APP_NAME == 'manage')
+{
+	$assets = $host . 'web/package/manage/assets/';
+}
+
+# 跨域设置
+header('Access-Control-Allow-Origin:*');
+return array
+(
+	# 项目跟域名
+	'base' 	=> DEVER_APP_HOST,
+	# 跟域名
+	'workspace'	=> $host,
+
+	# cookie 域名
+	'cookie' => '',
+	
+	# assets 核心库访问地址 一般用不到,如果想把所有资源都放到这里,就要启用
+	'core' 	=> $host . 'assets/lib/',
+	
+	# assets网络路径,会自动将assets替换为assets/模板
+	'assets' => $assets,
+	'css' => $assets . 'css/',
+	'js' => $assets . 'js/',
+	'lib' => $assets . 'lib/',
+	'img' => $assets . 'img/',
+	'images' => $assets . 'images/',
+	'font' => $assets . 'fonts/',
+	# 公共模块 不会替换
+	'public' => $assets . 'public/',
+
+	# 后台管理系统的assets路径
+	'manage' => $host . 'web/package/manage/assets/default/',
+	
+	# 合并之后的网络路径,填写之后自动合并资源,不填写则不合并,适合把资源放到云端
+	'merge' => $host . 'web/data/assets/' . DEVER_PROJECT . '/',
+	
+	# 上传系统的上传路径的域名(不带action)
+	'upload'=> $host . 'web/package/upload/?save',
+	# 上传系统的访问域名
+	'image'	=> $host . 'web/data/upload/',
+	
+	# 是否启用代理功能
+	'proxy' => $host . 'web/application/plant/main/?data.proxy?',
+
+	# 内部接口定义,manage为当前使用的系统
+	'manage_api' => array
+	(
+		//'module' => 'http://192.168.33.10/workspace/web/application/earth/module/?',
+		'upload' => 'http://192.168.33.10/workspace/web/package/upload/?',
+	),
+
+	'api_server' => array
+	(
+		'type' => 'tcp',
+	
+		# 以下为tcp模式特有的配置
+		# 是否使用后台运行
+		//'backend' => 1,
+		# 以下为swoole的配置
+		'worker_num' => 1,
+
+	),
+
+	# 开启url中某个字段加密
+    #'url_encode' => array('id'),
+    # url的原始路径里包含什么字符,则不加密
+    #'url_encode_filter' => array('tag'),
+    # 使用加密解密的方法
+    #'url_encode_method' => array('Dever::idtostr', 'Dever::strtoid'),
+);

+ 34 - 0
config/env/online/cache.php

@@ -0,0 +1,34 @@
+<?php
+
+return array
+(
+	# 启用mysql数据库缓存
+	'mysql' => 0,
+	# 启用页面缓存 会根据当前的url来生成缓存,相当于页面静态化。
+	'html' => 0,
+	# 启用路由缓存 暂时不支持
+	//'route' => 3600,
+
+	# 缓存类型
+	'type' => 'memcache',//file、memcache、redis 目前仅有memcache实现,其余后续加上
+
+	# 缓存保存方式,支持多个数据源、多台缓存服务器
+	'store' => array
+	(
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11211',
+			'weight' => 100,
+		),
+
+		/*
+		array
+		(
+			'host' => '127.0.0.1',
+			'port' => '11212',
+			'weight' => 100,
+		),
+		*/
+	),
+);

+ 27 - 0
config/env/online/database.php

@@ -0,0 +1,27 @@
+<?php
+
+return array
+(
+	# default database config
+	'default' => array
+	(
+		'type' => 'mysql',
+		'host' => 'localhost:3306,localhost:3306',//read,update
+		'database' => 'dever',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8'
+	),
+/*
+	'manage' => array
+	(
+		'type' => 'mysql',
+		'host' => 'localhost:3306,localhost:3306',//read,update
+		'database' => 'dever',
+		'username' => 'root',
+		'password' => '123456',
+		'charset' => 'utf8'
+	)
+*/
+	
+);

+ 21 - 0
config/env/online/debug.php

@@ -0,0 +1,21 @@
+<?php
+
+return array
+(
+	# 开启错误提示 生产环境建议禁止
+	'error' => false,
+	
+	# 开始日志记录 暂时无效
+	'log' => true,
+
+	# 开始访问报告
+	# 生产环境建议禁止或添加ip限制,多个ip用逗号隔开
+	# 如禁止,值为false,下述shell也将失效
+	# 值为2,则开启强制模式,任何输出都将打印debug
+	'request' => false,
+
+	# 设定打印访问报告的指令,值为request
+	'shell' => 'dever_debug',
+	# 以上指令,请通过&dever_debug=request来执行,如果你想设置断点或者打印当前业务逻辑下的sql,请直接用Dever::debug();打印数据
+
+);

+ 56 - 0
config/env/online/host.php

@@ -0,0 +1,56 @@
+<?php
+
+# 本配置文件会根据部署位置的不同而修改,此处请自行修改
+
+$local = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
+
+# 域名后缀,可以随意修改
+$domain = $_SERVER['SERVER_NAME'];
+
+# 当前项目的主域名
+$host = 'http://'.$local . '/';
+
+# 定义当前项目assets的域名
+$assets = $host . 'assets/';
+
+# 跨域设置
+header('Access-Control-Allow-Origin:http://'.$local);
+
+return array
+(
+	# 项目跟域名
+	'base' 	=> DEVER_APP_HOST,
+	# 跟域名
+	'workspace'	=> $host,
+
+	# cookie 域名
+	'cookie' => $domain,
+	
+	# assets 核心库访问地址 一般用不到,如果想把所有资源都放到这里,就要启用
+	'core' 	=> $host . 'assets/lib/',
+	
+	# assets网络路径,会自动将assets替换为assets/模板
+	'assets' => $assets,
+	'css' => $assets . 'css/',
+	'js' => $assets . 'js/',
+	'lib' => $assets . 'lib/',
+	'img' => $assets . 'img/',
+	'images' => $assets . 'images/',
+	'font' => $assets . 'fonts/',
+	# 公共模块 不会替换
+	'public' => $assets . 'public/',
+
+	# 后台管理系统的assets路径
+	'manage' => 'http://manage.'.$domain.'/assets/default/',
+	
+	# 合并之后的网络路径,填写之后自动合并资源,不填写则不合并,适合把资源放到云端
+	'merge' => 'http://assets.'.$domain.'/' . DEVER_PROJECT . '/',
+	
+	# 上传系统的上传路径的域名(不带action)
+	'upload' => 'http://upload.'.$domain.'/save',
+	# 上传系统的访问域名
+	'image' => 'http://file.'.$domain.'/',
+	
+	# 是否启用代理功能,代理接口
+	'proxy' => $host . 'data.proxy?',
+);

+ 62 - 0
config/html/index.html

@@ -0,0 +1,62 @@
+
+<!DOCTYPE html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+<title>无法打开页面-Dever</title>
+
+<style type="text/css">
+body,code,dd,div,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0}
+body{font:14px/1.5 'Microsoft YaHei','微软雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}
+:focus{outline:0}
+h1,h2,h3,h4,h5,h6,strong{font-weight:700}
+a{color:#428bca;text-decoration:none}
+a:hover{text-decoration:underline}
+.error-page{background:#f0f1f3;padding:80px 0 180px}
+.error-page-container{position:relative;z-index:1}
+.error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}
+.error-page-main:before{content:'';display:block;height:7px;position:absolute;top:-7px;width:100%;left:0}
+.error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}
+.error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}
+.error-page-main h4{font-size:20px;font-weight:400;color:#333}
+.error-page-actions{font-size:0;z-index:100}
+.error-page-actions div{font-size:14px;display:inline-block;padding:30px 0 0 10px;width:50%;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;color:#838383}
+.error-page-actions ol{list-style:decimal;padding-left:20px}
+.error-page-actions li{line-height:2.5em}
+.error-page-actions:before{content:'';display:block;position:absolute;z-index:-1;bottom:17px;left:50px;width:200px;height:10px;-moz-box-shadow:4px 5px 31px 11px #999;-webkit-box-shadow:4px 5px 31px 11px #999;box-shadow:4px 5px 31px 11px #999;-moz-transform:rotate(-4deg);-webkit-transform:rotate(-4deg);-ms-transform:rotate(-4deg);-o-transform:rotate(-4deg);transform:rotate(-4deg)}
+.error-page-actions:after{content:'';display:block;position:absolute;z-index:-1;bottom:17px;right:50px;width:200px;height:10px;-moz-box-shadow:4px 5px 31px 11px #999;-webkit-box-shadow:4px 5px 31px 11px #999;box-shadow:4px 5px 31px 11px #999;-moz-transform:rotate(4deg);-webkit-transform:rotate(4deg);-ms-transform:rotate(4deg);-o-transform:rotate(4deg);transform:rotate(4deg)}
+</style>
+
+</head>
+<body>
+
+<div class="error-page">
+    <div class="error-page-container">
+        <div class="error-page-main" error="<?php echo $html?>">
+            <h3>
+                <strong>404</strong>无法打开页面
+            </h3>
+            <div class="error-page-actions">
+                <div>
+                    <h4>可能原因:</h4>
+                    <ol>
+                        <li>网络信号差</li>
+                        <li>找不到请求的页面</li>
+                        <li>输入的网址不正确</li>
+                    </ol>
+                </div>
+                <div>
+                    <h4>可以尝试:</h4>
+                    <ul>
+                        <li><a href="<?php echo $host?>">返回首页</a></li>
+                        <li><a href="javascript:history.back(-1)">返回上一页</a></li>
+                        <li><a href="http://www.dever.cc/" target="_blank">到官网提出您的问题</a></li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+</body>
+</html>

+ 0 - 0
config/index.html


+ 38 - 0
config/lang/zh-cn.php

@@ -0,0 +1,38 @@
+<?php
+
+return array
+(
+	# 核心相关
+	# 数据不存在
+	'core_database_exists' => '数据库{0}不存在',
+	# 请求不匹配
+	'core_database_request' => '参数{0}为空,或者不匹配该规则:{1}',
+	# dom不存在
+	'dom_exists' => 'dom"{0}"不存在',
+	# 文件不存在
+	'file_exists' => '文件"{0}"不存在',
+	# 目录不存在
+	'path_exists' => '目录"{0}"不存在',
+	# 目录不存在
+	'path_exists_array' => '目录"{0}"不存在',
+	# 类中的方法不存在
+	'method_exists' => '{0}中的方法{1}不存在',
+	# api配置不存在
+	'api_exists' => 'api"{0}"不存在',
+	# api配置不存在
+	'api_key_exists' => 'api中的配置{0}不存在',
+	# api参数不存在
+	'api_param_exists' => '参数{0}不存在',
+	# api参数signature校验错误
+	'api_signature_exists' => 'signature校验错误',
+	# 错误的页面
+	'error_page' => '无法打开页面',
+	# xss请求
+	'request_tainting' => 'request_tainting',
+	# 项目不存在
+	'project_exists' => '项目"{0}"不存在',
+	# 项目已存在
+	'project_already_exists' => '项目"{0}"已存在',
+	
+	# 后台相关
+);

+ 6 - 0
config/route.php

@@ -0,0 +1,6 @@
+<?php
+
+return array
+(
+	'' => 'home',
+);

+ 92 - 0
config/web/plant.nginx.conf

@@ -0,0 +1,92 @@
+server {
+    server_name yubin.bid www.yubin.bid manage.yubin.bid forum.yubin.bid passport.yubin.bid upload.yubin.bid;
+
+    listen 80;
+
+    autoindex on;
+
+    set $charset utf-8;
+
+    charset $charset;
+
+    set $rootdir /data/web/yubin.bid/web/application/plant;
+    set $project www;
+
+    if ( $host ~* "^([^\.]+)\.yubin\.bid" ) {
+        set $project $1;
+    }
+
+    if ( $project ~* www ) {
+        set $project main;
+    }
+
+    set $rewrite yes;
+
+    if ( $request_uri ~* (assets\/|crossdomain\.xml) ) {
+        set $rewrite no;
+        set $rootdir /data/web/yubin.bid/web/package;
+    }
+
+    set $rootdir $rootdir/$project;
+    root $rootdir;
+    index index.php index.html;
+
+
+    if ($rewrite ~* yes) {
+        rewrite ^/(.*) /index.php/$1 last;
+    }
+
+    location ~ /(assets\/|crossdomain\.xml)
+    {
+        try_files $uri $uri/ /index.html;
+    }
+
+
+    location / {
+        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
+
+        # With php5-cgi alone:
+        #fastcgi_pass 127.0.0.1:9000;
+        # With php5-fpm:
+        fastcgi_pass unix:/var/run/php5-fpm.sock;
+        fastcgi_index index.php;
+        include fastcgi_params;
+    }
+}
+
+
+server {
+    server_name file.yubin.bid assets.yubin.bid;
+
+    listen 80;
+
+    autoindex on;
+
+    set $charset utf-8;
+
+    charset $charset;
+
+    set $rootdir /data/web/yubin.bid/web/data;
+    set $project upload;
+
+    if ( $host ~* "^([^\.]+)\.yubin\.bid" ) {
+        set $project $1;
+    }
+
+    if ( $project ~* file ) {
+        set $project upload;
+    }
+
+    set $rootdir $rootdir/$project;
+    root $rootdir;
+    index index.html;
+    location / {
+                # First attempt to serve request as file, then
+                # as directory, then fall back to displaying a 404.
+                try_files $uri $uri/ =404;
+                # Uncomment to enable naxsi on this location
+                # include /etc/nginx/naxsi.rules
+    }
+
+}

+ 462 - 0
dever

@@ -0,0 +1,462 @@
+#!/usr/bin/env php
+<?php
+define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+class Dever
+{
+	static protected $package = 'http://dever.shemic.com/';
+	static protected $command = array();
+	static protected $check = false;
+
+	static public function handle()
+	{
+		global $argc,$argv;
+
+		if(isset($argv) && isset($argv[1]))
+		{
+			self::out('loading...');
+			$method = 'method_' . $argv[1];
+			if(!method_exists(__CLASS__, $method))
+			{
+				self::error();
+			}
+			if(isset($argv[3]))
+			{
+				unset($argv[0]);
+				unset($argv[1]);
+				$name = $argv[2];
+				unset($argv[2]);
+				self::$method($name, $argv);
+			}
+			elseif(isset($argv[2]))
+			{
+				self::$method($argv[2]);
+			}
+			else
+			{
+				self::$method();
+			}
+
+			self::exe();
+		}
+		else
+		{
+			self::error();
+		}
+	}
+
+	static protected function input($text, $default = '')
+    {
+		if(is_array($text))
+		{
+			$text = implode("\n", $text);
+		}
+    	
+    	self::out($text);
+
+		$stdin = fopen('php://stdin','r');
+		$shell = trim(fgets($stdin,100));
+		
+		return $shell ? $shell : $default;
+	}
+
+	static protected function out($text)
+	{
+		echo $text . "\n";
+	}
+
+	static protected function error()
+	{
+		self::out('error');
+		die;
+	}
+
+	static protected function notice()
+	{
+		self::out('您的php不支持system,请联系空间商或管理员开启system。');
+		die;
+	}
+
+	static public function command($command)
+	{
+		array_push(self::$command, $command);
+	}
+
+	static public function exe()
+	{
+		if(!self::check())
+		{
+			self::notice();
+		}
+
+		if(self::$command)
+		{
+			system(implode(' && ', self::$command));
+		}
+		echo "Finished!\n";
+	}
+
+	static protected function check()
+	{
+		if(self::$check)
+		{
+			return true;
+		}
+		if(!function_exists('system'))
+		{
+			return false;
+		}
+
+		return true;
+	}
+
+    static protected function method_init($type = 'main')
+    {
+    	self::command('sudo cp -R dever /usr/bin/dever');
+		self::command('sudo chmod +x /usr/bin/dever');
+    	if($type == 'composer')
+    	{
+    		//$HOME
+			$composer = '/usr/bin/composer';
+			//$shell = 'sudo curl -sS http://packagist.cn/composer/installer | sudo php -d detect_unicode=Off';
+			self::command('sudo curl http://getcomposer.org/installer | sudo php -d detect_unicode=Off');
+			self::command('sudo mv composer.phar ' . $composer);
+			self::command('sudo chmod +x ' . $composer);
+			self::command('composer install --optimize-autoloader');
+    	}
+    	else
+    	{
+    		self::method_install('init');
+    	}
+	}
+	
+	static protected function method_up($type = 'main')
+    {
+    	if($type == 'composer')
+    	{
+			self::command('composer update --optimize-autoloader');
+		}
+		else
+    	{
+    		self::method_install('init');
+    	}
+	}
+	
+	static protected function method_opt()
+    {
+		self::command('composer dump-autoload --optimize');
+	}
+
+    static protected function method_git()
+    {
+        self::command('sudo apt-get install git-core');
+    }
+
+    static protected function method_pack($name, $path = '')
+    {
+    	if($name == 'init')
+    	{
+    		$path = array
+    		(
+    			'build/',
+    			'config/',
+    			'boot.php',
+    			'web/data/assets/index.html',
+    			'web/data/cache/index.html',
+    			'web/data/compile/index.html',
+    			'web/data/database/index.html',
+    			'web/data/manage/index.html',
+    			'web/data/node/index.html',
+    			'web/data/project/index.html',
+    			'web/data/sql/index.html',
+    			'web/data/upload/index.html',
+    			'web/data/index.html',
+    			'web/package/boot.php',
+    			'web/package/index.html',
+    			'web/application/boot.php',
+    			'web/application/index.html',
+    		);
+    		$path = implode(' ', $path);
+    	}
+    	else
+    	{
+    		if(!$path)
+	    	{
+	    		$path = $name;
+	    	}
+
+	    	if(is_array($path))
+	    	{
+	    		$method = 1;
+	    		if(isset($path[3]) && $path[3] == '-p')
+	    		{
+	    			unset($path[3]);
+	    			$method = 2;
+	    		}
+
+	    		$temp = $path;
+	    		$path = '';
+	    		foreach($temp as $k => $v)
+	    		{
+	    			if($method == 2)
+	    			{
+	    				$n = explode('/', $v);
+		    			$m = count($n)-2;
+		    			$n = $n[$m];
+
+		    			if(!is_dir(PATH . 'web/data/assets/'.$n))
+		    			{
+		    				$n = 'default';
+		    			}
+
+		    			$template = $v . 'template';
+
+		    			if(!is_dir(PATH . $template))
+		    			{
+		    				$template = $v . 'main/template';
+		    			}
+
+		    			$e = ' web/data/assets/'.$n.' web/data/compile/'.$n.' --exclude=' . $template;
+	    			}
+	    			else
+	    			{
+	    				$e = ' --exclude=' . $v . 'template';
+	    			}
+
+	    			$path .= ' ' . $v . $e;
+	    		}
+	    	}
+    	}
+    	
+        self::command('tar -czf install/' . $name . '.tar.gz ' . $path . ' --exclude-vcs');
+    }
+
+    static protected function method_init_laravel()
+    {
+    	self::command('composer create-project laravel/laravel --prefer-dist');
+    }
+
+    static protected function method_create()
+    {
+    	self::method_install('create');
+    }
+
+    static protected function method_mysql()
+    {
+    	$text = array
+		(
+			'请输入命令以执行相应操作:'
+			, 'backup:备份mysql'
+			, 'restore:恢复mysql'
+			, '请在输入命令之后按回车键'
+			
+		);
+
+		$shell = self::input($text);
+
+		switch($shell)
+		{
+			case 'backup':
+				Mysql::backup();
+				break;
+			case 'restore':
+				Mysql::restore();
+				break;
+			default:
+				echo "未定义的方法";
+				break;
+		}
+    }
+
+    static protected function method_install($value)
+	{
+		$value .= '.tar.gz';
+		if(self::check())
+		{
+			self::command('wget -c ' . self::$package . $value);
+			self::command('tar -zxvf ' . $value);
+			self::command('rm -rf ' . $value);
+
+			if($value == 'composer')
+			{
+				self::method_init($value);
+			}
+		}
+		elseif(class_exists('PharData'))
+		{
+			self::$check = true;
+			$path = dirname(__FILE__) . '/';
+			file_put_contents($path . $value, file_get_contents(self::$package . $value));
+			$phar = new PharData($value);
+			$phar->extractTo($path, null, true);
+			unlink($path . $value);
+		}
+		else
+		{
+			self::notice();
+		}
+	}
+
+	static private function copy($src, $dst, $path)
+    {
+        if(function_exists('system'))
+        {
+            system('cp -R ' . $src . ' ' . $dst);
+        }
+        else
+        {
+            $path = str_replace(array('/', '..'), '', $path);
+            $dst = $dst . $path;
+
+            if(!is_dir($dst))
+            {
+                mkdir($dst);
+            }
+
+            $dir = opendir($src);
+            
+            while(false !== ($file = readdir($dir)))
+            {
+                if(($file != '.') && ($file != '..'))
+                {
+                    if(is_dir($src . '/' . $file))
+                    {
+                        $this->copyDir($src . '/' . $file, $dst . '/' . $file);
+                    }
+                    else
+                    {
+                        copy($src . '/' . $file, $dst . '/' . $file);
+                    }
+                }
+            }
+            closedir($dir);
+        }
+    }
+
+	static protected function method_build($path = 'vendor')
+	{
+		//$exts = ['php','js','css','html'];
+		$exts = array('php', 'js', 'css', 'html');
+		$dir = dirname(__FILE__) . '/build/';
+
+		$path && system('cp -R '.$path.' ' . $dir);
+
+		$file = 'dever.phar';
+
+		$phar = new Phar($dir . $file, FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME, $file);
+
+		$phar->startBuffering();
+
+		if($path)
+		{
+			foreach($exts as $ext)
+			{
+			    $phar->buildFromDirectory($dir, '/\.' . $ext . '$/');
+			}
+		}
+
+		$index = 'boot.php';
+		$phar->buildFromIterator
+		(
+			new ArrayIterator
+			(
+		 		array
+		 		(
+				    $index => $dir . $index,
+				)
+		    )
+		);
+		//$phar->delete('build.php');
+		$phar->setStub($phar->createDefaultStub($index, $index));
+		$phar->compressFiles(Phar::GZ);
+		$phar->stopBuffering();
+		//system('cp -R ' . $dir . $file . ' ' . $file);
+		$path && system('rm -rf ' . $dir . $path);
+	}
+}
+
+class Create extends Dever
+{
+
+}
+
+class Mysql extends Dever
+{
+	static protected function common()
+    {
+		$info['host'] = self::input('请输入mysql的主机地址:默认为localhost', 'localhost');
+		$info['username'] = self::input('请输入mysql的账号:默认为root', 'root');
+		$info['password'] = self::input('请输入mysql的密码:默认为空', '');
+		$info['database'] = self::input('请输入mysql的数据库名:');
+		
+		if(!$info['host'] || !$info['username'] || !$info['password'] || !$info['database'])
+		{
+			self::out('请输入正确的数据库信息!');die;
+		}
+	
+		$info['file'] = PATH . 'web/data/sql/' . $info['database'];
+		
+		$info['shell'] = ' -u' . $info['username'] . ' -p' . $info['password'] . ' -h' . $info['host'] . ' ';
+
+		return $info;
+	}
+	
+	static public function backup()
+    {
+		$info = self::common();
+		
+		$info['table'] = self::input('请输入mysql的表名(不输入则备份整个'.$info['database'].'数据库):');
+		$info['type'] = self::input('请输入备份类型:1为备份全部,2为备份结构,3为备份数据');
+		
+		$info['shell'] = 'mysqldump ' . $info['shell'];
+
+		if($info['type'] == 2)
+		{
+			$info['shell'] .= ' -d ' . $info['database'];
+		}
+		elseif($info['type'] == 3)
+		{
+			$info['shell'] .= ' -t ' . $info['database'];
+		}
+		else
+		{
+			$info['shell'] .= ' ' . $info['database'];
+		}
+		
+		if($info['table'])
+		{
+			$info['shell'] .= ' ' . $info['table'];
+			$info['file'] .= '.' . $info['table'];
+		}
+		
+		$info['file'] .= '.sql';
+		
+		$info['shell'] .= ' > ' . $info['file'];
+		
+		self::command($info['shell']);
+
+		self::out('操作成功,输出路径:' . $info['file']);
+	}
+	
+	static public function restore()
+    {
+		$info = self::common();
+		
+		$info['new'] = self::input('请输入要恢复的全新数据库:为空则使用上边填的数据库', $info['database']);
+
+		$create_table = 'mysqladmin ' . $info['shell'] . ' create ' . $info['new'];
+
+		$info['shell'] = 'mysql ' . $info['shell'] . ' ' . $info['new'];
+		
+		$info['file'] .= '.sql';
+		
+		$info['shell'] .= ' < ' . $info['file'];
+		
+		self::exe($create_table);
+		self::command($info['shell']);
+
+		self::out('操作成功,您已成功恢复' . $info['file'] . '里的数据');
+	}
+}
+
+
+Dever::handle();

+ 3 - 0
include.php

@@ -0,0 +1,3 @@
+<?php
+define('DEVER_INCLUDE_PATH', DEVER_PATH);
+set_include_path(get_include_path() . PATH_SEPARATOR . $path);

+ 7 - 0
vendor/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer' . '/autoload_real.php';
+
+return ComposerAutoloaderInit250b3766e5468b010f1c776855455762::getLoader();

+ 36 - 0
vendor/composer.json

@@ -0,0 +1,36 @@
+{
+	"repositories": [
+        {
+            "type": "vcs",
+            "url": "https://github.com/dever-main/framework"
+        },
+        {   
+            "type": "composer", 
+            "url": "http://packagist.cn"
+        },
+        {
+            "packagist": false
+        }
+    ],
+    
+    "require": {
+        "dever-main/framework": "dev-master"
+        ,"sunra/php-simple-html-dom-parser": "v1.5.0"
+        ,"erusev/parsedown": "1.6.0"
+        ,"filp/whoops": "2.1.2"
+    },
+
+    "require_test": {
+        "username/project": "version"
+        ,"phpoffice/phpexcel": "1.8.1"
+        ,"kriswallsmith/assetic": "v1.3.2"
+        ,"fzaninotto/faker": "v1.6.0"
+        ,"illuminate/validation": "v5.2.31"
+        ,"mrrio/shellwrap": "0.4.1"
+        ,"symfony/var-dumper": "v3.1.6"
+    },
+
+	"config": {
+		"secure-http": false
+	}
+}

+ 413 - 0
vendor/composer/ClassLoader.php

@@ -0,0 +1,413 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see    http://www.php-fig.org/psr/psr-0/
+ * @see    http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+    // PSR-4
+    private $prefixLengthsPsr4 = array();
+    private $prefixDirsPsr4 = array();
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    private $prefixesPsr0 = array();
+    private $fallbackDirsPsr0 = array();
+
+    private $useIncludePath = false;
+    private $classMap = array();
+
+    private $classMapAuthoritative = false;
+
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', $this->prefixesPsr0);
+        }
+
+        return array();
+    }
+
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param array $classMap Class to filename map
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string       $prefix  The prefix
+     * @param array|string $paths   The PSR-0 root directories
+     * @param bool         $prepend Whether to prepend the directories
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string       $prefix  The prefix/namespace, with trailing '\\'
+     * @param array|string $paths   The PSR-4 base directories
+     * @param bool         $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string       $prefix The prefix
+     * @param array|string $paths  The PSR-0 base directories
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string       $prefix The prefix/namespace, with trailing '\\'
+     * @param array|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return bool|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+        if ('\\' == $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative) {
+            return false;
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if ($file === null && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if ($file === null) {
+            // Remember that this class does not exist.
+            return $this->classMap[$class] = false;
+        }
+
+        return $file;
+    }
+
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+    include $file;
+}

+ 21 - 0
vendor/composer/LICENSE

@@ -0,0 +1,21 @@
+
+Copyright (c) 2016 Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+

+ 74 - 0
vendor/composer/autoload_classmap.php

@@ -0,0 +1,74 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Dever\\Cache\\Handle' => $vendorDir . '/dever-main/framework/src/Dever/Cache/Handle.php',
+    'Dever\\Cache\\Store' => $vendorDir . '/dever-main/framework/src/Dever/Cache/Store.php',
+    'Dever\\Cache\\Store\\Memcache' => $vendorDir . '/dever-main/framework/src/Dever/Cache/Store/Memcache.php',
+    'Dever\\Cache\\Store\\Ris' => $vendorDir . '/dever-main/framework/src/Dever/Cache/Store/Redis.php',
+    'Dever\\Check\\Load' => $vendorDir . '/dever-main/framework/src/Dever/Check/Load.php',
+    'Dever\\Config\\Lang' => $vendorDir . '/dever-main/framework/src/Dever/Config/Lang.php',
+    'Dever\\Config\\Load' => $vendorDir . '/dever-main/framework/src/Dever/Config/Load.php',
+    'Dever\\Config\\Project' => $vendorDir . '/dever-main/framework/src/Dever/Config/Project.php',
+    'Dever\\Data\\Migration' => $vendorDir . '/dever-main/framework/src/Dever/Data/Migration.php',
+    'Dever\\Data\\Model' => $vendorDir . '/dever-main/framework/src/Dever/Data/Model.php',
+    'Dever\\Data\\Mongo\\Connect' => $vendorDir . '/dever-main/framework/src/Dever/Data/Mongo/Connect.php',
+    'Dever\\Data\\Mongo\\Store' => $vendorDir . '/dever-main/framework/src/Dever/Data/Mongo/Store.php',
+    'Dever\\Data\\Mysql\\Connect' => $vendorDir . '/dever-main/framework/src/Dever/Data/Mysql/Connect.php',
+    'Dever\\Data\\Mysql\\Store' => $vendorDir . '/dever-main/framework/src/Dever/Data/Mysql/Store.php',
+    'Dever\\Data\\Opt' => $vendorDir . '/dever-main/framework/src/Dever/Data/Opt.php',
+    'Dever\\Data\\Pdo\\Connect' => $vendorDir . '/dever-main/framework/src/Dever/Data/Pdo/Connect.php',
+    'Dever\\Data\\Pdo\\Store' => $vendorDir . '/dever-main/framework/src/Dever/Data/Pdo/Store.php',
+    'Dever\\Data\\Service' => $vendorDir . '/dever-main/framework/src/Dever/Data/Service.php',
+    'Dever\\Data\\Sql' => $vendorDir . '/dever-main/framework/src/Dever/Data/Sql.php',
+    'Dever\\Data\\Store' => $vendorDir . '/dever-main/framework/src/Dever/Data/Store.php',
+    'Dever\\Debug\\Log' => $vendorDir . '/dever-main/framework/src/Dever/Debug/Log.php',
+    'Dever\\Debug\\Process' => $vendorDir . '/dever-main/framework/src/Dever/Debug/Process.php',
+    'Dever\\File\\Path' => $vendorDir . '/dever-main/framework/src/Dever/File/Path.php',
+    'Dever\\Http\\Input' => $vendorDir . '/dever-main/framework/src/Dever/Http/Input.php',
+    'Dever\\Http\\Output' => $vendorDir . '/dever-main/framework/src/Dever/Http/Output.php',
+    'Dever\\Http\\Url' => $vendorDir . '/dever-main/framework/src/Dever/Http/Url.php',
+    'Dever\\Img\\Handle' => $vendorDir . '/dever-main/framework/src/Dever/Img/Handle.php',
+    'Dever\\Page\\Main' => $vendorDir . '/dever-main/framework/src/Dever/Page/Main.php',
+    'Dever\\Plad\\Upload' => $vendorDir . '/dever-main/framework/src/Dever/Upload/Upload.php',
+    'Dever\\Routing\\Load' => $vendorDir . '/dever-main/framework/src/Dever/Routing/Load.php',
+    'Dever\\Routing\\Route' => $vendorDir . '/dever-main/framework/src/Dever/Routing/Route.php',
+    'Dever\\Routing\\Step' => $vendorDir . '/dever-main/framework/src/Dever/Routing/Step.php',
+    'Dever\\Routing\\Uri' => $vendorDir . '/dever-main/framework/src/Dever/Routing/Uri.php',
+    'Dever\\Security\\Api' => $vendorDir . '/dever-main/framework/src/Dever/Security/Api.php',
+    'Dever\\Security\\Internal' => $vendorDir . '/dever-main/framework/src/Dever/Security/Internal.php',
+    'Dever\\Security\\String' => $vendorDir . '/dever-main/framework/src/Dever/Security/String.php',
+    'Dever\\Server\\Rpc' => $vendorDir . '/dever-main/framework/src/Dever/Server/Rpc.php',
+    'Dever\\Server\\Rpc_Api' => $vendorDir . '/dever-main/framework/src/Dever/Server/Rpc.php',
+    'Dever\\Server\\Swoole' => $vendorDir . '/dever-main/framework/src/Dever/Server/Swoole.php',
+    'Dever\\Session\\Save' => $vendorDir . '/dever-main/framework/src/Dever/Session/Save.php',
+    'Dever\\Template\\Compile' => $vendorDir . '/dever-main/framework/src/Dever/Template/Compile.php',
+    'Dever\\Template\\Parse' => $vendorDir . '/dever-main/framework/src/Dever/Template/Parse.php',
+    'Dever\\Template\\Parse\\Dom' => $vendorDir . '/dever-main/framework/src/Dever/Template/Parse/Dom.php',
+    'Dever\\Template\\View' => $vendorDir . '/dever-main/framework/src/Dever/Template/View.php',
+    'Parsedown' => $vendorDir . '/erusev/parsedown/Parsedown.php',
+    'ParsedownTest' => $vendorDir . '/erusev/parsedown/test/ParsedownTest.php',
+    'Sunra\\PhpSimple\\HtmlDomParser' => $vendorDir . '/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php',
+    'Whoops\\Exception\\ErrorException' => $vendorDir . '/filp/whoops/src/Whoops/Exception/ErrorException.php',
+    'Whoops\\Exception\\Formatter' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Formatter.php',
+    'Whoops\\Exception\\Frame' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Frame.php',
+    'Whoops\\Exception\\FrameCollection' => $vendorDir . '/filp/whoops/src/Whoops/Exception/FrameCollection.php',
+    'Whoops\\Exception\\Inspector' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Inspector.php',
+    'Whoops\\Handler\\CallbackHandler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/CallbackHandler.php',
+    'Whoops\\Handler\\Handler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/Handler.php',
+    'Whoops\\Handler\\HandlerInterface' => $vendorDir . '/filp/whoops/src/Whoops/Handler/HandlerInterface.php',
+    'Whoops\\Handler\\JsonResponseHandler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/JsonResponseHandler.php',
+    'Whoops\\Handler\\PlainTextHandler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/PlainTextHandler.php',
+    'Whoops\\Handler\\PrettyPageHandler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php',
+    'Whoops\\Handler\\XmlResponseHandler' => $vendorDir . '/filp/whoops/src/Whoops/Handler/XmlResponseHandler.php',
+    'Whoops\\Run' => $vendorDir . '/filp/whoops/src/Whoops/Run.php',
+    'Whoops\\RunInterface' => $vendorDir . '/filp/whoops/src/Whoops/RunInterface.php',
+    'Whoops\\Util\\HtmlDumperOutput' => $vendorDir . '/filp/whoops/src/Whoops/Util/HtmlDumperOutput.php',
+    'Whoops\\Util\\Misc' => $vendorDir . '/filp/whoops/src/Whoops/Util/Misc.php',
+    'Whoops\\Util\\SystemFacade' => $vendorDir . '/filp/whoops/src/Whoops/Util/SystemFacade.php',
+    'Whoops\\Util\\TemplateHelper' => $vendorDir . '/filp/whoops/src/Whoops/Util/TemplateHelper.php',
+);

+ 10 - 0
vendor/composer/autoload_files.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'a29b3138354a0000b56d8c47dcfa70fd' => $vendorDir . '/dever-main/framework/dever.php',
+);

+ 12 - 0
vendor/composer/autoload_namespaces.php

@@ -0,0 +1,12 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Sunra\\PhpSimple\\HtmlDomParser' => array($vendorDir . '/sunra/php-simple-html-dom-parser/Src'),
+    'Parsedown' => array($vendorDir . '/erusev/parsedown'),
+    'Dever' => array($vendorDir . '/dever-main/framework/src'),
+);

+ 10 - 0
vendor/composer/autoload_psr4.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Whoops\\' => array($vendorDir . '/filp/whoops/src/Whoops'),
+);

+ 59 - 0
vendor/composer/autoload_real.php

@@ -0,0 +1,59 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit250b3766e5468b010f1c776855455762
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        spl_autoload_register(array('ComposerAutoloaderInit250b3766e5468b010f1c776855455762', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInit250b3766e5468b010f1c776855455762', 'loadClassLoader'));
+
+        $map = require __DIR__ . '/autoload_namespaces.php';
+        foreach ($map as $namespace => $path) {
+            $loader->set($namespace, $path);
+        }
+
+        $map = require __DIR__ . '/autoload_psr4.php';
+        foreach ($map as $namespace => $path) {
+            $loader->setPsr4($namespace, $path);
+        }
+
+        $classMap = require __DIR__ . '/autoload_classmap.php';
+        if ($classMap) {
+            $loader->addClassMap($classMap);
+        }
+
+        $loader->register(true);
+
+        $includeFiles = require __DIR__ . '/autoload_files.php';
+        foreach ($includeFiles as $fileIdentifier => $file) {
+            composerRequire250b3766e5468b010f1c776855455762($fileIdentifier, $file);
+        }
+
+        return $loader;
+    }
+}
+
+function composerRequire250b3766e5468b010f1c776855455762($fileIdentifier, $file)
+{
+    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+        require $file;
+
+        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+    }
+}

+ 199 - 0
vendor/composer/installed.json

@@ -0,0 +1,199 @@
+[
+    {
+        "name": "sunra/php-simple-html-dom-parser",
+        "version": "v1.5.0",
+        "version_normalized": "1.5.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sunra/php-simple-html-dom-parser.git",
+            "reference": "a0b80ace086c7e09085669205e1b3c2c9c7a453c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sunra/php-simple-html-dom-parser/zipball/a0b80ace086c7e09085669205e1b3c2c9c7a453c",
+            "reference": "a0b80ace086c7e09085669205e1b3c2c9c7a453c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2"
+        },
+        "time": "2013-05-04 14:32:03",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Sunra\\PhpSimple\\HtmlDomParser": "Src/"
+            }
+        },
+        "notification-url": "http://packagist.cn/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "sunra",
+                "email": "sunra@yandex.ru",
+                "homepage": "http://github.com/sunra"
+            }
+        ],
+        "description": "Composer adaptation of: A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way! Require PHP 5+. Supports invalid HTML. Find tags on an HTML page with selectors just like jQuery. Extract contents from HTML in a single line.",
+        "homepage": "https://github.com/sunra/php-simple-html-dom-parser",
+        "keywords": [
+            "dom",
+            "html",
+            "parser"
+        ]
+    },
+    {
+        "name": "erusev/parsedown",
+        "version": "1.6.0",
+        "version_normalized": "1.6.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/erusev/parsedown.git",
+            "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
+            "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7",
+            "shasum": ""
+        },
+        "time": "2015-10-04 16:44:32",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Parsedown": ""
+            }
+        },
+        "notification-url": "http://packagist.cn/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Emanuil Rusev",
+                "email": "hello@erusev.com",
+                "homepage": "http://erusev.com"
+            }
+        ],
+        "description": "Parser for Markdown.",
+        "homepage": "http://parsedown.org",
+        "keywords": [
+            "markdown",
+            "parser"
+        ]
+    },
+    {
+        "name": "filp/whoops",
+        "version": "2.1.2",
+        "version_normalized": "2.1.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/filp/whoops.git",
+            "reference": "d13505b240a6f580bc75ba591da30299d6cb0eec"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/filp/whoops/zipball/d13505b240a6f580bc75ba591da30299d6cb0eec",
+            "reference": "d13505b240a6f580bc75ba591da30299d6cb0eec",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.5.9"
+        },
+        "require-dev": {
+            "mockery/mockery": "0.9.*",
+            "phpunit/phpunit": "^4.8 || ^5.0",
+            "symfony/var-dumper": "~3.0"
+        },
+        "suggest": {
+            "symfony/var-dumper": "Pretty print complex values better with var-dumper available",
+            "whoops/soap": "Formats errors as SOAP responses"
+        },
+        "time": "2016-04-07 06:16:25",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Whoops\\": "src/Whoops/"
+            }
+        },
+        "notification-url": "http://packagist.cn/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Filipe Dobreira",
+                "homepage": "https://github.com/filp",
+                "role": "Developer"
+            }
+        ],
+        "description": "php error handling for cool kids",
+        "homepage": "https://github.com/filp/whoops",
+        "keywords": [
+            "error",
+            "exception",
+            "handling",
+            "library",
+            "whoops",
+            "zf2"
+        ]
+    },
+    {
+        "name": "dever-main/framework",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/dever-main/framework.git",
+            "reference": "d5f2b5c9586d51b8001f78813baf54b620c20e81"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/dever-main/framework/zipball/d5f2b5c9586d51b8001f78813baf54b620c20e81",
+            "reference": "d5f2b5c9586d51b8001f78813baf54b620c20e81",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.0.0"
+        },
+        "time": "2016-05-05 03:02:00",
+        "type": "framework",
+        "installation-source": "source",
+        "autoload": {
+            "files": [
+                "dever.php"
+            ],
+            "psr-0": {
+                "Dever": "src/"
+            }
+        },
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Rabin",
+                "email": "2934170@qq.com"
+            }
+        ],
+        "description": "dever framework",
+        "homepage": "https://github.com/dever-main/framework",
+        "keywords": [
+            "framework",
+            "library"
+        ],
+        "support": {
+            "source": "https://github.com/dever-main/framework/tree/master",
+            "issues": "https://github.com/dever-main/framework/issues"
+        }
+    }
+]

+ 3 - 0
vendor/dever-main/framework/README.md

@@ -0,0 +1,3 @@
+framework
+
+wiki 

+ 25 - 0
vendor/dever-main/framework/composer.json

@@ -0,0 +1,25 @@
+{
+    "name": "dever-main/framework",
+    "type": "framework",
+    "description": "dever framework",
+    "keywords": ["framework","library"],
+    "homepage": "https://github.com/dever-main/framework",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Rabin",
+            "email": "2934170@qq.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.0.0"
+    },
+    "autoload": {
+        "files": [
+            "dever.php"
+        ],
+        "psr-0": {
+            "Dever": "src/"
+        }
+    }
+}

+ 1193 - 0
vendor/dever-main/framework/dever.php

@@ -0,0 +1,1193 @@
+<?php
+
+class Dever extends Dever\Config\Load
+{
+    static private $register = array
+    (
+        'path'      => array('File\\Path','create'),
+
+        'page'      => array('Page\\Main','getPage'),
+        'total'     => array('Page\\Main','getTotal'),
+        'html'     => array('Page\\Main','getHtml'),
+
+        'url'       => array('Http\\Url','get'),
+        'location'  => array('Http\\Url','location'),
+        'input'     => array('Http\\Input','get'),
+        'preInput'  => array('Http\\Input','prefix'),
+        'setInput'  => array('Http\\Input','set'),
+        'abert'     => array('Http\\Output','abert'),
+        'out'       => array('Http\\Output','result'),
+        'export'    => array('Http\\Output','export'),
+        'pageInfo'    => array('Http\\Output','page'),
+
+        'load'      => array('Routing\\Load','get'),
+        'object'    => array('Routing\\Load','object'),
+        'setStep'    => array('Routing\\Step','set'),
+        'getStep'    => array('Routing\\Step','get'),
+
+        'config'    => array('Config\\Load','get'),
+        'project'   => array('Config\\Project','load'),
+
+        'debug'   => array('Debug\\Process','wait'),
+
+        'view'   => array('Template\\View','get'),
+        'render'   => array('Template\\View','html'),
+        
+        'token'   => array('Security\\Api','get'),
+        'login'   => array('Security\\Api','login'),
+
+        'rule'  => array('Security\\String','rule'),
+        'idtostr'  => array('Security\\String','idtostr'),
+        'strtoid'  => array('Security\\String','strtoid'),
+
+        'tcp'  => array('Server\\Swoole','getInstance'),
+    );
+    
+    static public $markdown;
+
+    static public $save;
+
+    /**
+     * 设置循环里每行不同的值
+     * @param string $value
+     * @param string $index
+     *
+     * @return array
+     */
+    static public function lace($value, $index, $key = 2, $num = 0)
+    {
+        $value = explode(',', $value);
+        if(!isset($value[1]))
+        {
+            $value[1] = '';
+        }
+
+        if($index > 0 && $index%$key == $num)
+        {
+            return $value[0];
+        }
+        else
+        {
+            return $value[1];
+        }
+    }
+
+    /**
+     * 设置循环里最新一条数据的值
+     * @param string $value
+     * @param string $index
+     *
+     * @return array
+     */
+    static public function first($value, $index)
+    {
+        if($index == 0)
+        {
+            return $value;
+        }
+    }
+
+    /**
+     * 设置循环里最后一条数据的值
+     * @param string $value
+     * @param string $index
+     * @param string $total
+     *
+     * @return array
+     */
+    static public function last($value, $index, $total)
+    {
+        if($index == $total)
+        {
+            return $value;
+        }
+    }
+
+    /**
+     * 除了最后一条
+     * @param string $value
+     * @param string $index
+     * @param string $total
+     *
+     * @return array
+     */
+    static public function other($value, $index, $total)
+    {
+        if($index != $total)
+        {
+            return $value;
+        }
+    }
+
+    /**
+     * 对多维数组进行排序
+     * @param string $array
+     * @param string $field
+     * @param string $desc
+     *
+     * @return array
+     */
+    private function sort(&$array, $field, $desc = false)
+    {
+        $fieldArr = array();
+        foreach ($array as $k => $v)
+        {
+            $fieldArr[$k] = $v[$field];
+        }
+        $sort = $desc == false ? SORT_ASC : SORT_DESC;
+        array_multisort($fieldArr, $sort, $array);
+    }
+
+    /**
+     * 生成html a标记 以后统一修改
+     * @param string $name
+     * @param string $link
+     * @param string $target
+     *
+     * @return array
+     */
+    private function a($name, $link, $target = '_self')
+    {
+        return '<a href="'.Dever::url($link).'" target="'.$target.'">'.$name.'</a>';
+    }
+
+    /**
+     * 生成html img标记 以后统一修改
+     * @param string $link
+     * @param string $target
+     *
+     * @return array
+     */
+    private function img($link, $target = '_self')
+    {
+        return Dever::a('<img src="'.$link.'" />', $link, $target);
+    }
+
+    /**
+     * 获取assets的文件网络路径
+     * @param string $value
+     * @param string $type
+     *
+     * @return array
+     */
+    static public function assets($value, $type = 'css')
+    {
+        return parent::$global['host'][$type] . $value;
+    }
+    
+    /**
+     * 生成table
+     * @param string $data
+     * @param string $class
+     *
+     * @return array
+     */
+    static public function table($data, $class = '', $num = 1)
+    {
+        if($class)
+        {
+            $style = 'class='.$class.'';
+        }
+        else
+        {
+            $style = 'border=1 width=100% height=100%';
+        }
+        
+        $html = '<table '.$style.'>';
+        
+        foreach($data as $k => $v)
+        {
+            if(is_array($v) && $num == 2)
+            {
+                $tbody = array($k);
+                foreach($v as $j)
+                {
+                    array_push($tbody, $j);
+                }
+                $html .= self::tbody($tbody);
+            }
+            else
+            {
+                if(is_array($v))
+                {
+                    $v = self::table($v, $class);
+                    //$v = var_export($v, true);
+                }
+                if(is_numeric($k))
+                {
+                    $html .= self::tbody(array($v));
+                }
+                else
+                {
+                    $html .= self::tbody(array($k, $v));
+                }
+            }
+        }
+        
+        $html .= '</table>';
+
+        return $html;
+    }
+    
+    /**
+     * 生成tbody
+     * @param string $data
+     * @param string $class
+     *
+     * @return array
+     */
+    static public function tbody($data)
+    {
+        $html = '<tr>';
+        foreach($data as $k => $v)
+        {
+            if($k == 0)
+            {
+                $html .= '<td style=width:30%;line-height:1.75;font-weight:bold>'.$v.'</td>';
+            }
+            elseif($k == 1)
+            {
+                $html .= '<td style=width:30%;word-break:break-all;word-wrap:break-word;>'.$v.'</td>';
+            }
+            else
+            {
+                $html .= '<td style=word-break:break-all;word-wrap:break-word;>'.$v.'</td>';
+            }
+        }
+        
+        $html .= '</tr>';
+        
+        return $html;
+    }
+
+    /**
+     * 判断是否包含
+     * @param string $value
+     * @param string $source
+     *
+     * @return array
+     */
+    static public function in($value, $index)
+    {
+        $key = $value . '_' . $index;
+        if(isset(self::$global['in'][$key]))
+        {
+            return self::$global['in'][$key];
+        }
+        if(is_array($index))
+        {
+            $index = implode(',', $index);
+        }
+        $index .= ',';
+        if(strpos($value, ','))
+        {
+            $temp = explode(',', $value);
+            foreach($temp as $k => $v)
+            {
+                $state = self::in($v, $index);
+                if($state == true)
+                {
+                    break;
+                }
+            }
+
+            return self::$global['in'][$key] = $state;
+        }
+        else
+        {
+            if(strpos($index, $value . ',') !== false)
+            {
+                return self::$global['in'][$key] = true;
+            }
+            return self::$global['in'][$key] = false;
+        }
+    }
+    
+    /**
+     * pic
+     * @param string $file
+     * @param string $name
+     *
+     * @return array
+     */
+    static public function pic($file, $name = false)
+    {
+        if(strpos($file, ',') !== false)
+        {
+            $temp = explode(',', $file);
+            $file = array();
+            foreach($temp as $k => $v)
+            {
+                $file[$k] = self::pic($v, $name);
+            }
+            return implode(',', $file);
+        }
+
+        if($name && strpos($file, '_') !== false)
+        {
+            $temp = explode('_', $file);
+            $file = $temp[0] . '_' . $name;
+        }
+
+        # 替换host
+        if($file && strpos($file, 'http://') === false)
+        {
+            $host = Dever::$global['host']['image'];
+            if(is_array(Dever::$global['host']['image']))
+            {
+                $index = array_rand(Dever::$global['host']['image']);
+                $host = Dever::$global['host']['image'][$index];
+            }
+            $file = $host . $file;
+        }
+
+        return $file;
+    }
+
+    /**
+     * 获取链接
+     * @param string $url
+     * @param array $param
+     *
+     * @return string
+     */
+    static public function link($url, $param = array(), $project = 'main')
+    {
+        if($param)
+        {
+            $send = array();
+            foreach($param as $k => $v)
+            {
+                if(is_string($k) && $v)
+                {
+                    $send[] = $k.'=' . $v;
+                }
+                elseif($v && $value = Dever::input($v))
+                {
+                    $send[] = $v.'=' . $value;
+                }
+            }
+            if($send)
+            {
+                $url .= '?' . implode('&', $send);
+            }
+        }
+        return Dever::url($url, $project);
+    }
+
+    /**
+     * str_explode
+     * @param string $value
+     * @param string $index
+     *
+     * @return array
+     */
+    static function str_explode($value, $num = 2)
+    {
+        $len = strlen($value);
+        $result = array();
+        for($i = 0; $i < $len; $i=$i+$num)
+        {
+            $result[$i/$num] = substr($value, $i, $num);
+        }
+
+        return $result;
+    }
+    
+    /**
+     * 获取_param
+     * @param string $value
+     * @param string $index
+     *
+     * @return array
+     */
+    static public function param($name)
+    {
+        if(isset(Dever::$global['base']['_param']))
+        {
+            if(isset(Dever::$global['base']['_param']['add_' . $name]))
+            {
+                return Dever::$global['base']['_param']['add_' . $name];
+            }
+            
+            if(isset(Dever::$global['base']['_param']['set_' . $name]))
+            {
+                return Dever::$global['base']['_param']['set_' . $name];
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * 获取ip
+     *
+     * @return string
+     */
+    static public function ip()
+    {
+        $ip = '';
+        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown'))
+        {
+            $ip = getenv('HTTP_CLIENT_IP');
+        }
+        elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown'))
+        {
+            $ip = getenv('HTTP_X_FORWARDED_FOR');
+        }
+        elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown'))
+        {
+            $ip = getenv('REMOTE_ADDR');
+        }
+        elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown'))
+        {
+            $ip = $_SERVER['REMOTE_ADDR'];
+        }
+        return preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
+    }
+    
+    /**
+     * 获取ua
+     *
+     * @return string
+     */
+    static public function ua()
+    {
+        return $_SERVER['HTTP_USER_AGENT'];
+    }
+
+    /**
+     * kill
+     *
+     * @return string
+     */
+    static public function kill($commend)
+    {
+        $shell = "ps -ef | grep ".$commend." | grep -v grep | awk '{print $2}' | xargs kill -9";
+
+        self::run($shell, '');
+    }
+
+    /**
+     * 运维程序
+     *
+     * @return string
+     */
+    static public function daemon($interface, $project = false, $file = 'index.php', $state = false)
+    {
+        if(strpos($interface, 'http://') !== false)
+        {
+            return self::run('curl "' . $interface . '"');
+        }
+        $project = $project ? $project : DEVER_APP_NAME;
+        $path = self::load('manage/project.setup', $project);
+
+        if(strpos($path, 'http://') !== false)
+        {
+            //self::curl($path . $interface);
+            return self::run('curl "' . $path . $interface . '"');
+        }
+        else
+        {
+            # ?和&无法解析
+            $interface = str_replace(array('?', '&'), array('__', '^'), $interface);
+            return self::run('php ' . $path . $file . ' -send ' . $interface, $state);
+        }
+    }
+    
+    /**
+     * shell
+     *
+     * @return string
+     */
+    static public function run($shell, $state = false, $method = 'system')
+    {
+        if($state === false)
+        {
+            $state = ' > /dev/null &';
+        }
+        $method($shell . $state, $result);
+        
+        return $result;
+    }
+
+    /**
+     * process
+     *
+     * @return string
+     */
+    static public function process($commend, $count = false)
+    {
+        $shell = "ps -ef | grep ".$commend." | grep -v grep";
+
+        if($count)
+        {
+            $shell .= ' | grep "master" | wc -l';
+        }
+
+        $result = self::run($shell, '', 'system');
+
+        if($result != 1)
+        {
+            return $result;
+        }
+
+        return false;
+    }
+
+    static public function mdate($num, $type = 1)
+    {
+        $num = time() - $num;
+        
+        if($num <= 0)
+        {
+            if($type == 2)
+            {
+                return '1秒前';
+            }
+            else
+            {
+                return '1S';
+            }
+        }
+
+        $config = array
+        (
+            array(31536000, 'Y', '年'),
+            array(2592000, 'T', '个月'),
+            array(604800, 'W', '星期'),
+            array(86400, 'D', '天'),
+            array(3600, 'H', '小时'),
+            array(60, 'M', '分钟'),
+            array(1, 'S', '秒')
+        );
+
+        if($type == 2)
+        {
+            foreach($config as $k => $v)
+            {
+                $value = intval($num/$v[0]);
+                
+                if($value != 0) 
+                {
+                    return $value . $v[2] . '前';
+                }
+            }
+            
+            return '';
+        }
+        else
+        {
+            $result = '';
+            
+            foreach($config as $k => $v)
+            {
+                if($num > $v[0])
+                {
+                    $value = intval($num/$v[0]);
+                    $num = $num - $v[0]*$value;
+                    $result .= $value . $v[1] . ' ';
+                }
+            }
+            
+            return $result;
+        }
+    }
+
+    /**
+     * 加入到cron中
+     *
+     * @return string
+     */
+    static public function cron($name, $ldate, $interface, $time = 0, $project = false, $update = true)
+    {
+        if($ldate > 0)
+        {
+            $ldate = date('Y-m-d H:i:s', $ldate);
+        }
+        $info = Dever::load('manage/cron-getOne', array('where_project' => $project, 'where_interface' => $interface));
+        if($info)
+        {
+            if($update)
+            {
+                $update = array();
+                $update['set_name'] = $name;
+                $update['set_ldate'] = $ldate;
+                $update['set_interface'] = $interface;
+                $update['set_time'] = $time;
+                $update['set_project'] = $project;
+                $update['set_state'] = 1;
+                $update['where_id'] = $info['id'];
+
+                Dever::load('manage/cron-update', $update);
+            }
+        }
+        else
+        {
+            $update = array();
+            $update['add_name'] = $name;
+            $update['add_ldate'] = $ldate;
+            $update['add_interface'] = $interface;
+            $update['add_time'] = $time;
+            $update['add_project'] = $project;
+
+            Dever::load('manage/cron-insert', $update);
+        }
+    }
+
+    /**
+     * 字符串截取
+     * @param string $string
+     * @param string $length
+     * @param string $etc
+     *
+     * @return array
+     */
+    static public function cut($string, $length = 80, $etc = '...')
+    {
+        $result = '';
+        $string = html_entity_decode(trim(strip_tags($string)), ENT_QUOTES, 'utf-8');
+        for($i = 0, $j = 0; $i < strlen($string); $i++)
+        {
+            if($j >= $length)
+            {
+                for($x = 0, $y = 0; $x < strlen($etc); $x++)
+                {
+                    if($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0'))
+                    {
+                        $x += $number - 1;
+                        $y++;
+                    }
+                    else
+                    {
+                        $y += 0.5;
+                    }
+                }
+                $length -= $y;
+                break;
+            }
+            if($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0'))
+            {
+                $i += $number - 1;
+                $j++;
+            }
+            else
+            {
+                $j += 0.5;
+            }
+        }
+        for($i = 0; (($i < strlen($string)) && ($length > 0)); $i++)
+        {
+            if($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0'))
+            {
+                if($length < 1.0)
+                {
+                    break;
+                }
+                $result .= substr($string, $i, $number);
+                $length -= 1.0;
+                $i += $number - 1;
+            }
+            else
+            {
+                $result .= substr($string, $i, 1);
+                $length -= 0.5;
+            }
+        }
+        $result = htmlentities($result, ENT_QUOTES, 'utf-8');
+        if($i < strlen($string))
+        {
+            $result .= $etc;
+        }
+        return $result;
+    }
+
+    /**
+     * strlen
+     * @param string $string
+     *
+     * @return array
+     */
+    static public function strlen($string)
+    {
+        preg_match_all("/./us", $string, $match);
+        
+        return count($match[0]);
+    }
+
+    /**
+     * 执行hack的值
+     * @param string $value
+     * @param string $index
+     * @param string $total
+     *
+     * @return array
+     */
+    static public function hack($key)
+    {
+        if(isset(parent::$global['hack'][$key]))
+        {
+            return parent::$global['hack'][$key];
+        }
+    }
+
+    /**
+     * 注册dever类库里的常用类,方便使用
+     * @param string $name
+     * @param array $param
+     *
+     * @return mixed
+     */
+    static public function __callStatic($name, $param = array())
+    {
+        if(isset(self::$register[$name]))
+        {
+            $class = 'Dever\\' . self::$register[$name][0];
+
+            $method = self::$register[$name][1];
+
+            return call_user_func_array(array($class, $method), $param);
+        }
+    }
+    
+    static public function curl($url, $param = false, $type = '', $ip = '', $refer = '')
+    {
+        //初始化
+        $ch = curl_init();
+        //设置选项,包括URL
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+        if($ip)
+        {
+            $headers['CLIENT-IP'] = $ip; 
+            $headers['X-FORWARDED-FOR'] = $ip;
+            $headerArr = array(); 
+            foreach($headers as $n => $v)
+            { 
+                $headerArr[] = $n .':' . $v;  
+            }
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);
+        }
+        if($refer)
+        {
+            curl_setopt($ch, CURLOPT_REFERER, $refer);
+        }
+
+        if($ip || $refer)
+        {
+            curl_setopt($ch, CURLOPT_HEADER, 1);
+        }
+        else
+        {
+            curl_setopt($ch, CURLOPT_HEADER, 0);
+        }
+        
+        
+        if($param)
+        {
+            // post数据
+            curl_setopt($ch, CURLOPT_POST, 1);
+            
+            if($type == 'json')
+            {
+                # 中文不用unicode编码
+                $string = str_replace("\\/", "/", json_encode($param));
+                $search = "#\\\u([0-9a-f]+)#ie";
+             
+                if(strpos(strtoupper(PHP_OS), 'WIN') === false)
+                {
+                    $replace = "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))";//LINUX
+                }
+                else
+                {
+                    $replace = "iconv('UCS-2', 'UTF-8', pack('H4', '\\1'))";//WINDOWS
+                }
+ 
+                $param = preg_replace($search, $replace, $string);
+                //$param = json_encode($param, JSON_UNESCAPED_UNICODE);
+                curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+                    'Content-Type: application/json',
+                    'Content-Length: ' . strlen($param))
+                );
+            }
+            
+            //print_r($param);die;
+            
+            // post的变量
+            @curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
+        }
+
+        //执行并获取HTML文档内容
+        $output = curl_exec($ch);
+        //释放curl句柄
+        curl_close($ch);
+        //打印获得的数据
+        return $output;
+    }
+
+    static public function weixin()
+    { 
+        if(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false)
+        {
+            return true;
+        }
+        return false;
+    }
+    
+    static public function mobile()  
+    {
+        $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP']) ? $_SERVER['ALL_HTTP'] : '';  
+        $mobile_browser = '0';  
+        if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|ipad|ipod|android|xoom)/i', strtolower($_SERVER['HTTP_USER_AGENT'])))
+        {
+            $mobile_browser++;  
+        }
+        if((isset($_SERVER['HTTP_ACCEPT'])) && (strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false))
+        {
+            $mobile_browser++;
+        }
+        if(isset($_SERVER['HTTP_X_WAP_PROFILE']))
+        {
+            $mobile_browser++;
+        }
+        if(isset($_SERVER['HTTP_PROFILE']))
+        {
+            $mobile_browser++;
+        }
+        $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));  
+        $mobile_agents = array(  
+        'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',  
+        'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',  
+        'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',  
+        'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',  
+        'newt','noki','oper','palm','pana','pant','phil','play','port','prox',  
+        'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',  
+        'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',  
+        'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',  
+        'wapr','webc','winw','winw','xda','xda-'
+        );  
+        if(in_array($mobile_ua, $mobile_agents)) 
+        {
+            $mobile_browser++;  
+        }
+        if(strpos(strtolower($_SERVER['ALL_HTTP']), 'operamini') !== false)
+        {
+            $mobile_browser++;
+        }
+        // Pre-final check to reset everything if the user is on Windows  
+        if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
+        { 
+            $mobile_browser=0;
+        }
+        // But WP7 is also Windows, with a slightly different characteristic  
+        if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows phone') !== false)
+        {
+            $mobile_browser++;
+        }
+        if($mobile_browser>0)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    static public function maketime($v)
+    {
+        if(!$v) return '';
+        
+        if(is_numeric($v)) return $v;
+
+        if(is_array($v))
+        {
+            $v = $v[1];
+        }
+        
+        if(strstr($v, ' '))
+        {
+            $t = explode(' ', $v);
+            $v = $t[0];
+            $s = explode(':', $t[1]);
+        }
+        else
+        {
+            $s = array(0,0,0);
+        }
+        
+        if(strstr($v, '-'))
+        {
+            $t = explode('-', $v);
+        }
+        elseif(strstr($v, '/'))
+        {
+            $u = explode('/', $v);
+            $t[0] = $u[2];
+            $t[1] = $u[0];
+            $t[2] = $u[1];
+        }
+        
+        if(!isset($t))
+        {
+            $t = array(0,0,0);
+        }
+        
+        $v = mktime($s[0], $s[1], $s[2], $t[1], $t[2], $t[0]);
+
+        return $v;
+    }
+    
+    /**
+     * 生成随机码
+     */ 
+    static function code($num = 4)
+    {
+        $codes = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        $code="";
+        for($i=1;$i<=$num;$i++)
+        {
+            $code.=$codes{rand(0,61)};
+        }
+        return $code;
+    }
+    
+    static function proxy($method = false, $param = false)
+    {
+        if($method)
+        {
+            if(isset(Dever::$global['host']['proxy']) && Dever::$global['host']['proxy'])
+            {
+                $method = urlencode($method);
+                return Dever::url(Dever::$global['host']['proxy'] . 'proxy_method=' . $method . '&' . $param);
+            }
+            return Dever::url($method . '?' . $param);
+        }
+        $data = Dever::input();
+        
+        foreach($data as $k => $v)
+        {
+            Dever::setInput($k, $v);
+        }
+        
+        return Dever::load(urldecode($data['proxy_method']), array('CHECK' => true));
+    }
+    
+    static public function script()
+    {
+        $script = 'var config={};config.host="'.Dever::url('').'";config.type="'.Dever\Routing\Uri::$type.'";config.current="'.Dever::url().'";config.upload="'.Dever::$global['host']['upload'].'";config.assets="'.Dever::$global['host']['core'].'";';
+
+        if(isset(Dever::$global['host']['proxy']))
+        {
+            $script .= 'config.proxy="'.Dever::$global['host']['proxy'].'";';
+        }
+        if(isset(Dever::$global['host']['manage']))
+        {
+            $script .= 'config.manage_assets="'.Dever::$global['host']['manage'].'";';
+        }
+        if(isset(Dever::$global['host']['workspace']))
+        {
+            $script .= 'config.workspace="'.Dever::$global['host']['workspace'].'";';
+        }
+        if(isset(Dever::$global['base']['layout']))
+        {
+            $script .= 'config.layout = "'.Dever::$global['base']['layout'].'";$(document).ready(function()
+                        {
+                            $(document).pjax("a", "'.Dever::$global['base']['layout'].'");
+
+                            $(document).on("submit", "#form1", function (event) {event.preventDefault();$.pjax.submit(event, "'.Dever::$global['base']['layout'].'", {"push": true, "replace": false, timeout:6000, "scrollTo": 0, maxCacheLength: 0});});
+
+                            $(document).on("pjax:start", function()
+                            {
+                                NProgress.start();
+                            });
+                            $(document).on("pjax:end", function()
+                            {
+                                NProgress.done();
+                            });
+                        });';
+        }
+        return $script;
+    }
+
+    /**
+     * 获取文件后缀
+     * @param string $file
+     *
+     * @return string
+     */
+    static public function ext($file)
+    {
+        return pathinfo($file, PATHINFO_EXTENSION);
+    }
+    
+    /**
+     * markdown解析
+     * @param string $value
+     *
+     * @return string
+     */
+    static public function markdown($value)
+    {
+        self::$markdown = self::$markdown ? self::$markdown : new \Parsedown();
+        
+        # 一个回车就换行
+        self::$markdown->setBreaksEnabled(true);
+        
+        # 过滤掉所有特殊代码
+        return self::$markdown->text($value);
+    }
+    
+    /**
+     * setup 安装引导程序
+     * @param string $value
+     *
+     * @return string
+     */
+    static public function setup()
+    {
+        $host = DEVER_APP_HOST;
+        
+        $path = DEVER_APP_PATH . '../';
+        
+        $dir = scandir($path);
+    
+        foreach($dir as $k => $v)
+        {
+            if($v != '.' && $v != '..' && is_dir($path . $v))
+            {
+                $url = str_replace(array('www', 'main'), $v, $host);
+                
+                Dever::curl($url);
+
+                echo $url . ' 安装成功!<br />' . "\r\n";
+            }
+        }
+        
+        return '感谢您使用Dever!';
+    }
+
+    /**
+     * cache 缓存功能
+     * @param string $key
+     * @param array $data
+     * @param int $expire
+     * @param string $type
+     *
+     * @return mixed
+     */
+    static public function cache($key = false, $data = false, $expire = 0, $type = 'data')
+    {
+        $cache = self::$global['cache'];
+        if(empty($cache[$type]))
+        {
+            return;
+        }
+        //$handle =& \Dever\Cache\Handle::getInstance($type, $cache[$type]);
+        $handle = \Dever\Cache\Handle::getInstance($type, $cache[$type]);
+
+        if(is_string($data) && $data == 'delete')
+        {
+            return $handle->delete($key);
+        }
+        elseif($data)
+        {
+            return $handle->set($key, $data, $expire);
+        }
+        return $handle->get($key);
+    }
+
+     /**
+     * dyna 动态解析功能
+     * @param string $key
+     * @param array $data
+     *
+     * @return mixed
+     */
+    static public function odyna($key = false, $data = array())
+    {
+        return (object)self::dyna($key, $data);
+    }
+
+    /**
+     * dyna 动态解析功能
+     * @param string $key
+     * @param array $data
+     *
+     * @return mixed
+     */
+    static public function dyna($key = false, $data = array())
+    {
+        if(isset(self::$global['dyna_data'][$key]))
+        {
+            return self::$global['dyna_data'][$key];
+        }
+        $config = self::get('dyna');
+        if(empty($config[$key]))
+        {
+            return $key;
+        }
+        if(!$data)
+        {
+            return $config[$key];
+        }
+
+        if(is_array($config[$key]))
+        {
+            foreach($config[$key] as $k => $v)
+            {
+                $v = '$value = "'.$v.'";';
+                eval($v);
+                if(isset($value))
+                {
+                    $config[$key][$k] = $value;
+                }
+            }
+        }
+        else
+        {
+            $v = '$value = "'.$config[$key].'";';
+            eval($v);
+            if(isset($value))
+            {
+                $config[$key] = $value;
+            }
+        }
+
+        self::$global['dyna_data'][$key] = $config[$key];
+        
+        return $config[$key];
+    }
+
+    /**
+     * submit 处理重复提交功能 此处暂时有问题
+     * @param string $type
+     * @param int $value
+     *
+     * @return mixed
+     */
+    static public function submit($type = 'update', $value = 1)
+    {
+        if(empty(self::$save))
+        {
+            self::$save = new \Dever\Session\Save(DEVER_APP_NAME, 'cookie');
+        }
+        
+        if($type == 'check')
+        {
+            $submit = self::$save->get('submit');
+
+            if($submit == 2)
+            {
+                Dever::abert('请不要重复提交');
+            }
+        }
+
+        if($value)
+        {
+            self::$save->add('submit', $value);
+        }
+    }
+}

+ 210 - 0
vendor/dever-main/framework/src/Dever/Cache/Handle.php

@@ -0,0 +1,210 @@
+<?php namespace Dever\Cache;
+
+use Dever\Config\Load as Config;
+use Dever\Cache\Store;
+use Dever\Http\Input;
+use Dever\Debug\Process as Debug;
+
+class Handle
+{
+    /**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * store
+     *
+     * @var object
+     */
+    protected $store;
+
+    /**
+     * config
+     *
+     * @var array
+     */
+    protected $config;
+
+    /**
+     * expire
+     *
+     * @var int
+     */
+    protected $expire;
+
+    /**
+     * type
+     *
+     * @var string
+     */
+    protected $type;
+
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Cache\Handle;
+     */
+    static public function getInstance($type = 'mysql', $expire = 3600)
+    {
+        if(empty(self::$instance[$type]))
+        {
+            self::$instance[$type] = new self($expire, $type);
+        }
+
+        return self::$instance[$type];
+    }
+
+    public function __construct($expire = 3600, $type = 'mysql')
+    {
+        $this->expire = $expire;
+        $this->type = $type;
+    }
+
+    public function store($key)
+    {
+        if($this->store)
+        {
+            return;
+        }
+
+        if(!$this->config)
+        {
+            $this->config = Config::$global['cache'];
+        }
+
+        $class = 'Dever\\Cache\\Store\\' . ucfirst($this->config['type']);
+        $this->store = new $class();
+
+        $this->log('connect', $this->config['type']);
+
+        foreach($this->config['store'] as $k => $v)
+        {
+            if(empty($v['expire']))
+            {
+                $v['expire'] = $this->expire;
+            }
+            $this->store->connect($v);
+        }
+    }
+
+    /**
+     * get
+     *
+     * @return mixd
+     */
+    public function get($key)
+    {
+        $this->store($key);
+        $param = isset($this->config['clear']) ? $this->config['clear'] : 'dever_cache';
+        if(Input::get($param) == 'clear')
+        {
+            //$this->delete($key);
+            return false;
+        }
+        $data = $this->store->get($key);
+        //$data = json_decode(base64_decode($data), true);
+        $this->log('get', $key, $data, $this->expire($key));
+        return $data;
+    }
+
+    /**
+     * set
+     *
+     * @return mixd
+     */
+    public function set($key, $value, $expire = 0)
+    {
+        $this->store($key);
+        $this->init($key, $expire);
+        $this->log('set', $key, $value, $expire);
+        //$value = base64_encode(json_encode($value));
+        return $this->store->set($key, $value, $expire);
+    }
+
+    /**
+     * delete
+     *
+     * @return mixd
+     */
+    public function delete($key)
+    {
+        $this->store($key);
+        $this->log('delete', $key, 1);
+        return $this->store->delete($key);
+    }
+
+    /**
+     * init
+     *
+     * @return mixed
+     */
+    protected function init($key, &$expire)
+    {
+        if(isset($this->config[$this->type . '_key']))
+        {
+            foreach($this->config[$this->type . '_key'] as $k => $v)
+            {
+                if(strpos($key, $k) !== false)
+                {
+                    $expire = $v;
+                }
+            }
+        }
+
+        $this->expire($key, ($expire > 0 ? $expire : $this->expire));
+    }
+
+    /**
+     * expire
+     *
+     * @return mixed
+     */
+    protected function expire($key, $expire = false)
+    {
+        if(isset($this->config['expire']) && $this->config['expire'])
+        {
+            $key .= '_expire';
+            if($expire > 0)
+            {
+                $expire = $expire*2;
+                $this->store->set($key, DEVER_TIME + $expire, $expire);
+            }
+            else
+            {
+                $expire = $this->store->get($key);
+                if($expire)
+                {
+                    $num = $expire - DEVER_TIME;
+                    return '将于' . date('Y-m-d H:i:s', $expire) . '失效('.$num.'s)';
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * log
+     *
+     * @return mixed
+     */
+    protected function log($method, $key = false, $value = false, $expire = 0)
+    {
+        $expire = $expire ? $expire : $this->expire;
+        $log = array();
+        $log['method'] = $method;
+        $log['key'] = $key;
+        if($value)
+        {
+            $log['value'] = $value;
+        }
+        if($expire >= 0)
+        {
+            $log['expire'] = $expire;
+        }
+        Debug::log($log, 'cache');
+    }
+}

+ 11 - 0
vendor/dever-main/framework/src/Dever/Cache/Store.php

@@ -0,0 +1,11 @@
+<?php namespace Dever\Cache;
+
+interface Store
+{
+	public function __construct();
+	public function connect($config);
+	public function get($key);
+	public function set($key, $value, $expire);
+	public function delete($key);
+	public function close();
+}

+ 97 - 0
vendor/dever-main/framework/src/Dever/Cache/Store/Memcache.php

@@ -0,0 +1,97 @@
+<?php namespace Dever\Cache\Store;
+
+use Dever\Cache\Store;
+
+class Memcache implements Store
+{
+	private $class;
+	private $expire;
+
+	public function __construct()
+	{
+		if(class_exists('\Memcached'))
+		{
+			$this->class = new \Memcached;
+		}
+		else
+		{
+			$this->class = new \Memcache;
+		}
+	}
+
+	public function connect($config)
+	{
+		if(isset($config["host"]))
+		{
+			$this->expire = $config['expire'];
+
+			$this->class->addServer($config["host"], $config["port"], $config["weight"]);
+		}
+	}
+
+	public function get($key)
+	{
+		if(!$this->class) return false;
+
+		$key = $this->key($key);
+		
+		$result = $this->class->get($key);
+		
+		return $result;
+	}
+
+	public function set($key, $value, $expire = 0)
+	{
+		if(!$this->class) return false;
+
+		if(!is_string($key))
+		{
+			return false;
+		}
+		
+		$key = $this->key($key);
+
+		$expire = $expire > 0 ? $expire : $this->expire;
+
+		if(!class_exists('\Memcached'))
+		{
+			$result = $this->class->set($key, $value, MEMCACHE_COMPRESSED, $expire);
+		}
+		else
+		{
+			$result = $this->class->set($key, $value, $expire);
+		}
+		
+		return $result;
+	}
+
+	public function delete($key)
+	{
+		if(!$this->class) return false;
+
+		$key = $this->key($key);
+
+		if($this->class->delete($key, 0))
+		{
+			return true;
+		}
+		return false;
+	}
+
+	public function close()
+	{
+		if(!$this->class) return false;
+
+		if($this->class->close())
+		{
+			return true;
+		}
+		return false;
+	}
+
+	private function key($key)
+	{
+		return '_' . $key;
+		return DEVER_APP_NAME . '_' . $key;
+	}
+}

+ 83 - 0
vendor/dever-main/framework/src/Dever/Cache/Store/Redis.php

@@ -0,0 +1,83 @@
+<?php namespace Dever\Cache\Store;
+
+use Dever\Cache\Store;
+
+class Ris implements Store
+{
+	private $class;
+	private $expire;
+
+	public function __construct()
+	{
+		$this->class = new \Redis;
+	}
+
+	public function connect($config)
+	{
+		if(isset($config["host"]))
+		{
+			$this->expire = $config['expire'];
+
+			$this->class->addServer($config["host"], $config["port"], $config["weight"]);
+		}
+	}
+
+	public function get($key)
+	{
+		if(!$this->class) return false;
+
+		$key = $this->key($key);
+		
+		$result = $this->class->get($key);
+		
+		return $result;
+	}
+
+	public function set($key, $value, $expire = 0)
+	{
+		if(!$this->class) return false;
+
+		if(!is_string($key))
+		{
+			return false;
+		}
+		
+		$key = $this->key($key);
+
+		$expire = $expire > 0 ? $expire : $this->expire;
+
+		$result = $this->class->set($key, $value, $expire);
+		
+		return $result;
+	}
+
+	public function delete($key)
+	{
+		if(!$this->class) return false;
+
+		$key = $this->key($key);
+
+		if($this->class->delete($key, 0))
+		{
+			return true;
+		}
+		return false;
+	}
+
+	public function close()
+	{
+		if(!$this->class) return false;
+
+		if($this->class->close())
+		{
+			return true;
+		}
+		return false;
+	}
+
+	private function key($key)
+	{
+		return '_' . $key;
+		return DEVER_APP_NAME . '_' . $key;
+	}
+}

+ 54 - 0
vendor/dever-main/framework/src/Dever/Check/Load.php

@@ -0,0 +1,54 @@
+<?php namespace Dever\Check;
+
+use Dever\Routing\Load as Route;
+class Load
+{
+    /**
+     * object
+     *
+     * @var object
+     */
+    static public $object;
+
+    /**
+     * __construct
+     * @param object $class
+     *
+     * @return mixed
+     */
+    public function __construct($class)
+    {
+        if(is_string($class))
+        {
+            $class = Route::get($class . '.');
+        }
+
+        $this->object = new \ReflectionClass($class);
+    }
+
+    /**
+     * get
+     * @param object $class
+     *
+     * @return mixed
+     */
+	static public function get($class)
+	{
+        $class = new self($class);
+
+        return $class;
+	}
+
+    /**
+     * code
+     * @param string $method
+     *
+     * @return mixed
+     */
+    public function code($method)
+    {
+        $return = $this->object->getmethod($method);
+
+        return $return;
+    }
+}

+ 41 - 0
vendor/dever-main/framework/src/Dever/Config/Lang.php

@@ -0,0 +1,41 @@
+<?php namespace Dever\Config;
+
+use Dever\Config\Load as Config;
+
+class Lang
+{
+	/**
+     * get
+     * @param string $type
+     *
+     * @return array
+     */
+	static public function get($key = 'host', $param = '')
+	{
+		$name = 'lang/' . Config::$global['base']['lang'];
+		Config::get($name);
+
+		if(isset(Config::$global[$name][$key]))
+		{
+			if($param)
+			{
+				if(is_string($param))
+				{
+					$param = array($param);
+				}
+				foreach($param as $k => $v)
+				{
+					$k = '{' . $k . '}';
+					if(strpos(Config::$global[$name][$key], $k) !== false)
+					{
+						Config::$global[$name][$key] = str_replace($k, $v, Config::$global[$name][$key]);
+					}
+				}
+			}
+
+			return Config::$global[$name][$key];
+		}
+
+		return $key;
+	}
+}

+ 209 - 0
vendor/dever-main/framework/src/Dever/Config/Load.php

@@ -0,0 +1,209 @@
+<?php namespace Dever\Config;
+
+use Dever\Config\Lang;
+use Dever\Http\Output;
+
+class Load
+{
+    /**
+     * env
+     *
+     * @var const string
+     */
+    const ENV = 'env';
+
+    /**
+     * global
+     *
+     * @var array
+     */
+    static public $global;
+
+    /**
+     * object
+     *
+     * @var object
+     */
+    static public $object;
+
+    /**
+     * init
+     *
+     * @return mixed
+     */
+    static public function init()
+    {
+        self::get('base');
+    }
+
+    /**
+     * get
+     * @param string $name
+     * @param string $path
+     * @param string $project
+     *
+     * @return mixed
+     */
+    static public function get($name = 'host', $project = '', $path = 'config')
+    {
+        self::server();
+
+        if($project)
+        {
+            $index = $project . '_' . $path . '_' . $name;
+        }
+        else
+        {
+            $index = $name;
+        }
+
+        if(empty(self::$global[$index]))
+        {
+            $root = DEVER_APP_PATH;
+            $name = DEVER_APP_NAME;
+            if($project)
+            {
+                $project = Project::load($project);
+                $root = $project['path'];
+                $name = $project['name'];
+            }
+
+            $config = array(DEVER_PATH, $root);
+            //$config = array(DEVER_PATH, $root, DEVER_PATH . 'data/' . $project . '/');
+
+            self::$global[$index] = array();
+
+            foreach($config as $k => $v)
+            {
+                self::assign($name, $v . $path . '/', $index);
+            }
+
+            if($name != $index)
+            {
+                self::$global[$name] = self::$global[$index];
+            }
+        }
+
+        if(empty(self::$global[$index]))
+        {
+            Output::abert('file_exists', $name);
+        }
+        
+        return self::$global[$index];
+    }
+
+    /**
+     * object
+     * @param string $name
+     *
+     * @var array
+     */
+    static private function object($name, $project = '', $path = 'config')
+    {
+        if($project)
+        {
+            $index = $project . '_' . $path . '_' . $name;
+        }
+        else
+        {
+            $index = $name;
+        }
+
+        if(isset(self::$object[$index]))
+        {
+            return self::$object[$index];
+        }
+
+        self::$object[$index] = (object) self::$global[$index];
+
+        if($name != $index)
+        {
+            self::$object[$name] = self::$object[$index];
+        }
+
+        return self::$object[$index];
+    }
+
+    /**
+     * server
+     *
+     * @var mixed
+     */
+    static private function server()
+    {
+        if(empty($_SERVER['DEVER_SERVER']))
+        {
+            if(isset($_SERVER['SERVER_NAME']))
+            {
+                $_SERVER['DEVER_SERVER'] = $_SERVER['SERVER_NAME'];
+            }
+            else
+            {
+                $_SERVER['DEVER_SERVER'] = 'localhost';
+            }
+        }
+
+        if(strpos($_SERVER['DEVER_SERVER'], '*.') !== false)
+        {
+            $_SERVER['DEVER_SERVER'] = str_replace('*.', '', $_SERVER['DEVER_SERVER']);
+        }
+    }
+
+    /**
+     * env
+     * @param string $name
+     * @param string $path
+     * @param string $index
+     *
+     * @var array
+     */
+    static private function env($name, $path, $index)
+    {
+        $config[] = 'default';
+        if($name != 'base')
+        {
+            $config[] = $name;
+        }
+        foreach($config as $k => $v)
+        {
+            self::assign($v, $path . self::ENV . '/' . $_SERVER['DEVER_SERVER'] . '/', $index);
+        }
+    }
+
+    /**
+     * assign
+     * @param string $name
+     * @param string $path
+     * @param string $index
+     *
+     * @var array
+     */
+    static private function assign($name, $path, $index)
+    {
+        $file = $path . $name . '.php';
+
+        if(is_file($file))
+        {
+            if($name == 'base')
+            {
+                self::env($name, $path, $index);
+            }
+            $config = include($file);
+            
+            if(is_array($config))
+            {
+                self::$global[$index] = array_merge(self::$global[$index], $config);
+            }
+        }
+    }
+
+    /**
+     * env
+     *
+     * @var string
+     */
+    static public function data()
+    {
+        return isset(self::$global['base']['data']) ? self::$global['base']['data'] : DEVER_PATH . 'data/';
+    }
+}

+ 166 - 0
vendor/dever-main/framework/src/Dever/Config/Project.php

@@ -0,0 +1,166 @@
+<?php namespace Dever\Config;
+
+use Dever\Http\Url;
+use Dever\Config\Load as Config;
+
+class Project
+{
+	static private $content;
+
+	static private $alias;
+
+	static public function content($update = false)
+	{
+		$file = Config::data() . 'project/' . DEVER_PROJECT . '.php';
+		
+		if(self::$content && $update == false)
+		{
+			return $file;
+		}
+
+		self::$content = $poject = $alias = array();
+		
+		if(is_file($file))
+		{
+			require $file;
+
+			self::$content = $project;
+
+			self::$alias = $alias;
+		}
+
+		return $file;
+	}
+
+	static public function register()
+	{
+		$file = self::content();
+
+		if(empty(self::$content[DEVER_APP_NAME]))
+		{
+			self::init();
+
+			file_put_contents($file, '<?php $project = ' . var_export(self::$content, true) . ';$alias = ' . self::getAlias() . ';');
+			
+			# 加入后台菜单
+			if(self::load('manage') && \Dever\Routing\Load::get('manage/auth.data'))
+			{
+				\Dever\Routing\Load::get('manage/menu.load');
+			}
+		}
+		elseif(isset(self::$content[DEVER_APP_NAME]) && self::$content[DEVER_APP_NAME]['path'] != DEVER_APP_PATH && isset(Load::$global['host']['base']) && Load::$global['host']['base'])
+		{
+			self::update(DEVER_APP_NAME, 'path', DEVER_APP_PATH);
+			self::update(DEVER_APP_NAME, 'url', Load::$global['host']['base']);
+			if(defined('DEVER_APP_SETUP'))
+			{
+				self::update(DEVER_APP_NAME, 'setup', DEVER_APP_SETUP);
+			}
+			self::content(true);
+			//\Dever\Http\Output::abert('project_already_exists', DEVER_APP_NAME);
+		}
+	}
+
+	static private function init()
+	{
+		self::$content[DEVER_APP_NAME] = array
+		(
+			'name' => DEVER_APP_NAME,
+			'path' => DEVER_APP_PATH,
+			'url' => Load::$global['host']['base'],
+			'lang' => defined('DEVER_APP_LANG') ? DEVER_APP_LANG : DEVER_APP_NAME, 
+			'order' => defined('DEVER_APP_ORDER') ? DEVER_APP_ORDER : 1, 
+			'lib' => defined('DEVER_APP_LIB') ? DEVER_APP_LIB : DEVER_APP_NAME,
+			'icon' => defined('DEVER_APP_ICON') ? DEVER_APP_ICON : ''
+		);
+		
+		if(defined('DEVER_APP_SETUP'))
+		{
+			self::$content[DEVER_APP_NAME]['setup'] = DEVER_APP_SETUP;
+		}
+
+		if(defined('DEVER_INCLUDE_PATH'))
+		{
+			self::$content[DEVER_APP_NAME]['base'] = DEVER_INCLUDE_PATH;
+
+			$path = DEVER_APP_PATH;
+			$base = DEVER_INCLUDE_PATH;
+			if(strstr(DEVER_APP_PATH, DEVER_PATH))
+			{
+				$path = str_replace(DEVER_PATH, '', DEVER_APP_PATH);
+			}
+			elseif(strstr(DEVER_APP_PATH, Load::$global['base']['path']))
+			{
+				$temp = explode(Load::$global['base']['path'], DEVER_APP_PATH);
+				$base = $temp[0];
+				$path = $temp[1];
+			}
+			self::$content[DEVER_APP_NAME]['rel'] = $path;
+		}
+
+		self::setAlias();
+	}
+
+	static private function getAlias()
+	{
+		$alias = array();
+		if(self::$alias)
+		{
+			$alias = str_replace(array("'$", "',"), array("$", ","), var_export(self::$alias, true));
+		}
+		else
+		{
+			$alias = var_export(self::$alias, true);
+		}
+
+		return $alias;
+	}
+
+	static private function setAlias()
+	{
+		foreach(self::$content as $k => $v)
+		{
+			if($v['lib'] != $k)
+			{
+				self::$alias[$v['lib']] = '$project["'.$k.'"]';
+			}
+		}
+	}
+
+	static public function update($key, $index, $value)
+	{
+		$file = self::content();
+
+		if(isset(self::$content[$key]))
+		{
+			self::$content[$key][$index] = $value;
+
+			file_put_contents($file, '<?php $project = ' . var_export(self::$content, true) . ';');
+		}
+	}
+
+	static public function read()
+	{
+		return self::$content;
+	}
+
+	static public function load($project)
+	{
+		$config = false;
+		if(isset(self::$content[$project]))
+		{
+			$config = self::$content[$project];
+		}
+		elseif(isset(self::$alias[$project]))
+		{
+			$config = self::$alias[$project];
+		}
+
+		if($config && isset(Config::$global['host']['project'][$project]))
+		{
+			array_merge($config, Config::$global['host']['project'][$project]);
+		}
+
+		return $config;
+	}
+}

+ 51 - 0
vendor/dever-main/framework/src/Dever/Data/Migration.php

@@ -0,0 +1,51 @@
+<?php namespace Dever\Data;
+
+use Dever;
+
+class Migration
+{
+    protected $num;
+    protected $class;
+    protected $method;
+    protected $type;
+
+    public function __construct($num = 1000)
+    {
+        $this->num = $num;
+    }
+
+    public function action($class, $method, $type, $num = false)
+    {
+        $limit = 0;
+        $this->num = $num > 0 ? $num : $this->num;
+        $this->class = $class;
+        $this->method = $method;
+        $this->type = $type;
+        while($this->handle($limit, $this->num))
+        {
+            $limit += $num;
+        }
+
+        return $limit;
+    }
+
+    private function handle($limit, $num)
+    {
+        $param['limit'] = array($num, $limit);
+
+        $data = Dever::load($this->type, $param);
+
+        if(!$data)
+        {
+            return false;
+        }
+
+        $method = $this->method;
+        foreach($data as $k => $v)
+        {
+            $this->class->$method($v);
+        }
+
+        return true;
+    }
+}

+ 1422 - 0
vendor/dever-main/framework/src/Dever/Data/Model.php

@@ -0,0 +1,1422 @@
+<?php namespace Dever\Data;
+
+use Dever\Debug\Process as Debug;
+use Dever\Config\Load as Config;
+use Dever\Http\Output;
+use Dever\Http\Input;
+use Dever\Routing\Load;
+use Dever\Config\Project;
+
+class Model
+{
+	/**
+     * database
+     *
+     * @var array
+     */
+	protected $database;
+
+	/**
+     * config
+     *
+     * @var array
+     */
+	protected $config;
+
+	/**
+     * index
+     *
+     * @var string
+     */
+	protected $index;
+
+	/**
+     * key
+     *
+     * @var string
+     */
+	protected $key;
+
+	/**
+     * db
+     *
+     * @var Object
+     */
+	protected $db;
+
+	/**
+     * __construct
+     *
+     * @return mixd
+     */
+	public function __construct($config, $index = '')
+	{
+		$this->config = $config;
+
+		$this->database = Config::$global['database'];
+
+		$this->index = $index;
+	}
+
+	/**
+     * key
+     *
+     * @return mixd
+     */
+	protected function key($key = '')
+	{
+		$this->key = $key ? $key : (isset($this->config['project']) ? $this->config['project'] : DEVER_APP_NAME);
+
+		return $this->key;
+	}
+
+	/**
+     * db
+     *
+     * @return mixd
+     */
+	protected function db($key = '')
+	{
+		$key = $this->key($key);
+		
+		$this->checkDatabase($key);
+
+		if(empty($this->db[$key]))
+		{
+			//$this->config['name'] = $key . '_' . $this->config['name'];
+			
+			$method = 'Dever\\Data\\' . ucwords($this->database[$key]['type']) . '\\Store';
+
+			if(isset($this->config['cache']) && !$this->index)
+			{
+				$this->database[$key]['cache']['mysql'] = $this->config['cache'];
+			}
+			$this->db[$key] = new $method($this->database[$key]);
+
+			if(isset($this->config['struct']))
+			{
+				$this->db[$key]->table($key . '_' . $this->config['name'], $this->index);
+			
+				$this->create($key);
+			}
+			else
+			{
+				$this->db[$key]->table($this->config['name'], $this->index, false);
+			}
+		}
+
+		return $this->db[$key];
+	}
+	
+	private function checkDatabase($key)
+	{
+		if(empty($this->database[$key]))
+		{
+			if(empty($this->database['default']))
+			{
+				Output::abert('core_database_exists', $key);
+			}
+			$this->database[$key] = $this->database['default'];
+		}
+
+		if(isset($this->database[$key][$this->index]))
+		{
+			$this->database[$key] = $this->database[$key][$this->index];
+		}
+	}
+	
+	private function create($key)
+	{
+		# 建表
+		if(isset($this->config['struct']))
+		{
+			$this->config['type'] = isset($this->config['type']) ? $this->config['type'] : 'innodb';
+			$create = $this->db[$key]->create($this->config['struct'], $this->index, $this->config['type']);
+			if($create === true)
+			{
+				# 写入默认值
+				if(isset($this->config['default']))
+				{
+					$this->db[$key]->inserts($this->config['default'], $this->index);
+				}
+			}
+			else
+			{
+				if(isset($create['struct']))
+				{
+					if(count($create['struct']) < count($this->config['struct']))
+					{
+						$alter = array_diff_key($this->config['struct'], $create['struct']);
+						if($alter)
+						{
+							$this->db[$key]->alter($alter, $this->config['struct'], $this->index);
+						}
+					}
+				}
+				
+				# 更改表结构
+				if(isset($this->config['alter']))
+				{
+					$this->db[$key]->alter($this->config['alter'], $this->index);
+				}
+			}
+
+			# 建立索引
+			if(isset($this->config['index']))
+			{
+				$this->index($this->config['index'], $this->index);
+			}
+		}
+	}
+	
+	public function index($index)
+	{
+		return $this->db()->index($index);
+	}
+
+	/**
+     * db
+     *
+     * @return mixd
+     */
+	public function getDb($key = '')
+	{
+		return $this->db($key);
+	}
+	
+	/**
+     * 获取匹配的类型
+     *
+     * @return mixd
+     */
+	private function type($method)
+	{
+		switch($method)
+		{
+			case 1:
+				$method = '=';
+				break;
+			case 2:
+				$method = 'like';
+				break;
+			case 3:
+				$method = '>';
+				break;
+			case 4:
+				$method = '>=';
+				break;
+			case 5:
+				$method = '<';
+				break;
+			case 6:
+				$method = '<=';
+				break;
+		}
+		
+		return $method;
+	}
+	
+	/**
+     * # 初始化默认方法one、list、update、insert、delete、total、all、check
+     *
+     * @return mixd
+     */
+	private function init($method, $param = array())
+	{
+		$array = array();
+		$type = '';
+		
+		$this->config['request'][$method] = array
+		(
+			'type' => $method,
+			'where' => array('id' => 'yes'),
+		);
+		
+		# 支持单独字段更新
+		$key = '';
+		if(strpos($method, 'update_') !== false)
+		{
+			$key = str_replace('update_', '', $method);
+			if($key && isset($this->config['struct'][$key]))
+			{
+				$match = $this->config['struct'][$key]['match'];
+				if(is_array($this->config['struct'][$key]['match']))
+				{
+					$match = $this->config['struct'][$key]['match'][0];
+				}
+				$this->config['request'][$method]['type'] = 'update';
+				$this->config['request'][$method]['set'][$key] = $match;
+				$this->config['request'][$method]['where']['id'] = 'yes';
+
+				return;
+			}
+		}
+
+		switch($method)
+		{
+			case 'one':
+			case 'delete':
+				if(isset($param['where']))
+				{
+					$this->config['request'][$method]['where'] = $param['where'];
+				}
+				break;
+			case 'updatemul':
+				#批量更新操作,仅仅开启了mul_type配置或者后台可用
+				if(isset(Config::$global['base']['mul_type']) && Config::$global['base']['mul_type'] > 0)
+				{
+					$this->config['request'][$method]['type'] = 'update';
+
+					if(Config::$global['base']['mul_type'] == 2)
+					{
+						unset($this->config['request'][$method]['where']);
+						$type = 'option';
+					}
+					else
+					{
+						$type = 'mul';
+						$this->config['request'][$method]['where']['id'] = array('yes', 'in');
+					}
+				}
+
+				break;
+			case 'update':
+				$type = 'set';
+				$this->config['request'][$method]['input'] = false;
+				break;
+			case 'insert':
+				$this->config['request'][$method]['input'] = false;
+				unset($this->config['request'][$method]['where']);
+				$type = 'add';
+				break;
+			case 'state':
+				$this->config['request']['state'] = array
+				(
+					'type' => 'one',
+					'where' => array
+					(
+						'state' => 1,
+						'id' => 'yes'
+					)
+				);
+				break;
+			case 'list':
+				$type = 'option';
+				$this->config['request']['list'] = array
+				(
+					'type' => 'all',
+					'order' => array('id', 'desc'),
+					'page' => array(15, 'list'),
+					'col' => '*|id',
+					'option' => array(),
+				);
+
+				if(isset($this->config['manage']['list_type']) && $this->config['manage']['list_type'])
+				{
+					$this->config['request']['list']['page'][0] = 50000;
+				}
+				
+				if(isset(Config::$global['base']['excel']))
+				{
+					unset($this->config['request']['list']['page']);
+				}
+				break;
+			case 'all':
+				$type = 'option';
+				$this->config['request']['all'] = array
+				(
+					'type' => 'all',
+					'order' => array('id', 'desc'),
+					'col' => '*|id',
+					'where' => array
+					(
+						'state' => 1,
+					),
+					'option' => array(),
+					'input' => false,
+				);
+				break;
+			case 'check':
+				$type = 'option';
+				$this->config['request']['check'] = array
+				(
+					'type' => 'one',
+					'col' => '*',
+					'where' => array
+					(
+						'state' => 1,
+					),
+					'order' => array('id', 'desc'),
+					'option' => array(),
+					'input' => false,
+				);
+				break;
+			case 'info':
+				$type = 'option';
+				$this->config['request']['info'] = array
+				(
+					'type' => 'one',
+					'col' => '*',
+					'order' => array('id', 'desc'),
+					'option' => array(),
+					'input' => false,
+				);
+				break;
+			case 'total':
+				$type = 'option';
+				$this->config['request']['total'] = array
+				(
+					'type' => 'count',
+					'col' => 'count(1) as total',
+					//'group' => array('month'),
+					'option' => array(),
+				);
+				break;
+			default:
+				unset($this->config['request'][$method]);
+				break;
+		}
+
+		if(strpos($this->index, 'old') !== false)
+		{
+			if(isset($this->config['request'][$method]['where']['state']))
+			{
+				unset($this->config['request'][$method]['where']['state']);
+			}
+			
+			if(isset($this->config['request'][$method]['where']['option']))
+			{
+				unset($this->config['request'][$method]['where']['option']);
+			}
+
+			if(isset($this->config['request'][$method]['order']))
+			{
+				unset($this->config['request'][$method]['order']);
+			}
+		}
+
+		if(isset($this->config['struct']) && $type)
+		{
+			if($type == 'option' && is_array($param))
+			{
+				$param['search_type'] = isset($param['search_type']) ? $param['search_type'] : Input::get('search_fulltext_type', 1);
+				
+				$param['search_type'] = $this->type($param['search_type']);
+			}
+			foreach($this->config['struct'] as $k => $v)
+			{
+				if(isset($v['match']))
+				{
+					# 这里增加value,用以区分update/select的值
+					if(is_array($v['match']))
+					{
+						$v['value'] = $v['match'][1];
+						$v['match'] = $v['match'][0];
+					}
+					else
+					{
+						$v['value'] = $v['match'];
+					}
+					
+					# 首先匹配批量更新
+					if($method == 'updatemul' && isset($v['update']) && $v['update'] == 'radio' && (is_array($v['option']) || is_object($v['option'])))
+					{
+						$this->config['request'][$method]['set'][$k] = $v['value'];
+					}
+					
+					if(!isset($this->config['request'][$method][$type][$k]))
+					{
+						if($type == 'option')
+						{
+							# 位运算
+							if(isset($v['bit']))
+							{
+								$this->config['request'][$method][$type][$k] = array('option', '&');
+							}
+							# 默认排序
+							elseif(isset($v['order']))
+							{
+								if(isset($this->config['request'][$method]['order']))
+								{
+									if($this->config['request'][$method]['order'][0] && $this->config['request'][$method]['order'][0] != $k)
+									{
+										if($this->config['request'][$method]['order'][0] == 'id')
+										{
+											$this->config['request'][$method]['order'][0] = $k;
+											$this->config['request'][$method]['order'][1] = is_string($v['order']) ? $v['order'] : 'desc';
+										}
+										else
+										{
+											$this->config['request'][$method]['order'][0] = $k . '` '.(is_string($v['order']) ? $v['order'] : 'desc').',`' . $this->config['request'][$method]['order'][0];
+										}
+									}
+								}
+								
+								
+							}
+							# 全文检索
+							if(isset($param['search_type']) && isset($v['search']) && strpos($v['search'], 'fulltext') !== false)
+							{
+								$this->config['request'][$method][$type][$k] = array('option', $param['search_type']);
+							}
+
+							# 时间区间
+							elseif(isset($v['search']) && (strpos($v['search'], 'time') !== false || strpos($v['search'], 'date') !== false))
+							{
+								$this->config['request'][$method][$type]['start_' . $k] = array('yes-' . $k, '>=');
+								$this->config['request'][$method][$type]['end_' . $k] = array('yes-' . $k, '<=');
+							}
+							elseif(isset($v['search']) && strpos($v['search'], 'mul') !== false)
+							{
+								$this->config['request'][$method][$type][$k] = array('option', 'like');
+							}
+							else
+							{
+								$this->config['request'][$method][$type][$k] = $v['match'];
+							}
+
+							# in
+							if(isset($v['in']))
+							{
+								$this->config['request'][$method][$type][$k] = array('option', 'in');
+							}
+						}
+						elseif($type != 'mul' && !isset($v['table']))
+						{
+							if(!empty($v['insert']) && $type == 'set')
+							{
+								
+							}
+							else
+							{
+								$this->config['request'][$method][$type][$k] = $v['value'];
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		//print_r($_POST);die;
+		//print_r($this->config['request'][$method]);
+	}
+
+	private function top($param)
+	{
+		if(isset($this->config['top']) && is_string($this->config['top']))
+		{
+			$value = isset($param[$this->config['top_key']]) ? $param[$this->config['top_key']] : Input::get($this->config['top_key']);
+			if($value)
+			{
+				$top['value'] = $value;
+			}
+			else
+			{
+				$top = Load::get('manage/auth.getTop', array($this->config['top']));
+			}
+
+			if($top)
+			{
+				if(!Input::get('where_' . $this->config['top_key'])) Input::set('where_' . $this->config['top_key'], $top['value']);
+				if(!Input::get('option_' . $this->config['top_key'])) Input::set('option_' . $this->config['top_key'], $top['value']);
+				if(!Input::get('set_' . $this->config['top_key'])) Input::set('set_' . $this->config['top_key'], $top['value']);
+				if(!Input::get('add_' . $this->config['top_key'])) Input::set('add_' . $this->config['top_key'], $top['value']);
+				
+				if(!isset($param['where_' . $this->config['top_key']])) $param['where_' . $this->config['top_key']] = $top['value'];
+				if(!isset($param['option_' . $this->config['top_key']])) $param['option_' . $this->config['top_key']] = $top['value'];
+				if(!isset($param['set_' . $this->config['top_key']])) $param['set_' . $this->config['top_key']] = $top['value'];
+				if(!isset($param['add_' . $this->config['top_key']])) $param['add_' . $this->config['top_key']] = $top['value'];
+			}
+		}
+	}
+
+	/**
+     * method
+     *
+     * @return mixd
+     */
+	public function method($method = 'one', $param = array())
+	{
+		if(isset($param[0]) && is_array($param[0]))
+		{
+			$result = array();
+			foreach($param as $k => $v)
+			{
+				$result[] = $this->method($method, $v);
+			}
+			
+			return $result;
+		}
+
+		if($method == 'insert' && empty($this->config['submit']))
+		{
+			//\Dever::submit('check', 2);
+		}
+
+		$update_state = ($method == 'update' || $method == 'insert' || strpos($method, 'update_') !== false);
+
+		# 自动为admin赋值
+		$this->updateManage($method, $update_state, $param);
+
+		if($update_state)
+		{
+			$this->db();
+			if(isset($this->database[$this->key]['save']))
+			{
+				Load::get($this->config['project'] . '/' . $this->config['name'] . '-' . $method . '-save', $param);
+			}
+		}
+
+		if(!isset($this->config['request'][$method])) $this->init($method, $param);
+
+		if(isset($param['option']))
+		{
+			$this->config['request'][$method]['option'] = $param['option'];
+		}
+
+		$this->diy($method, $param);
+		
+		$this->config['param'] = array();
+		if(isset($this->config['request']) && isset($this->config['request'][$method]))
+		{
+			$this->hook('request', 'onload', $param);
+			$this->hook($method, 'start', $param);
+
+			if($param && !is_array($param))
+			{
+				if(isset($this->config['request'][$method]['where']))
+				{
+					$this->config['request'][$method]['where'] = array('id' => $param);
+					$param = array('where_id' => $param);
+				}
+				else
+				{
+					$this->config['request'][$method]['option'] = array('id' => $param);
+					$param = array('option_id' => $param);
+				}
+			}
+
+			# 验证头部权限
+			$this->top($param);
+
+			if($param)
+			{
+				$this->config['param'] =& $param;
+			}
+			
+			# 创建全局参数,给hook使用
+			Config::$global['base']['_param'] =& $this->config['param'];
+
+			if(isset($this->config['check']) && $update_state)
+			{
+				$check = false;
+				if(is_array($this->config['check']))
+				{
+					foreach($this->config['check'] as $k => $v)
+					{
+						$temp = $this->check($v);
+						if($temp == true)
+						{
+							$check = true;
+						}
+					}
+				}
+				else
+				{
+					$check = $this->check($this->config['check']);
+				}
+
+				if($check == true)
+				{
+					return;
+				}
+			}
+			
+			$this->config['response'] = $this->config['request'][$method];
+			
+			$this->config['input'] = true;
+			
+			if(isset($this->config['response']['input']))
+			{
+				$this->config['input'] = $this->config['response']['input'];
+			}
+
+			if(isset($this->config['response']['join']) && $this->config['response']['join'])
+			{
+				$this->db()->join($this->config['response']['join']);
+			}
+
+			$this->push(array('where', 'add', 'set', 'option'))->condition(array('page', 'order', 'limit', 'group'));
+
+			$type = isset($this->config['response']['type']) ? $this->config['response']['type'] : $method;
+
+			$this->col();
+
+			$data = $this->db()->$type($this->config['response']['col']);
+
+			if($data && $type == 'update' && isset($param['where_id']))
+			{
+				$data = $param['where_id'];
+			}
+
+			if($update_state && Project::load('manage') && isset($this->config['manage']) && isset($this->config['manage']['filter']))
+			{
+				$this->filter($this->config['manage']['filter'], $param, $data, $method);
+			}
+
+			if(isset($this->config['sync']) && $update_state)
+			{
+				$this->sync($this->config['sync'], $data);
+			}
+
+			if(isset($this->config['response']['relate']) && !$update_state && $data)
+			{
+				$this->relate($this->config['response']['relate'], $data, $type);
+			}
+			
+			$this->hook($method, 'end', $data);
+			
+			return $data;
+		}
+
+		return array();
+	}
+
+	private function updateManage($method, $update_state, &$param)
+	{
+		if(Project::load('manage') && DEVER_APP_NAME == 'manage' && $this->config['project'] != 'manage')
+		{
+			$admin = Load::get('manage/auth.info');
+			if($admin && $admin['id'] > 0)
+			{
+				if($method == 'insert')
+				{
+					$this->updateManageMethod($admin, 'insert', 'add', $param);
+				}
+				elseif($update_state)
+				{
+					$this->updateManageMethod($admin, 'update', 'set', $param);
+				}
+				elseif($admin['self'] == 1)
+				{
+					$this->updateManageMethod($admin, 'select', 'where', $param);
+				}
+			}
+			//print_r($param);die;
+		}
+	}
+
+	private function updateManageMethod($admin, $type, $prefix = 'add', &$param)
+	{
+		if(isset($admin['col_' . $type]) && $admin['col_' . $type] && is_array($param))
+		{
+			$col = explode(',', $admin['col_' . $type]);
+			foreach($col as $k => $v)
+			{
+				if(isset($this->config['struct'][$v]) && empty($this->config['struct'][$v]['value']))
+				{
+					$param[$prefix . '_' . $v] = $admin['id'];
+					if($prefix == 'where')
+					{
+						$param['option_' . $v] = $admin['id'];
+					}
+				}
+			}
+		}
+	}
+
+	private function filter($filter, $param, $data, $method)
+	{
+		if($method == 'update' && isset($param['where_id']))
+		{
+			$this->filterText($filter, $param, 'set', $param['where_id']);
+		}
+		elseif($method == 'insert' && $data > 0)
+		{
+			$this->filterText($filter, $param, 'add', $data);
+		}
+	}
+
+	private function filterText($filter, $param, $prefix = 'set', $id)
+	{
+		$text = '';
+
+		foreach($filter as $k => $v)
+		{
+			if(isset($param[$prefix . '_' . $v]))
+			{
+				$text .= '&dever_'.$v.'=' . $param[$prefix . '_' . $v];
+			}
+		}
+
+		if($text)
+		{
+			$config['project'] = $this->config['project'];
+			$config['table'] = $this->config['name'];
+			Load::get('manage/filter.handle', array($id, $text, $config));
+		}
+	}
+
+	private function check($col)
+	{
+		$state = true;
+		if(strpos($col, '.option'))
+		{
+			$col = str_replace('.option', '', $col);
+			$state = false;
+		}
+
+		$data = explode(',', $col);
+		$id = -1;
+		if(isset($this->config['param']['where_id']))
+		{
+			$id = $this->config['param']['where_id'];
+		}
+		foreach($data as $k => $v)
+		{
+			if(isset($this->config['struct'][$v]))
+			{
+				if(isset($this->config['param']['set_' . $v]))
+				{
+					$param['option_' . $v] = $this->config['param']['set_' . $v];
+				}
+				elseif(isset($this->config['param']['add_' . $v]))
+				{
+					$param['option_' . $v] = $this->config['param']['add_' . $v];
+				}
+
+				$temp = explode('-', $this->config['struct'][$v]['name']);
+				$name[] = $temp[0];
+			}
+		}
+
+		if(isset($param) && $param)
+		{
+			$info = Load::get($this->config['project'] . '/' . $this->config['name'] . '-info', $param);
+
+			if($id > 0 && $info && $info['id'] != $id)
+	        {
+	        	if($state == true)
+	        	{
+	        		Output::abert(implode(',', $name).'已经存在');
+	        	}
+	        	else
+	        	{
+	        		return true;
+	        	}
+	        }
+	        elseif($id < 0 && $info)
+	        {
+	            if($state == true)
+	        	{
+	        		Output::abert(implode(',', $name).'已经存在');
+	        	}
+	        	else
+	        	{
+	        		return true;
+	        	}
+	        }
+		}
+
+		return false;
+	}
+
+	private function relate($config, &$data, $type)
+	{
+		if($type == 'all')
+		{
+			foreach($data as $k => $v)
+			{
+				$this->relate($config, $data[$k], 'one');
+			}
+		}
+		else
+		{
+			foreach($config as $k => $v)
+			{
+				foreach($v as $i => $j)
+				{
+					$v[$i] = $data[$j];
+				}
+				$data[$k] = Load::get($k, $v);
+			}
+		}
+	}
+
+	private function sync($config, $id)
+	{
+		foreach($config as $k => $v)
+		{
+			$id = $id > 0 ? $id : $this->config['param']['where_id'];
+
+			$info = Load::get($this->config['project'] . '/' . $this->config['name'] . '-one', $id);
+			if(empty($info[$v['where'][1]]))
+			{
+				break;
+			}
+
+			if($v['type'] == 'delete')
+			{
+				Load::get($k . '-delete', array
+				(
+					'where' => array
+					(
+						$v['where'][0] => 'yes',
+					),
+					'where_' . $v['where'][0] => $info[$v['where'][1]],
+				));
+			}
+			foreach($v['update'] as $i => $j)
+			{
+				if(strpos($i, '-'))
+				{
+					$t = explode('-', $i);
+					$i = $t[0];
+				}
+				$value = $info[$j];
+
+				if($value)
+				{
+					$value = explode(',', $value);
+					foreach($value as $a => $b)
+					{
+						$method = 'insert';
+						$type = 'add';
+						$param = array();
+						if($v['type'] != 'delete')
+						{
+							$check = Load::get($k . '-info', array
+							(
+								'option_' . $i => $b, 
+								'option_' . $v['where'][0] => $info[$v['where'][1]],
+							));
+
+							if($check)
+							{
+								$method = 'update';
+								$type = 'set';
+								$param = array
+								(
+									'where_id' => $check['id'],
+								);
+							}
+						}
+
+						if($method)
+						{
+							$param += array
+							(
+								$type . '_' . $i => $b, 
+								$type . '_' . $v['where'][0] => $info[$v['where'][1]],
+							);
+
+							if(isset($v['sync']))
+							{
+								foreach($v['sync'] as $c => $d)
+								{
+									if(isset($info[$d]) && $info[$d])
+									{
+										$param[$type . '_' . $c] = $info[$d];
+									}
+								}
+							}
+
+							Load::get($k . '-' . $method, $param);
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	private function col()
+	{
+		if(empty($this->config['response']['col']))
+		{
+			$this->config['response']['col'] = '*';
+		}
+
+		if(isset(Config::$global['base']['sql']) && Config::$global['base']['sql'] && strpos($this->config['response']['col'], '*') !== false)
+		{
+			$temp = array();
+			foreach($this->config['struct'] as $k => $v)
+			{
+				if(isset($v['type']))
+				{
+					$temp[$k] = '`' . $k . '`';
+				}
+			}
+			
+			$this->config['response']['col'] = str_replace('*', implode(',', $temp), $this->config['response']['col']);
+		}
+	}
+
+	private function diy($method, $param)
+	{
+		if(($method == 'all' || $method == 'list') && is_array($param))
+		{
+			#diy all
+			$diy = array('page', 'group', 'order', 'col', 'limit', 'relate', 'join');
+			foreach($diy as $k => $v)
+			{
+				if(isset($param[$v]))
+				{
+					$this->config['request'][$method][$v] = $param[$v];
+				}
+			}
+
+			$diy = array('where', 'option');
+			foreach($diy as $k => $v)
+			{
+				if(isset($param[$v]))
+				{
+					$this->config['request'][$method][$v] = array_merge($this->config['request'][$method][$v], $param[$v]);
+				}
+			}
+		}
+	}
+
+	/**
+     * hook 插件钩子处理
+     * @param string $key
+     *
+     * @return mixd
+     */
+	private function hook($key, $method = 'start', &$param)
+	{
+		# 不再继续执行hook,就设置这个参数
+		if(Input::get('dever_onload') == 'no')
+		{
+			if($method == 'end')
+			{
+				//Input::set('dever_onload', 'yes');
+			}
+		}
+		elseif(isset($this->config[$method][$key]))
+		{
+			Input::set('dever_onload', 'no');
+			# 如果定义了top,就要传过去
+			if(isset($this->config['top']) && is_array($this->config['top']))
+			{
+				$param = array($param, $this->config['top']);
+			}
+			# 如果定义了auth,就要传过去
+			if(isset($this->config['auth']) && is_array($this->config['auth']))
+			{
+				$param = array($param, $this->config['auth']);
+			}
+			if(is_array($this->config[$method][$key]))
+			{
+				foreach($this->config[$method][$key] as $k => $v)
+				{
+					$data = Load::get($v, $param);
+				}
+				if($data)
+				{
+					$param = $data;
+				}
+			}
+			else
+			{
+				Input::set('dever_onload', 'no');
+				$data = Load::get($this->config[$method][$key], $param);
+
+				if($data)
+				{
+					$param = $data;
+				}
+			}
+		}
+	}
+
+	/**
+     * push
+     *
+     * @return mixd
+     */
+	private function push($param)
+	{
+		foreach($param as $k => $v)
+		{
+			if(isset($this->config['response'][$v]) && is_array($this->config['response'][$v]))
+			{
+				# 验证传入参数与配置是否相同
+				/*
+				$request = Input::prefix($v . '_');
+				if($v == 'where')
+				{
+					$request = Input::prefix('where_');
+				}
+				*/
+				
+				$value = array();
+				foreach($this->config['response'][$v] as $i => $j)
+				{
+					$t = array();
+					if(is_array($j))
+					{
+						$t = $j;
+						$j = $t[0];
+					}
+					$temp = $this->request($v. '_' . $i, $j, '', $i, $v);
+					//if($temp || (($v == 'add' || $v == 'set') && $temp && $temp == 0))
+					if($temp || ($temp === '0' || $temp === 0))
+					//if($temp)
+					{
+						if(is_array($temp))
+						{
+							if(isset($this->config['struct'][$i]) && isset($this->config['struct'][$i]['bit']))
+							{
+								$vt = 0;
+								foreach($temp as $ki => $vi)
+								{
+									if(isset($this->config['struct'][$i]['bit'][$vi]))
+									{
+										$vt += $this->config['struct'][$i]['bit'][$vi];
+									}
+								}
+								$temp = $vt;
+							}
+							elseif(isset($temp[0]) && is_array($temp[0]))
+							{
+								$temp = base64_encode(json_encode($temp));
+							}
+							else
+							{
+								$temp = str_replace(',0', '', implode(',', $temp));
+							}
+						}
+						
+						if($temp === 'null')
+						{
+							$temp = '';
+						}
+						$g = array($i, $temp);
+						if(isset($t[1]))
+						{
+							$g[2] = $t[1];
+						}
+						if(isset($t[2]))
+						{
+							$g[3] = $t[2];
+						}
+						$value[] = $g;
+					}
+				}
+
+				if($value)
+				{
+					if($v == 'option')
+					{
+						$v = 'where';
+					}
+					
+					$this->opt($v, $value);
+
+					$this->db()->$v($value);
+				}
+			}
+		}
+
+		return $this;
+	}
+	
+	/**
+     * opt
+     *
+     * @return mixd
+     */
+	private function opt($method, $param)
+	{
+		if(Project::load('manage') && isset(Config::$global['base']['opt']) && Config::$global['base']['opt'] && $this->config['project'] . $this->config['name']  != 'manageopt')
+		{
+			if($method == 'where')
+			{
+				$col = array();
+				foreach($param as $k => $v)
+				{
+					$col[] = $v[0];
+				}
+			}
+			
+			elseif($method == 'order')
+			{
+				$col = $param[0];
+				if(is_string($col))
+				{
+					if(strpos($col, '`') !== false)
+					{
+						$col = str_replace(array('`', 'desc', 'asc', ' '), '', $col);
+					}
+					
+					$col = explode(',', $col);
+				}
+				elseif(is_array($col))
+				{
+					foreach($col as $k => $v)
+					{
+						$col[] = $k;
+					}
+				}
+			}
+			
+			if(isset($col) && $col)
+			{
+				Opt::push($this->config['project'], $this->config['name'], $col);
+			}
+		}
+	}
+
+	/**
+     * condition
+     *
+     * @return mixd
+     */
+	private function condition($param)
+	{
+		foreach($param as $k => $v)
+		{
+			if(isset($this->config['response'][$v]) && $this->config['response'][$v])
+			{
+				if($v == 'page')
+				{
+					$value = $this->config['response'][$v];
+
+					if(isset($this->config['param']['page']) && $this->config['param']['page'] != $value)
+					{
+						$value[1] = array_merge($value[1], $this->config['param']['page']);
+					}
+					
+					if(is_string($value[1]))
+					{
+						$temp[] = $value[1];
+						unset($value[1]);
+						$value[1] = $temp;
+					}
+
+					if(isset($value[2])) $value[1][2] = $value[2];
+				}
+				else
+				{
+					$temp = '';
+					$value = $this->request($v, $this->config['response'][$v], '-', $temp);
+
+					if(!$value)
+					{
+						$value = $this->config['response'][$v];
+					}
+				}
+
+				if(is_string($value))
+				{
+					$value = array($value, '');
+				}
+
+				if(empty($value[0])) $value[0] = $value;
+				if(empty($value[1])) $value[1] = '';
+
+				$this->opt($v, $value);
+
+				$this->db()->$v($value[0], $value[1]);
+			}
+		}
+
+		return $this;
+	}
+
+	/**
+     * request
+     *
+     * @return mixd
+     */
+	private function request($key, $value, $split = '', &$index, $method = '')
+	{
+		//$index = str_replace(array('add_', 'where_', 'set_', 'option_'), '', $key);
+		
+		if($index && strpos($value, 'yes-') !== false)
+		{
+			$temp = explode('-', $value);
+			$value = $temp[0];
+			$index = $temp[1];
+		}
+		
+		if($index && $value == 'yes')
+		{
+			$value = 'option';
+			if(strpos($index, '.') !== false)
+			{
+				//$temp = explode('.', $index);
+				//$index = $temp[1];
+			}
+			if(isset($this->config['struct'][$index]) && is_array($this->config['struct'][$index]) && isset($this->config['struct'][$index]['match']) && $this->config['struct'][$index]['match'])
+			{
+				if(is_array($this->config['struct'][$index]['match']))
+				{
+					$value = $this->config['struct'][$index]['match'][0];
+				}
+				else
+				{
+					$value = $this->config['struct'][$index]['match'];
+				}
+			}
+		}
+		$state 		= false;
+		
+		if(isset($this->config['param'][$key]))
+		{
+			$request 	= $this->config['param'][$key];
+		}
+
+		
+
+		if($value == 'option')
+		{
+			$value = '';
+			$state = true;
+		}
+
+		$callback = is_string($value) && function_exists($value);
+		if($callback)
+		{
+			$callback = $value;
+			$value = '';
+		}
+
+		
+
+		if(isset($request) && ($request === '0' || $request === 0))
+		{
+			return 0;
+		}
+
+
+		
+		if(empty($request))
+		{	
+			if($this->config['input'])
+			{
+				$request 	= Input::get($key, $value);
+			}
+			else
+			{
+				$request = $value;
+			}
+		}
+
+
+
+		/*
+		if(is_array($request))
+		{
+			$request = implode(',', $request);
+		}
+		*/
+		if(is_string($value) && strpos($value, '/') === 0)
+		{
+			$state = preg_match($value, $request);
+		}
+		elseif(!empty($request))
+		{
+			if($callback)
+			{
+				$state = $callback($request);
+			}
+			elseif(is_string($request) && $split && strpos($request, $split) !== false)
+			{
+				$request = explode($split, $request);
+			}
+
+			$state = true;
+		}
+
+		if($key == 'set_name')
+		{
+			//echo $state;die;
+		}
+
+		//Debug::log(array('text' => 'model', 'state' => $state, 'preg' => $value, 'key' => $key, 'value' => $request));
+
+
+		if($state)
+		{
+			if(empty(Config::$global['base']['model_callback']) && $index && isset($this->config['struct'][$index]) && is_array($this->config['struct'][$index]) && isset($this->config['struct'][$index]['callback']) && $this->config['struct'][$index]['callback'] && $request)
+			{
+				$call = $this->config['struct'][$index]['callback'];
+				if($call == 'maketime')
+				{
+					if(is_string($request))
+					{
+						$request = \Dever::maketime($request);
+					}
+				}
+				else
+				{
+					if(strpos($call, '.'))
+					{
+						$temp = explode('.', $call);
+						$call = $temp[0];
+						$request = $call($temp[1], $request);
+					}
+					else
+					{
+						$request = $call($request);
+					}
+				}
+			}
+
+			if(($method == 'set' || $method == 'add') && isset($this->config['struct'][$index]['update']))
+			{
+				if(is_string($request) && empty($this->config['struct'][$index]['strip']))
+				{
+					$request = $this->safe_replace($request);
+					//$request = strip_tags($request);
+					//$request = htmlspecialchars($request);
+				}
+
+				if(isset($this->config['struct'][$index]['key']) && isset(Config::$global['host']['image']) && strpos($request, Config::$global['host']['image']) !== false)
+				{
+					$request = str_replace(Config::$global['host']['image'], '', $request);
+				}
+			}
+			
+			return $request;
+		}
+
+		# error
+		if($method != 'option' && $method != 'add' && $method != 'set')
+		{
+			if(isset($this->config['struct'][$index]['desc']) && $this->config['struct'][$index]['desc'])
+			{
+				Output::abert($this->config['struct'][$index]['desc']);
+			}
+			else
+			{
+				Output::abert('core_database_request', array($key, ($value ? $value : $callback)));
+			}
+		}
+
+		return false;
+	}
+	
+	private function safe_replace($content)
+	{
+		$tags = array(
+
+			"'<iframe[^>]*?>.*?</iframe>'is",
+
+			"'<frame[^>]*?>.*?</frame>'is",
+
+			"'<script[^>]*?>.*?</script>'is",
+
+			"'<head[^>]*?>.*?</head>'is",
+
+			"'<title[^>]*?>.*?</title>'is",
+
+			"'<meta[^>]*?>'is",
+
+			"'<link[^>]*?>'is",
+		);
+
+		return preg_replace($tags, "", $content);
+	}
+}

+ 101 - 0
vendor/dever-main/framework/src/Dever/Data/Mongo/Connect.php

@@ -0,0 +1,101 @@
+<?php namespace Dever\Data\Mongo;
+
+use Dever\Debug\Process as Debug;
+
+class Connect
+{
+	/**
+     * handle
+     *
+     * @var object
+     */
+	private $handle;
+
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Data\Mongo\Connect;
+     */
+    static public function getInstance($config)
+    {
+    	$key = $config['host'] . $config['database'];
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self();
+            self::$instance[$key]->init($config);
+        }
+
+        return self::$instance[$key];
+    }
+
+    
+    /**
+     * init
+     *
+     * @return mixd
+     */
+	private function init($config)
+	{
+		if(strpos($config['host'], ':') !== false) list($config['host'], $config['port']) = explode(':', $config['host']);
+
+        try
+        {
+			$mongo = new \Mongo('mongodb://'.$config['host'].':'.$config['port'], array("connectTimeoutMS"=>1000));
+			
+			$this->handle = $mongo->selectDB($config['database']);
+
+            Debug::log('mongodb ' . $config['host'] . ' connected', 'db');
+        }
+        catch(\PDOException $e)
+        {
+            echo $e->getMessage();die;
+        }
+	}
+
+	/**
+     * __destruct
+     *
+     * @return mixd
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+    
+    /**
+     * table
+     *
+     * @return mixd
+     */
+    public function table($table)
+    {
+        return $this->handle->selectCollection($table);
+    }
+
+	/**
+     * handle
+     *
+     * @return object
+     */
+	public function handle()
+	{
+		return $this->handle;
+	}
+
+	/**
+     * close
+     *
+     * @return mixd
+     */
+    public function close()
+    {
+		$this->handle = null;
+	}
+}

+ 485 - 0
vendor/dever-main/framework/src/Dever/Data/Mongo/Store.php

@@ -0,0 +1,485 @@
+<?php namespace Dever\Data\Mongo;
+
+use Dever\Data\Store as Base;
+
+class Store extends Base
+{
+    /**
+     * init
+     *
+     * @return mixd
+     */
+    public function init()
+    {
+        return;
+    }
+
+    /**
+     * connect
+     *
+     * @return mixd
+     */
+    public function connect($config)
+    {
+        return Connect::getInstance($config);
+    }
+
+	/**
+     * getTable
+     *
+     * @return mixd
+     */
+	public function getTable($table)
+	{
+		$this->table = $this->connect->table($table);
+	}
+	
+	/**
+     * getIndex
+     *
+     * @return mixed
+     */
+    public function getIndex($version, $index)
+    {
+        $return = $this->table->ensureIndex($index[$version], array('name' => ''));
+
+        $this->log($index[$version], 'index');
+        
+        $data['index'] = $version;
+
+        return $data;
+    }
+
+    /**
+     * alter table
+     *
+     * @return mixed
+     */
+    public function alter($alter)
+    {
+        return true;
+    }
+
+    /**
+     * query table
+     *
+     * @return mixed
+     */
+    public function query($sql, $state = true)
+    {
+        return true;
+    }
+
+    /**
+     * exe table
+     *
+     * @return mixed
+     */
+    public function exe($sql, $value = array(), $method = 'fetchAll')
+    {
+        return true;
+    }
+	
+	/**
+     * insert the default value
+     *
+     * @return mixed
+     */
+	public function getInserts($value)
+	{
+		$col = explode(',', $value['col']);
+        $value = explode(',', $value['value']);
+
+        foreach($col as $k => $v)
+        {
+            $this->value['add'][$v] = $value[$k];
+            $this->insert();
+        }
+
+        $this->log($value, 'inserts');
+        
+        $data = include($file);
+        
+        $data['insert'] = $value;
+
+        return $data;
+	}
+
+    /**
+     * all
+     *
+     * @return array
+     */
+    public function all($col)
+    {
+        $key = false;
+        if(strpos($col, '|') !== false)
+        {
+            $array = explode('|', $col);
+            $key = $array[1];
+            $col = $array[0];
+        }
+        $data = $this->select($col, 'find');
+
+		$result = array();
+		
+        if($data)
+        {
+            foreach($data as $k => $v)
+            {
+				$v['id'] = (array) $v['_id']; 
+				$v['id'] = $v['id']['$id'];
+                if(isset($v[$key]))
+                {
+					if(isset($array[3]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]][$v[$array[2]]] = $v;
+                    }
+                    elseif(isset($array[2]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]] = $v[$array[2]];
+                    }
+                    elseif(isset($array[2]))
+                    {
+                        $result[$v[$key]][] = $v;
+                    }
+                    else
+                    {
+                        $result[$v[$key]] = $v;
+                    }
+                }
+                else
+                {
+					$result[] = $v;
+				}
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * one
+     *
+     * @return array
+     */
+    public function one($col = '')
+    {
+        $data = $this->select($col, 'findOne');
+        if($data)
+        {
+			$data['id'] = (array) $data['_id']; 
+			$data['id'] = $data['id']['$id'];
+		}
+		return $data;
+    }
+
+    /**
+     * count
+     *
+     * @return array
+     */
+    public function count($col = 'clear')
+    {
+        return $this->select($col, 'count');
+    }
+
+    /**
+     * insert
+     *
+     * @return int
+     */
+	public function insert()
+    {
+        $insert = $this->value['add'];
+		
+		$return = $this->table->insert($insert);
+
+        $this->log($this->value);
+
+        $this->value = array();
+
+        return $insert['_id'];
+    }
+
+    /**
+     * update
+     *
+     * @return int
+     */
+	public function update()
+    {
+		$method = '$set';
+		$return = $this->table->update($this->value['where'], array($method => $this->value['set']));
+
+        $this->log($this->value);
+
+        $this->value = array();
+
+        return $return;
+    }
+
+    /**
+     * delete
+     *
+     * @return int
+     */
+	public function delete()
+    {
+        $this->update('$unset');
+
+        return $result;
+    }
+
+    /**
+     * select
+     *
+     * @return array
+     */
+    private function select($col = '', $method = 'find')
+    {
+        if(isset($this->value['where']))
+        {
+			//print_r($this->value['where']);
+            $return = $cursor = $this->table->$method($this->value['where']);
+        }
+        else
+        {
+			$return = $cursor = $this->table->$method();
+		}
+		
+		if($method != 'count')
+		{
+			if(isset($this->value['order']))
+			{
+				$return = $cursor->sort($this->value['order']);
+			}
+			
+			if(isset($this->value['limit']))
+			{
+				foreach($this->value['limit'] as $k => $v)
+				{
+					$return = $cursor->limit($k)->skip($v);
+				}
+			}
+			
+			if($col && $col != '*' && $col != 'clear')
+			{
+				if(is_string($col))
+				{
+					$temp = explode(',', $col);
+					$col = array();
+					foreach($temp as $k => $v)
+					{
+						$col[$v] = true;
+					}
+				}
+				$return = $cursor->fields($col);
+			}
+		}
+
+        $this->log($this->value);
+
+        if($col != 'clear')
+        {
+            $this->value = array();
+        }
+
+        return $return;
+    }
+
+    /**
+     * join
+     *
+     * @return object
+     */
+    public function join($param)
+    {
+        return $this;
+    }
+
+    /**
+     * __call
+     *
+     * @return object
+     */
+    public function __call($method, $param)
+    {
+        if(is_array($param[0]))
+        {
+            foreach($param[0] as $k => $v)
+            {
+				if($method == 'order')
+				{
+					$this->call($method, array($k, $v));
+				}
+				else
+				{
+					$this->call($method, $v);
+				}
+            }
+        }
+        else
+        {
+            $this->call($method, $param);
+        }
+
+    	return $this;
+    }
+
+    /**
+     * call
+     *
+     * @return mixd
+     */
+    private function call($method, $param)
+    {
+        if(is_array($param) && isset($param[0]))
+        {
+            if(is_string($param[0]) && strpos($param[0], ','))
+            {
+                $temp = explode(',', str_replace('`', '', $param[0]));
+                $index = count($temp)-1;
+                foreach($temp as $k => $v)
+                {
+                    if($k == $index)
+                    {
+                        $param[0] = $v;
+                    }
+                    else
+                    {
+                        $array = explode(' ', $v);
+                        $this->call($method, $array);
+                    }
+                }
+            }
+            
+            if($param[0] == 'id')
+            {
+				$param[0] = '_id';
+			}
+			
+            $func = 'convert_' . $method;
+            if(method_exists($this, $func))
+            {
+				$this->$func($param);
+			}
+
+            $this->value[$method][$param[0]] = $param[1];
+        }
+        else
+        {
+            $this->value[$method] = $param;
+        }
+    }
+
+    /**
+     * convert_order
+     *
+     * @return mixed
+     */
+    private function convert_order(&$param)
+    {
+		switch($param[1])
+		{
+			case 'desc':
+				$param[1] = -1;
+				break;
+			case 'asc':
+				$param[1] = 1;
+				break;
+		}
+    }
+    
+    /**
+     * convert_group
+     *
+     * @return mixed
+     */
+    private function convert_group(&$param)
+    {
+		print_r($param);die;
+    }
+    
+    /**
+     * convert_where
+     *
+     * @return mixed
+     */
+    private function convert_where(&$param)
+    {
+		if(isset($param[2]))
+		{
+			$state = true;
+			switch($param[2])
+			{
+				case 'like':
+					# 模糊查询
+					if(strpos($param[1], '%') !== false)
+					{
+						$param[1] = str_replace('%', '(.*?)', $param[1]);
+						$param[1] = new \MongoRegex('/'.$param[1].'/i');
+					}
+					else
+					{
+						$param[1] = new \MongoRegex('/(.*?)'.$param[1].'(.*?)/i');
+					}
+					$state = false;
+					break;
+					
+				case 'in':
+				case 'nin':
+					# in查询
+					$param[1] = explode(',', $param[1]);
+					if($param[0] == '_id')
+					{
+						foreach($param[1] as $k => $v)
+						{
+							$param[1][$k] = new \MongoId($v);
+						}
+					}
+					$param[2] = '$' . $param[2];
+					break;
+					
+				case '>':
+					$param[2] = '$gt';
+					break;
+				case '>=':
+					$param[2] = '$gte';
+					break;
+				case '<':
+					$param[2] = '$lt';
+					break;
+				case '<=':
+					$param[2] = '$lte';
+					break;
+				case '!=':
+					$param[2] = '$ne';
+					break;
+				case '%':
+					$param[2] = '$mod';
+					break;
+				case 'bt':
+					$state = false;
+					$param[1] = array('gt' => $param[1][0], 'lt' => $param[1][1]);
+					break;
+				case 'bte':
+					$state = false;
+					$param[1] = array('gte' => $param[1][0], 'lte' => $param[1][1]);
+					break;
+				default:
+					$param[2] = '$' . $param[2];
+					break;
+			}
+			if($state == true)
+			{
+				$param[1] = array($param[2] => $param[1]);
+			}
+		}
+		
+		if($param[0] == '_id' && is_string($param[1]))
+		{
+			$param[1] = new \MongoId($param[1]);
+		}
+    }
+}

+ 234 - 0
vendor/dever-main/framework/src/Dever/Data/Mysql/Connect.php

@@ -0,0 +1,234 @@
+<?php namespace Dever\Data\Mysql;
+
+use Dever\Debug\Process as Debug;
+
+class Connect
+{
+	/**
+     * handle
+     *
+     * @var object
+     */
+	private $handle;
+
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Data\Mysql\Connect;
+     */
+    static public function getInstance($config)
+    {
+    	$key = $config['host'] . $config['database'];
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self();
+            self::$instance[$key]->init($config);
+        }
+
+        return self::$instance[$key];
+    }
+
+    
+    /**
+     * init
+     *
+     * @return mixd
+     */
+	private function init($config)
+	{
+        $this->handle = @mysql_connect($config['host'], $config['username'], $config['password'], true);
+
+        if (!$this->handle)
+        {
+            die('Could not connect: ' . mysql_error());
+        }
+    
+        Debug::log('db ' . $config['host'] . ' connected', 'db');
+
+        if(!mysql_select_db($config['database'], $this->handle))
+        {
+            $this->query("CREATE DATABASE `".$config['database']."` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+
+            if(!mysql_select_db($config['database'], $this->handle))
+            {
+                die("Can\'t use ".$config['database']." : " . mysql_error());
+            }
+        }
+
+        $this->query("set names '".$config['charset']."'");
+        //$this->_log('connected mysql:' . $config['host']);
+	}
+
+	/**
+     * __construct
+     *
+     * @return mixd
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+	/**
+     * handle
+     *
+     * @return object
+     */
+	public function handle()
+	{
+		return $this->handle;
+	}
+
+	/**
+     * close
+     *
+     * @return mixd
+     */
+    public function close()
+    {
+		@mysql_close($this->handle);
+        $this->handle = null;
+	}
+
+	/**
+     * fetchAll
+     *
+     * @return object
+     */
+    public function fetchAll($sql, $method = MYSQL_ASSOC)
+    {
+    	$handle = $this->exec($sql);
+
+        $result = array();
+
+        while($row = mysql_fetch_array($handle, $method))
+        {
+            $result[] = $row;
+        }
+
+        return $result;
+    }
+
+    /**
+     * fetch
+     *
+     * @return object
+     */
+    public function fetch($sql, $method = MYSQL_ASSOC)
+    {
+        $handle = $this->exec($sql);
+
+        $result = mysql_fetch_array($handle, $method);
+
+        return $result;
+    }
+
+    /**
+     * exec
+     *
+     * @return object
+     */
+    public function exec($sql)
+    {
+        # 同步执行
+        if(strpos($sql, ';'))
+        {
+            $temp = explode(';', $sql);
+            foreach($temp as $k => $v)
+            {
+                $this->exec($v);
+            }
+
+            return true;
+        }
+        else
+        {
+            return mysql_query($sql, $this->handle);
+        }
+    }
+
+    /**
+     * query
+     *
+     * @return object
+     */
+    public function query($sql)
+    {
+        $this->exec($sql);
+
+        return $this;
+    }
+
+    /**
+     * rowCount
+     *
+     * @return object
+     */
+    public function rowCount()
+    {
+        return mysql_affected_rows();
+    }
+
+    /**
+     * fetchColumn
+     *
+     * @return object
+     */
+    public function fetchColumn($sql)
+    {
+        $handle = $this->exec($sql);
+
+        $result = mysql_fetch_row($handle);
+
+        return $result[0];
+    }
+
+    /**
+     * lastid
+     *
+     * @return int
+     */
+    public function id()
+    {
+        return mysql_insert_id($this->handle);
+    }
+
+    /**
+     * 
+     * @desc 释放结果内存
+     * @param  $query SQL语句
+     * @return  Boolean
+     * @author alfa  2011-2-17
+     */
+    public function freeResult($query){
+        return @mysql_free_result($query);
+    }
+
+    /**
+     * @desc 得到错误编号
+     * @return (int)错误编号
+     * @author alfa  2011-2-17
+     */
+    public function getErrno()
+    {
+        return mysql_errno();
+    }
+
+    /**
+     * 
+     * @desc 得到错误消息
+     * @return (string)错误消息
+     * @author alfa  2011-2-17
+     */
+    public function getError()
+    {
+        return mysql_error();
+    }
+}

+ 390 - 0
vendor/dever-main/framework/src/Dever/Data/Mysql/Store.php

@@ -0,0 +1,390 @@
+<?php namespace Dever\Data\Mysql;
+
+use Dever\Data\Sql;
+use Dever\Data\Store as Base;
+
+class Store extends Base
+{
+    /**
+     * init
+     *
+     * @return mixd
+     */
+    public function init()
+    {
+		$this->sql = Sql::getInstance();
+    }
+
+    /**
+     * connect
+     *
+     * @return mixd
+     */
+    public function connect($config)
+    {
+        return Connect::getInstance($config);
+    }
+
+	/**
+     * getTable
+     *
+     * @return mixd
+     */
+	public function getTable($table)
+	{
+        $this->table = $table;
+	}
+	
+	/**
+     * getIndex
+     *
+     * @return mixed
+     */
+    public function getIndex($version, $index)
+    {
+		$sql = $this->sql->showIndex($this->table);
+        
+        $info = $this->update->fetchAll($sql);
+        
+        if($info)
+        {
+            foreach($info as $k => $v)
+            {
+                if($v['Key_name'] != 'PRIMARY')
+                {
+                    $sql = $this->sql->dropIndex($this->table, $v['Key_name']);
+                    $this->update->query($sql);
+                }
+            }
+        }
+        
+        $sql = $this->sql->index($this->table, $index[$version]);
+
+        $this->query($sql);
+        
+        $this->log($sql, 'index');
+        
+        $data['index'] = $version;
+        
+        $data['order'] = array_flip(explode(',', array_shift($index[$version])));
+
+        return $data;
+	}
+
+    public function exe($sql, $value = array(), $method = 'fetchAll')
+    {
+        if(stristr($sql, 'select'))
+        {
+            $db = $this->read;
+        }
+        else
+        {
+            $db = $this->update;
+        }
+
+        $handle = $db->query($sql);
+
+        return $handle;
+    }
+	
+	public function query($sql, $state = true)
+	{
+		if(empty($this->config['shell']))
+		{
+			if(strpos($this->config['host'], ':') !== false)
+			{
+				$temp = explode(':', $this->config['host']);
+				$this->config['host'] = $temp[0];
+				$this->config['port'] = $temp[1];
+			}
+			
+			$this->config['shell'] = 'mysql -u'.$this->config['username'].' -p'.$this->config['password'].' '.$this->config['database'].' -h'.$this->config['host'].' -P'.$this->config['port'].' -e ';
+		}
+		
+		if($state == true)
+		{
+			# 异步执行
+			\Dever::run($this->config['shell'] . '"'.$sql.'"');
+		}
+		else
+		{
+			# 同步执行
+            if(strpos($sql, ';'))
+            {
+                $temp = explode(';', $sql);
+                foreach($temp as $k => $v)
+                {
+                    $this->update->query($v);
+                }
+            }
+			else
+            {
+                $this->update->query($sql);
+            }
+		}
+	}
+	
+	/**
+     * insert the default value
+     *
+     * @return mixed
+     */
+	public function getInserts($value, $data = array())
+	{
+		$sql = $this->sql->inserts($this->table, $value['col'], $value['value']);
+
+        $this->update->query($sql);
+
+        $this->log($sql, 'inserts');
+        
+        $data['insert'] = $sql;
+
+        return $data;
+	}
+
+    /**
+     * all
+     *
+     * @return array
+     */
+    public function all($col)
+    {
+        $key = false;
+        if(strpos($col, '|') !== false)
+        {
+            $array = explode('|', $col);
+            $key = $array[1];
+            $col = $array[0];
+        }
+        $data = $this->select($col, 'fetchAll');
+
+        if($data && $key)
+        {
+            $result = array();
+
+            foreach($data as $k => $v)
+            {
+                if(isset($v[$key]))
+                {
+					if(isset($array[3]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]][$v[$array[2]]] = $v;
+                    }
+                    elseif(isset($array[2]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]] = $v[$array[2]];
+                    }
+                    elseif(isset($array[2]))
+                    {
+                        $result[$v[$key]][] = $v;
+                    }
+                    else
+                    {
+                        $result[$v[$key]] = $v;
+                    }
+                }
+            }
+
+            return $result;
+        }
+
+        return $data;
+    }
+
+    /**
+     * one
+     *
+     * @return array
+     */
+    public function one($col)
+    {
+        return $this->select($col);
+    }
+
+    /**
+     * count
+     *
+     * @return array
+     */
+    public function count($col = '')
+    {
+        return $this->select($col, 'fetchColumn', 'count');
+    }
+
+    /**
+     * insert
+     *
+     * @return int
+     */
+	public function insert()
+    {
+    	$sql = $this->sql->insert($this->table);
+
+        $id = $this->update->query($sql)->id();
+
+        $this->log($sql, $this->value);
+
+        $this->cache();
+
+        $this->value = array();
+
+        return $id;
+    }
+
+    /**
+     * update
+     *
+     * @return int
+     */
+	public function update()
+    {
+        $sql = $this->sql->update($this->table);
+
+        $result = false;
+
+        if($sql)
+        {
+            //$result = $this->update->query($sql)->rowCount();
+            $result = $this->update->query($sql)->id();
+
+            $this->log($sql, $this->value);
+
+            $this->cache();
+        }
+
+        $this->value = array();
+
+        return $result;
+    }
+
+    /**
+     * delete
+     *
+     * @return int
+     */
+	public function delete()
+    {
+        $sql = $this->sql->delete($this->table);
+
+        $result = false;
+
+        if($sql)
+        {
+            $result = $this->update->query($sql)->rowCount();
+
+            $this->log($sql, $this->value);
+
+            $this->cache();
+        }
+
+        $this->value = array();
+
+        return $result;
+    }
+
+    /**
+     * select
+     *
+     * @return array
+     */
+    private function select($col = '', $method = 'fetch', $type = 'select')
+    {
+        $sql = $this->sql->{$type}($this->table, $col);
+
+        $key = $this->table . '_' . $method . '_' . md5($sql);
+
+        $data = $this->cache($key);
+
+        if($data)
+        {
+            if($col != 'clear')
+            {
+                $this->value = array();
+            }
+
+            return $data;
+        }
+        
+        if($type == 'count' && strpos($sql, 'group by `'))
+        {
+			$method = 'fetchAll';
+		}
+
+        $data = $this->read->$method($sql);
+
+        $this->cache($key, $data);
+
+        $this->log($sql, $this->value, $data);
+
+        if($col != 'clear')
+        {
+            $this->value = array();
+        }
+
+        return $data;
+    }
+
+    /**
+     * join
+     *
+     * @return object
+     */
+    public function join($param)
+    {
+        $this->sql->join($param);
+
+        return $this;
+    }
+
+    /**
+     * __call
+     *
+     * @return object
+     */
+    public function __call($method, $param)
+    {
+        if(is_array($param[0]) && $method != 'order')
+        {
+            foreach($param[0] as $k => $v)
+            {
+                $this->call($method, $v);
+            }
+        }
+        else
+        {
+            $this->call($method, $param);
+        }
+
+    	return $this;
+    }
+
+    /**
+     * call
+     *
+     * @return mixd
+     */
+    private function call($method, $param)
+    {
+        if($method == 'where' || $method == 'set' || $method == 'add')
+        {
+            # 特殊处理in
+            if(isset($param[2]) && $param[2] == 'in')
+            {
+                if(is_array($param[1]))
+                {
+                    $param[1] = '(' . implode(',', $param[1]) . ')';
+                }
+                else
+                {
+                    $param[1] = '(' . $param[1] . ')';
+                }
+            }
+            else
+            {
+                $param[1] = is_numeric($param[1]) ? intval($param[1]) : '"' . $param[1] . '"';
+            }
+        }
+
+        $this->sql->$method($param);
+    }
+}

+ 30 - 0
vendor/dever-main/framework/src/Dever/Data/Opt.php

@@ -0,0 +1,30 @@
+<?php namespace Dever\Data;
+
+class Opt
+{
+    static protected $data;
+    
+    static protected $instance;
+
+    static public function push($project, $table, $col)
+    {
+		if($col)
+		{
+			$key = $project . '.' . $table;
+			foreach($col as $k => $v)
+			{
+				self::$data[$key][$v] = $v;
+			}
+		}
+    }
+
+    static public function record()
+    {
+		if(self::$data)
+		{
+			$server = $_SERVER['DEVER_SERVER'];
+
+			\Dever::daemon('opt.push?dever_server=' . $server . '&param=' . base64_encode(json_encode(self::$data)), 'manage');
+		}
+    }
+}

+ 169 - 0
vendor/dever-main/framework/src/Dever/Data/Pdo/Connect.php

@@ -0,0 +1,169 @@
+<?php namespace Dever\Data\Pdo;
+
+use Dever\Debug\Process as Debug;
+
+class Connect
+{
+	/**
+     * handle
+     *
+     * @var object
+     */
+	private $handle;
+
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Data\Pdo\Connect;
+     */
+    static public function getInstance($config)
+    {
+    	$key = $config['host'] . $config['database'];
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self();
+            self::$instance[$key]->init($config);
+        }
+
+        return self::$instance[$key];
+    }
+
+    
+    /**
+     * init
+     *
+     * @return mixd
+     */
+	private function init($config)
+	{
+		if(strpos($config['host'], ':') !== false) list($config['host'], $config['port']) = explode(':', $config['host']);
+
+        $dsn['type'] 		= $config['type'];
+        $dsn['host'] 		= $config['host'];
+        $dsn['port'] 		= $config['port'];
+        $dsn['dbname'] 	    = $config['database'];
+        $dsn['charset']     = $config['charset'];
+
+        foreach($dsn as $key => $val)
+        {
+            $dsn[$key] = "$key=$val";
+        }
+
+        $dsnList = 'mysql:' . implode(';', $dsn);
+
+        try
+        {
+            $this->handle = new \PDO($dsnList, $config['username'], $config['password']);
+            $this->handle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+            //$this->handle->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
+            $this->handle->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_NATURAL);
+            $this->handle->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
+
+            Debug::log('db ' . $config['host'] . ' connected', 'db');
+        }
+        catch(\PDOException $e)
+        {
+            if(strstr($e->getMessage(),'Unknown database'))
+            {
+                $link = @mysql_connect($config['host'] . ':' . $config['port'], $config['username'], $config['password']);
+                @mysql_query("CREATE DATABASE `".$config['database']."` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;", $link);
+                @mysql_close($link);
+                $this->init($config);
+            }
+            else
+            {
+                echo $e->getMessage();
+            }
+        }
+
+        //$this->query("set names '".$config['charset']."'");
+        //$this->_log('connected mysql:' . $config['host']);
+	}
+
+    public function set()
+    {
+        $this->handle->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
+    }
+
+	/**
+     * __construct
+     *
+     * @return mixd
+     */
+    public function __destruct()
+    {
+        $this->close();
+    }
+
+	/**
+     * handle
+     *
+     * @return object
+     */
+	public function handle()
+	{
+		return $this->handle;
+	}
+
+	/**
+     * close
+     *
+     * @return mixd
+     */
+    public function close()
+    {
+		$this->handle = null;
+	}
+
+	/**
+     * prepare
+     *
+     * @return object
+     */
+    public function prepare($sql)
+    {
+    	return $this->handle->prepare($sql);
+    }
+
+    /**
+     * exec
+     *
+     * @return object
+     */
+    public function exec($sql)
+    {
+        return $this->handle->exec($sql);
+    }
+
+    /**
+     * query
+     *
+     * @return object
+     */
+    public function query($sql)
+    {
+        if($sql)
+        {
+            return $this->handle->query($sql);
+        }
+
+        return false;
+    }
+
+    /**
+     * lastid
+     *
+     * @return int
+     */
+    public function id()
+    {
+        return $this->handle->lastInsertId();
+    }
+}

+ 501 - 0
vendor/dever-main/framework/src/Dever/Data/Pdo/Store.php

@@ -0,0 +1,501 @@
+<?php namespace Dever\Data\Pdo;
+
+use Dever\Data\Sql;
+use Dever\Data\Store as Base;
+use Dever\Debug\Process as Debug;
+
+class Store extends Base
+{
+    /**
+     * init
+     *
+     * @return mixd
+     */
+    public function init()
+    {
+        $this->sql = Sql::getInstance();
+    }
+
+    /**
+     * connect
+     *
+     * @return mixd
+     */
+    public function connect($config)
+    {
+        return Connect::getInstance($config);
+    }
+
+    /**
+     * getTable
+     *
+     * @return mixd
+     */
+    public function getTable($table)
+    {
+        $this->table = $table;
+    }
+    
+    /**
+     * getIndex
+     *
+     * @return mixed
+     */
+    public function getIndex($version, $index)
+    {
+        $sql = $this->sql->showIndex($this->table);
+        
+        $handle = $this->update->query($sql);
+        
+        $info = $handle->fetchAll();
+        
+        if($info)
+        {
+            foreach($info as $k => $v)
+            {
+                if($v['Key_name'] != 'PRIMARY')
+                {
+                    $sql = $this->sql->dropIndex($this->table, $v['Key_name']);
+                    $this->update->query($sql);
+                }
+            }
+        }
+        
+        $sql = $this->sql->index($this->table, $index[$version]);
+
+        $this->query($sql);
+        
+        $this->log($sql, 'index');
+        
+        $data['index'] = $version;
+        
+        $data['order'] = array_flip(explode(',', array_shift($index[$version])));
+        
+        return $data;
+    }
+
+    public function exe($sql, $value = array(), $method = 'fetchAll')
+    {
+        if(stristr($sql, 'select'))
+        {
+            $db = $this->read;
+        }
+        else
+        {
+            $db = $this->update;
+        }
+        
+        try
+        {
+            if($value)
+            {
+                $handle = $db->prepare($sql);
+                $handle->execute($value);
+            }
+            else
+            {
+                $handle = $db->query($sql);
+            }
+        }
+        catch(\PDOException $exception)
+        {
+            $this->error($exception->getMessage(), $sql);
+        }
+
+        $this->log($sql, $value);
+
+        return $handle;
+
+        $data = $handle->$method();
+
+        return $data;
+    }
+    
+    public function query($sql, $state = true)
+    {
+        if(empty($this->config['shell']))
+        {
+            if(strpos($this->config['host'], ':') !== false)
+            {
+                $temp = explode(':', $this->config['host']);
+                $this->config['host'] = $temp[0];
+                $this->config['port'] = $temp[1];
+            }
+            
+            $this->config['shell'] = 'mysql -u'.$this->config['username'].' -p'.$this->config['password'].' '.$this->config['database'].' -h'.$this->config['host'].' -P'.$this->config['port'].' -e ';
+        }
+        
+        if($state == true)
+        {
+            # 异步执行
+            \Dever::run($this->config['shell'] . '"'.$sql.'"');
+        }
+        else
+        {
+            try
+            {
+                # 同步执行
+                if(strpos($sql, ';'))
+                {
+                    $temp = explode(';', $sql);
+                    foreach($temp as $k => $v)
+                    {
+                        $this->update->query($v);
+                    }
+                }
+                else
+                {
+                    $this->update->query($sql);
+                }
+            }
+            catch(\PDOException $exception)
+            {
+                $this->error($exception->getMessage(), $sql);
+            }
+        }
+    }
+
+    /**
+     * insert the default value
+     *
+     * @return mixed
+     */
+    public function getInserts($value, $data = array())
+    {
+        $sql = $this->sql->inserts($this->table, $value['col'], $value['value']);
+
+        try
+        {
+            $this->update->query($sql);
+        }
+        catch(\PDOException $exception)
+        {
+            $this->error($exception->getMessage(), $sql);
+        }
+
+        $this->log($sql, 'inserts');
+        
+        $data['insert'] = $sql;
+
+        return $data;
+    }
+
+    /**
+     * all
+     *
+     * @return array
+     */
+    public function all($col)
+    {
+        $key = false;
+        if(strpos($col, '|') !== false)
+        {
+            $array = explode('|', $col);
+            $key = $array[1];
+            $col = $array[0];
+        }
+        $data = $this->select($col, 'fetchAll');
+
+        if($data && $key)
+        {
+            $result = array();
+
+            foreach($data as $k => $v)
+            {
+                if(isset($v[$key]))
+                {
+                    if(isset($array[3]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]][$v[$array[2]]] = $v;
+                    }
+                    elseif(isset($array[2]) && isset($v[$array[2]]))
+                    {
+                        $result[$v[$key]] = $v[$array[2]];
+                    }
+                    elseif(isset($array[2]))
+                    {
+                        $result[$v[$key]][] = $v;
+                    }
+                    else
+                    {
+                        $result[$v[$key]] = $v;
+                    }
+                }
+            }
+
+            return $result;
+        }
+
+        return $data;
+    }
+
+    /**
+     * one
+     *
+     * @return array
+     */
+    public function one($col)
+    {
+        return $this->select($col);
+    }
+
+    /**
+     * count
+     *
+     * @return array
+     */
+    public function count($col = '')
+    {
+        return $this->select($col, 'fetchColumn', 'count');
+    }
+
+    /**
+     * insert
+     *
+     * @return int
+     */
+    public function insert()
+    {
+        $sql = $this->sql->insert($this->table);
+
+        if($sql)
+        {
+            try
+            {
+                $handle = $this->update->prepare($sql);
+
+                $handle->execute($this->value);
+            }
+            catch(\PDOException $exception)
+            {
+                $this->error($exception->getMessage(), $sql);
+            }
+
+            $id = $this->update->id();
+
+            $this->log($sql, $this->value);
+
+            $this->cache();
+        }
+
+        $this->value = array();
+
+        return $id;
+    }
+
+    /**
+     * update
+     *
+     * @return int
+     */
+    public function update()
+    {
+        $sql = $this->sql->update($this->table);
+
+        $result = false;
+
+        if($sql)
+        {
+            try
+            {
+                $handle = $this->update->prepare($sql);
+
+                $handle->execute($this->value);
+            }
+            catch(\PDOException $exception)
+            {
+                $this->error($exception->getMessage(), $sql);
+            }
+
+            $result = $handle->rowCount();
+            //$result = $this->update->id();
+
+            $this->log($sql, $this->value);
+
+            $this->cache();
+        }
+
+        $this->value = array();
+
+        return $result;
+    }
+
+    /**
+     * delete
+     *
+     * @return int
+     */
+    public function delete()
+    {
+        $sql = $this->sql->delete($this->table);
+
+        $result = false;
+
+        if($sql)
+        {
+            try
+            {
+                $handle = $this->update->prepare($sql);
+
+                $handle->execute($this->value);
+            }
+            catch(\PDOException $exception)
+            {
+                $this->error($exception->getMessage(), $sql);
+            }
+
+            $result = $handle->rowCount();
+
+            $this->log($sql, $this->value);
+
+            $this->cache();
+        }
+
+        $this->value = array();
+
+        return $result;
+    }
+
+    /**
+     * select
+     *
+     * @return array
+     */
+    private function select($col = '', $method = 'fetch', $type = 'select')
+    {
+        $sql = $this->sql->{$type}($this->table, $col);
+
+        $key = $this->table . '_' . $method . '_' . md5(serialize($this->value) . $sql);
+
+        $data = $this->cache($key);
+
+        if($data)
+        {
+            if($col != 'clear')
+            {
+                $this->value = array();
+            }
+
+            return $data;
+        }
+        
+        if($type == 'count' && strpos($sql, 'group by `'))
+        {
+            $method = 'fetchAll';
+        }
+
+        try
+        {
+            if($this->value)
+            {
+                $handle = $this->read->prepare($sql);
+
+                //print_r($this->value);
+
+                $handle->execute($this->value);
+            }
+            else
+            {
+                $handle = $this->read->query($sql);
+            }
+        }
+        catch(\PDOException $exception)
+        {
+            $this->error($exception->getMessage(), $sql);
+        }
+
+        $data = $handle->$method();
+
+        //print_r($data);
+
+        $this->cache($key, $data);
+
+        $this->log($sql, $this->value, $data);
+
+        if($col != 'clear')
+        {
+            $this->value = array();
+        }
+
+        return $data;
+    }
+
+    /**
+     * join
+     *
+     * @return object
+     */
+    public function join($param)
+    {
+        $this->sql->join($param);
+
+        return $this;
+    }
+
+    /**
+     * __call
+     *
+     * @return object
+     */
+    public function __call($method, $param)
+    {
+        if(is_array($param[0]) && $method != 'order')
+        {
+            foreach($param[0] as $k => $v)
+            {
+                $this->call($method, $v);
+            }
+        }
+        else
+        {
+            $this->call($method, $param);
+        }
+
+        return $this;
+    }
+
+    /**
+     * call
+     *
+     * @return mixd
+     */
+    private function call($method, $param)
+    {
+        if($method == 'where' || $method == 'set' || $method == 'add')
+        {
+            # 特殊处理in
+            if(isset($param[2]) && $param[2] == 'in')
+            {
+                if(!is_array($param[1]))
+                {
+                    $param[1] = explode(',', $param[1]);
+                }
+                
+                $prefix = 'in_';
+                $temp = $param[0];
+                foreach($param[1] as $k => $v)
+                {
+                    if(strpos($temp, '.'))
+                    {
+                        $temp = str_replace('.', '_', $temp);
+                    }
+                    $k = ':' . $temp . '_'. $prefix . $k;
+                    $key[] = $k;
+                    $this->value[$k] = $v;
+                }
+                
+                $param[1] = '(' . implode(',', $key) . ')';
+            }
+            else
+            {
+                $key = ':' . count($this->value);
+
+                $this->value[$key] = $param[1];
+
+                $param[1] = $key;
+            }
+        }
+
+        $this->sql->$method($param);
+    }
+}

+ 120 - 0
vendor/dever-main/framework/src/Dever/Data/Service.php

@@ -0,0 +1,120 @@
+<?php namespace Dever\Data;
+
+use Dever;
+use Dever\Data\Model;
+use Dever\Http\Input;
+use Dever\Page\Main as Page;
+
+class Service
+{
+    protected $model;
+    
+    protected $db;
+
+    public function __construct()
+    {
+        $config['name'] = 'table';
+        $config['project'] = DEVER_APP_NAME;
+		$this->model = new Model($config, 'service_' . DEVER_APP_NAME);
+        $this->db = $this->model->getDb();
+    }
+
+    public function query($sql, $value = array())
+    {
+        return $this->db->exe($sql, $value);
+    }
+
+    /**
+     * @desc 执行SQL语句
+     * @param  $sql 要执行的sql语句
+     * @param  $value 预处理要绑定的数据
+     * @param  $page 是否进行分页 参数:template 分页模板名称 maxnum 显示的记录数 maxpage 显示的最大页数 current 当前页数
+     * @param  $cache 是否进行缓存,如缓存,则为缓存的key
+     * @return array
+     */
+    public function all($sql, $value = array(), $page = array(), $cache = false)
+    {
+        # 这里的缓存是mysql缓存
+        if($cache)
+        {
+            $data = $this->db->cache($cache);
+            if($data)
+            {
+                return $data;
+            }
+        }
+
+        if($page)
+        {
+            $data = $this->page($page, $sql);
+        }
+        else
+        {
+            $data = $this->query($sql, $value)->fetchAll();
+        }
+        
+        if($cache)
+        {
+            $this->db->cache($cache, $data);
+        }
+
+        return $data;
+    }
+
+    /**
+     * cache 数据业务缓存
+     *
+     * @return object
+     */
+    public function cache($key = false, $data = array())
+    {
+        return Dever::cache($key, $data);
+    }
+
+    /**
+     * log 调试工具
+     *
+     * @return object
+     */
+    public function log($param)
+    {
+        return Debug::log($param);
+    }
+
+    /**
+     * page
+     *
+     * @return object
+     */
+    public function page($config = array(), $sql = false)
+    {
+        empty($config['template']) && $config['template'] = 'list';
+
+        empty($config['key']) && $config['key'] = 'current';
+
+        empty($config['link']) && $config['link'] = '';
+
+        empty($config['num']) && $config['num'] = 10;
+
+        $page = Page::getInstance($config['key']);
+
+        $page->template($config['template']);
+
+        $page->link($config['link']);
+
+        $total = Input::get('pt', -1);
+
+        if(isset($config['explode']) && isset($config['content']))
+        {
+            $content = explode($config['explode'], $config['content']);
+            $page->offset(1);
+            $data = $page->data($content, $total);
+        }
+        else
+        {
+            $data = $page->count($sql, $page->offset($config['num']), $total, $this);
+        }
+        
+        return $data;
+    }
+}

+ 739 - 0
vendor/dever-main/framework/src/Dever/Data/Sql.php

@@ -0,0 +1,739 @@
+<?php namespace Dever\Data;
+
+class Sql
+{
+    private $prefix = '';
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Data\Sql;
+     */
+    static public function getInstance()
+    {
+        if(empty(self::$instance))
+        {
+            self::$instance = new self();
+        }
+
+        return self::$instance->init();
+    }
+    
+    public function setColOrder($order)
+    {
+		$this->colOrder = $order;
+	}
+
+    /**
+     * create
+     * 
+     * @return string
+     */
+    public function create($table, $struct, $type = '')
+    {
+        $create = $primary = array();
+
+        foreach($struct as $k => $v)
+        {
+			if(isset($v['table']) && $v['table'] != $table)
+			{
+				continue;
+			}
+            $primary[$k] = '';
+            if(is_array($v))
+            {
+				if(!isset($v['type']))
+                {
+                    continue;
+                }
+                $com = $v;
+                $v = $com['type'];
+                if(strpos($com['type'], 'text') !== false)
+                {
+                    $primary[$k] .= '';
+                }
+                elseif(strpos($com['type'], 'int') === false)
+                {
+                    $primary[$k] .= 'not null default \'\'';
+                }
+                elseif(!empty($com['default']))
+                {
+                    $default = $com['default'];
+                    $com['default'] = '{default}';
+                    $primary[$k] .= 'not null default \'' . $com['default'] . '\'';
+                }
+                elseif($k != 'id' && strpos($com['type'], 'int') !== false)
+                {
+                    $primary[$k] .= 'not null default 0';
+                }
+                else
+                {
+                    $primary[$k] .= 'not null';
+                }
+
+                if(!empty($com['name']))
+                {
+                    $primary[$k] .= ' comment \'' . $com['name'] . '\'';
+                }
+            }
+            elseif(is_string($v) && strpos($v,' ') !== false)
+            {
+                $com = explode(' ',$v);
+                $v = $com[0];
+                if(!empty($com[1]))
+                {
+                    $default = $com[1];
+                    $com[1] = '{default}';
+                    $primary[$k] .= 'not null default \'' . $com[1] . '\'';
+                }
+                else
+                {
+                    $primary[$k] .= 'not null';
+                }
+
+                if(!empty($com[2]))
+                {
+                    $primary[$k] .= ' comment \'' . $com[2] . '\'';
+                }
+            }
+            if($k == 'id')
+            {
+                $primary[$k] = 'unsigned auto_increment primary key ' . $primary[$k];
+            }
+
+            $create[] = '`' . $k . '` ' . strtoupper(str_replace('-','(',$v) . ') ' . $primary[$k] . '');// not null 
+        }
+        $sql    = 'DROP TABLE IF EXISTS `' . $table . '`;CREATE TABLE `' . $table . '`(' . implode(',', $create) . ')';
+        
+        //$sql    = 'CREATE TABLE `' . $table . '`(' . implode(',', $create) . ')';
+
+        if(strpos($sql, '{DEFAULT}') && isset($default))
+        {
+            $sql = str_replace('{DEFAULT}', $default, $sql);
+        }
+
+        if($type)
+        {
+            $sql .= ' ENGINE = ' . $type;
+        }
+
+        //echo $sql;die;
+
+        return $sql;
+    }
+
+    /**
+     * alter
+     * 
+     * @return string
+     */
+    public function alter($table, $config)
+    {
+        $create = $primary = array();
+
+        $alter = 'ALTER TABLE `' . $table;
+
+        $sql = array();
+        foreach($config as $k => $v)
+        {
+			if(isset($v['type']))
+			{
+				$v = array
+				(
+					'add', $k, $k, $v['type'] . ' ' . $v['default'] . ' ' . $v['name'],
+				);
+			}
+
+            if(empty($v[3]))
+            {
+                continue;
+            }
+            $sql[$k] = '';
+            if(isset($v[3]) && strpos($v[3],' ') !== false)
+            {
+                $com = explode(' ',$v[3]);
+                $sql[$k] = str_replace('-','(',$com[0]) . ') ';
+                if(isset($com[1]) && $com[1] != '')
+                {
+                    $sql[$k] .= 'not null default \'' . $com[1] . '\'';
+                }
+                else
+                {
+                    $sql[$k] .= 'not null';
+                }
+
+                if(!empty($com[2]))
+                {
+                    $sql[$k] .= ' comment \'' . $com[2] . '\'';
+                }
+                $sql[$k] = strtoupper($sql[$k]);
+            }
+
+            if($v[0] == 'add')
+            {
+                # 新增字段
+                $sql[$k] = $alter . '` ADD `' . $v[1] . '` ' . $sql[$k];
+            }
+            elseif($v[0] == 'delete')
+            {
+                # 删除字段
+                $sql[$k] = $alter . '` DROP `' . $v[1] . '`';
+            }
+            else
+            {
+                # 修改字段
+                $sql[$k] = $alter . '` CHANGE `' . $v[1] . '` `' . $v[2] . '` ' . $sql[$k];
+            }
+        }
+
+        $sql = implode(';', $sql);
+        
+        return $sql;
+    }
+
+    /**
+     * col
+     * 
+     * @return string
+     */
+    private function col($col)
+    {
+        $result = '';
+
+        if(is_array($col))
+        {
+        	$array = array();
+            foreach($col as $k => $v)
+            {
+                if(!is_numeric($k))
+                {
+                    $array[] = $this->prefix . $k . ' AS ' . $v;
+                }
+                else
+                {
+                    $array[] = $this->prefix . $v;
+                }
+            }
+            $result = implode(' ', $array);
+        }
+        else
+        {
+            $result = $col ? $this->prefix . $col : $this->prefix . '*';
+        }
+
+        if(isset($this->col) && $this->col)
+        {
+            $result .= ',' . $this->col;
+        }
+        return $result;
+    }
+
+    /**
+     * select
+     * 
+     * @return string
+     */
+    public function select($table, $col = '')
+    {
+        $where = $this->createWhere();
+
+        $join = isset($this->join) ? implode(' ', $this->join) : '';
+
+        $sql = 'SELECT ' . $this->col($col) . ' FROM `' . $table . '` '  . $join . $where . ' ' . $this->group . ' ' . $this->order . ' ' . $this->limit;
+
+        $this->init();
+
+        //echo $sql;
+
+        return $sql;
+    }
+    
+    private function createWhere()
+    {
+		$where = '';
+        if($this->where)
+        {
+			if(isset($this->colOrder))
+			{
+				ksort($this->where);
+			}
+			
+			if(isset($this->between))
+			{
+				$where = 'WHERE ' . $this->between . ' ' . implode(' ', $this->where);
+				$this->limit = '';
+			}
+			else
+			{
+				$where = 'WHERE ' . ltrim(implode(' ', $this->where), 'and');
+			}
+        }
+		
+		return $where;
+	}
+
+    /**
+     * count
+     * 
+     * @return string
+     */
+    public function count($table, $col = '')
+    {
+        $where = $this->createWhere();
+
+        $state = 1;
+        if($col == 'clear')
+        {
+            $col = '';
+            $state = 2;
+        }
+        if(!$col)
+        {
+            $col = 'count(*) as total';
+        }
+
+        $join = isset($this->join) ? implode(' ', $this->join) : '';
+
+        $sql = 'SELECT ' . $col . ' FROM `' . $table . '` ' . $join . $where . ' ' . $this->group . ' ';
+
+        if($state == 1)
+        {
+            $this->init();
+        }
+
+        return $sql;
+    }
+    
+    /**
+     * showIndex
+     * 
+     * @return string
+     */
+    public function showIndex($table)
+    {
+        $sql = 'SHOW INDEX FROM ' . $table . ' ';
+        
+        return $sql;
+    }
+    
+    /**
+     * dropIndex
+     * 
+     * @return string
+     */
+    public function dropIndex($table, $name)
+    {
+        $sql = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $name;
+        
+        return $sql;
+    }
+
+    /**
+     * index
+     * 
+     * @return string
+     */
+    public function index($table, $value)
+    {
+        $sql = 'ALTER TABLE ' . $table . ' ';
+
+        $max = count($value)-1;
+
+        $i = 0;
+        
+        foreach($value as $k => $v)
+        {
+            $type = 'INDEX';
+            if(strpos($v, '.'))
+            {
+                $t = explode('.', $v);
+                $v = $t[0];
+                $type = ucwords($t[1]);
+            }
+            $sql .= 'ADD '.$type.' ' . $k . ' (' . $v . ')';
+
+            if($i >= $max)
+            {
+                $sql .= '';
+            }
+            else
+            {
+                $sql .= ',';
+            }
+
+            $i++;
+        }
+
+        return $sql;
+    }
+
+    /**
+     * insert
+     * 
+     * @return string
+     */
+    public function insert($table)
+    {
+        $sql = 'INSERT INTO `' . $table . '` (' . implode(',', $this->col) . ') VALUES (' . implode(',', $this->value) . ')';
+
+        $this->init();
+
+        return $sql;
+    }
+    
+    /**
+     * inserts
+     * 
+     * @return string
+     */
+    public function inserts($table, $col, $value)
+    {
+        $sql = 'INSERT INTO `' . $table . '` (' . $col . ') VALUES ';
+
+        $max = count($value)-1;
+
+        foreach($value as $k => $v)
+        {
+            $sql .= '(' . $v . ')';
+
+            if($k >= $max)
+            {
+                $sql .= '';
+            }
+            else
+            {
+                $sql .= ',';
+            }
+        }
+
+        return $sql;
+    }
+    
+    /**
+     * explain
+     * 
+     * @return string
+     */
+    public function explain($sql)
+    {
+        $sql = 'EXPLAIN ' . $sql . ' ';
+        
+        return $sql;
+    }
+
+    /**
+     * update
+     * 
+     * @return string
+     */
+    public function update($table)
+    {
+        if(!$this->where)
+        {
+            return false;
+        }
+        
+        $where = $this->createWhere();
+
+        $sql = 'UPDATE `' . $table . '` SET ' . implode(',', $this->value) . ' ' . $where;
+
+        $this->init();
+
+        return $sql;
+    }
+
+    /**
+     * delete
+     * 
+     * @return string
+     */
+    public function delete($table)
+    {
+        if(!$this->where)
+        {
+            return false;
+        }
+        
+        $where = $this->createWhere();
+
+        $sql = 'DELETE FROM `' . $table . '` ' . $where;
+
+        $this->init();
+
+        return $sql;
+    }
+    
+    /**
+     * truncate
+     * 
+     * @return string
+     */
+    public function truncate($table)
+    {
+		$sql = 'TRUNCATE TABLE `' . $table . '`';
+		
+		return $sql;
+	}
+
+    /**
+     * opt
+     * 
+     * @return string
+     */
+    public function opt($table)
+    {
+        $sql = 'OPTIMIZE TABLE `' . $table . '`';
+        
+        return $sql;
+    }
+	
+	/**
+     * sql
+     * 
+     * @return string
+     */
+    public function sql($sql)
+    {
+		return $sql;
+	}
+
+    /**
+     * init
+     * 
+     * @return object
+     */
+    public function init()
+    {
+        $this->where = $this->value = $this->col = $this->join = array();
+        $this->order = '';
+        $this->group = '';
+        $this->limit = '';
+        $this->prefix = '';
+
+        return $this;
+    }
+
+    /**
+     * where
+     * 
+     * @return string
+     */
+    public function where($param)
+    {
+        if(empty($param[2])) $param[2] = '=';
+
+        if(empty($param[3])) $param[3] = 'and';
+
+        if(strpos($param[3], ')') !== false)
+        {
+            $temp = explode(')', $param[3]);
+            $param[3] = $temp[0];
+            $param[1] = $param[1] . ' )';
+        }
+
+        if(!strpos($param[0], '.'))
+        {
+            $param[0] = $this->prefix . '`' . $param[0] . '`';
+        }
+
+        $where = $param[3] . ' ' . $param[0] . ' '. $param[2] . ' ' . $param[1];
+        
+        if(isset($this->colOrder))
+		{
+			if(isset($this->colOrder[$param[0]]))
+			{
+				$this->where[$this->colOrder[$param[0]]] = $where;
+			}
+			else
+			{
+				$num = count($this->where) + 100;
+				$this->where[$num] = $where;
+			}
+		}
+		else
+		{
+			$this->where[] = $where;
+		}
+    }
+
+    /**
+     * order
+     * 
+     * @return string
+     */
+    public function order($param)
+    {
+		if(is_array($param[0]))
+		{
+			$this->order = 'order by ';
+			foreach($param[0] as $k => $v)
+			{
+                $k1 = '';
+                if(strpos($k, '.'))
+                {
+                    $t = explode('.', $k);
+                    $k = $t[1];
+                    $k1 = $t[0] . '.';
+                }
+				$order[] = $k1 . '`' . $k . '` ' . $v;
+			}
+			
+			$this->order .= implode(',', $order);
+			
+			//echo $this->order;
+		}
+		else
+		{
+			if(empty($param[1])) $param[1] = 'desc';
+
+			$this->order = 'order by `' . $param[0] . '` ' . $param[1];
+		}
+    }
+
+    /**
+     * group
+     * 
+     * @return string
+     */
+    public function group($param)
+    {
+        if(is_array($param))
+        {
+            $param = trim(implode(',', $param), ',');
+            
+            $this->group = ' group by ' . $param;
+        }
+
+		# 去掉id的分组,没用
+		if(is_string($param) && $param != 'id')
+		{
+            if($param == 'day')
+            {
+                $this->col = 'FROM_UNIXTIME(cdate, "%Y-%m-%d") as day';
+            }
+            elseif($param == 'month')
+            {
+                $this->col = 'FROM_UNIXTIME(cdate, "%Y-%m") as month';
+            }
+            elseif($param == 'year')
+            {
+                $this->col = 'FROM_UNIXTIME(cdate, "%Y") as year';
+            }
+            elseif(strpos($param, ',') === false)
+            {
+                $this->col = $param;
+            }
+
+			$this->group = ' group by ' . $param;
+		}
+    }
+
+    /**
+     * join 为临时解决方案,不建议用join
+     * 
+     * @return string
+     */
+    public function join($param)
+    {
+        $this->prefix = 't_1.';
+        $this->join[] = 'as t_1';
+        $num = 2;
+        foreach($param as $k => $v)
+        {
+            if($v)
+            {
+                $table = 't_' . $num;
+                if(strpos($v['on'][0], '.') === false)
+                {
+                    $v['on'][0] = 't_1.`' . $v['on'][0] . '`';
+                }
+                else
+                {
+                    $v['on'][0] = 't_' . $v['on'][0];
+                }
+
+                $v['on'][1] = $table . '.`' . $v['on'][1] . '`';
+
+                $v['table'] = str_replace('/', '_', $v['table']);
+                if(DEVER_PROJECT != 'default')
+                {
+                    $v['table'] = DEVER_PROJECT . '_' . $v['table'];
+                }
+                
+                $this->join[] = ucwords($v['type']) . ' `' . $v['table'] . '` AS '.$table.' ON ' . $v['on'][0] . '=' . $v['on'][1] . ' ';
+
+                if(isset($v['col']))
+                {
+                    $this->col = $v['col'];
+                }
+
+                $num++;
+            }
+        }
+    }
+
+    /**
+     * limit
+     * 
+     * @return string
+     */
+    public function limit($param)
+    {
+        if(empty($param[1])) $param[1] = 0;
+
+        $this->limit = 'limit ' . $param[1] . ',' . $param[0];
+        
+        //$this->between = ' `id` BETWEEN ' . $param[1] . ' AND ' . ($param[1] + $param[0]);
+    }
+
+    /**
+     * reset limit
+     * 
+     * @return string
+     */
+    public function reset($param)
+    {
+        $this->{$param[0]} = '';
+    }
+
+    /**
+     * add
+     * 
+     * @return string
+     */
+    public function add($param)
+    {
+        $this->col[] = '`' . $param[0] . '`';
+        $this->value[] = $param[1];
+    }
+
+    /**
+     * set
+     * 
+     * @return string
+     */
+    public function set($param)
+    {
+        if(empty($param[2])) $param[2] = '=';
+
+        $param[0] = '`' . $param[0] . '`';
+
+        if(strpos($param[2], '+=') !== false)
+        {
+            $param[2] = '=' . $param[0] . '+';
+        }
+
+        if(strpos($param[2], '-=') !== false)
+        {
+            $param[2] = '=' . $param[0] . '-';
+        }
+
+        $this->value[] = $param[0] . $param[2] . $param[1];
+    }
+}

+ 494 - 0
vendor/dever-main/framework/src/Dever/Data/Store.php

@@ -0,0 +1,494 @@
+<?php namespace Dever\Data;
+
+use Dever\File\Path;
+use Dever\Page\Main as Page;
+use Dever\Config\Load as Config;
+use Dever\Cache\Handle;
+use Dever\Debug\Process as Debug;
+use Dever\Http\Input;
+
+class Store
+{
+	/**
+     * read
+     *
+     * @var Dever\Data\Connect
+     */
+    protected $read;
+
+    /**
+     * update
+     *
+     * @var Dever\Data\Connect
+     */
+    protected $update;
+    
+    /**
+     * config
+     *
+     * @var array
+     */
+    protected $config;
+
+    /**
+     * table
+     *
+     * @var string
+     */
+	protected $table;
+
+    /**
+     * value
+     *
+     * @var array
+     */
+    protected $value = array();
+
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Data\Store;
+     */
+    static public function getInstance($config)
+    {
+        if(empty(self::$instance))
+        {
+            self::$instance = new self();
+        }
+
+        self::$instance->register($config);
+
+        return self::$instance;
+    }
+
+    /**
+     * __construct
+     *
+     * @return mixd
+     */
+    public function __construct($config)
+    {
+    	$this->init();
+
+		$this->register($config);
+    }
+
+    /**
+     * register
+     *
+     * @return mixd
+     */
+	private function register($config)
+	{
+        # read update 
+        if(is_array($config['host']))
+        {
+            $host = $config['host'];
+
+            $config['host'] = $host['read'];
+
+            $this->read = $this->connect($config);
+
+            $config['host'] = $host['update'];
+
+            $this->update = $this->connect($config);
+        }
+        elseif(is_string($config['host']) && strpos($config['host'], ',') !== false)
+        {
+            $host = explode(',', $config['host']);
+
+            $config['host'] = $host[0];
+
+            $this->read = $this->connect($config);
+
+            $config['host'] = $host[1];
+
+            $this->update = $this->connect($config);
+        }
+        else
+        {
+            $this->read = $this->update = $this->connect($config);
+        }
+        
+        $this->config = $config;
+	}
+
+	/**
+     * table
+     *
+     * @return object
+     */
+	public function table($table, $name = '', $state = true)
+	{
+        if(defined('DEVER_DB_PREFIX'))
+        {
+            $table = DEVER_DB_PREFIX . '_' . $table;
+        }
+		elseif($state == true && defined('DEVER_PROJECT') && DEVER_PROJECT != 'default')
+		{
+			$table = DEVER_PROJECT . '_' . $table;
+		}
+		
+        $this->getTable($table);
+
+        if($state == true && isset($this->sql) && isset($global['base']['sql']) && Config::$global['base']['sql'])
+        {
+            $file = $this->file($name);
+            
+            if(is_file($file))
+            {
+                $config = include($file);
+                $this->sql->setColOrder($config['order']);
+            }
+        }
+
+        return $this;
+	}
+
+	/**
+     * table
+     *
+     * @return object
+     */
+	public function index($index, $name = '')
+	{
+		if(empty($index))
+		{
+			return false;
+		}
+		$file = $this->file($name);
+        if(!is_file($file))
+        {
+            return false;
+        }
+        
+        $data = include($file);
+        
+        if(isset($index['version']))
+        {
+			$version = $index['version'];
+			
+			unset($index['version']);
+		}
+		else
+		{
+			$version = 1;
+		}
+        
+        if(empty($data['index']) || (isset($data['index']) && $data['index'] < $version))
+        {
+        	$data = $this->getIndex($version, $index);
+
+        	file_put_contents($file, '<?php return ' . var_export($data, true) . ';');
+        }
+
+        return $this;
+	}
+
+
+	/**
+     * alter table
+     *
+     * @return mixed
+     */
+    public function alter($alter, $struct = array(), $name = '')
+    {
+    	if(empty($this->sql))
+        {
+            return false;
+        }
+        if(empty($alter))
+        {
+            return false;
+        }
+        $file = $this->file($name);
+
+        if(!is_file($file))
+        {
+            return false;
+        }
+        
+        $data = include($file);
+        if(is_array($struct))
+        {
+            $sql = $this->sql->alter($this->table, $alter);
+
+            $this->exe($sql);
+
+            $this->log($sql, 'alter');
+            
+            $data['struct'] = array_flip(array_keys($struct));
+
+            file_put_contents($file, '<?php return ' . var_export($data, true) . ';');
+        }
+        else
+        {
+            if(isset($alter['version']))
+            {
+                $version = $alter['version'];
+            }
+            else
+            {
+                $version = 1;
+            }
+            
+            if(isset($alter[$version]) && (empty($data['alter']) || (isset($data['alter']) && $data['alter'] != $version)))
+            {
+                $sql = $this->sql->alter($this->table, $alter[$version]);
+
+                $this->exe($sql);
+
+                $this->log($sql, 'alter');
+                
+                $data['alter'] = $version;
+
+                file_put_contents($file, '<?php return ' . var_export($data, true) . ';');
+            }
+        }
+        
+
+        return true;
+    }
+
+    /**
+     * insert the default value
+     *
+     * @return mixed
+     */
+	public function inserts($value, $name = '')
+	{
+		$file = $this->file($name);
+        if(!is_file($file))
+        {
+            return false;
+        }
+
+        $data = include($file);
+		if(isset($value['col']) && isset($value['value']))
+		{
+            $this->truncate();
+
+			$data = $this->getInserts($value, $data);
+
+			file_put_contents($file, '<?php return ' . var_export($data, true) . ';');
+		}
+
+        return true;
+	}
+
+	/**
+     * file
+     *
+     * @return mixed
+     */
+	public function file($name = '')
+	{
+        if(isset(Config::$global['base']['data']))
+        {
+            $path = Config::$global['base']['data'];
+        }
+        else
+        {
+            $path = DEVER_PATH . 'data/';
+        }
+
+        if($name)
+        {
+        	$name = $this->table . '_' . $name . '.php';
+        }
+        else
+        {
+        	$name = $this->table . '.php';
+        }
+
+        $temp = explode('_', $this->table);
+
+		$file = Path::create($path . 'database/', $temp[0] . '/' . $name);
+		return $file;
+	}
+
+	/**
+     * create
+     *
+     * @return mixed
+     */
+	public function create($struct, $name = '', $type = 'innodb')
+	{
+        if(isset(Config::$global['base']['create']))
+        {
+            return false;
+        }
+        $file = $this->file($name);
+        if(is_file($file))
+        {
+            return include($file);
+        }
+
+        if(isset($this->sql))
+        {
+        	$sql = $this->sql->create($this->table, $struct, $type);
+
+        	$this->exe($sql);
+
+        	$this->log($sql, 'create');
+        }
+        
+        $data['time'] = DEVER_TIME;
+        
+        $data['table'] = $this->table;
+        
+        if(isset($this->sql))
+        {
+        	$data['create'] = $sql;
+
+        	$data['struct'] = array_flip(array_keys($struct));
+        }
+        else
+        {
+        	$data['create'] = $struct;
+
+        	$this->log($data, 'create');
+        }
+
+        file_put_contents($file, '<?php return ' . var_export($data, true) . ';');
+        
+        return true;
+	}
+
+    private function truncate()
+    {
+        if(isset($this->sql))
+        {
+            $sql = $this->sql->truncate($this->table);
+
+            $this->exe($sql);
+
+            $this->log($sql, 'truncate');
+        }
+    }
+
+	/**
+     * page
+     *
+     * @return object
+     */
+    public function page($num, $config = array())
+    {
+        $this->reset('limit');
+
+        empty($config[0]) && $config[0] = 'list';
+
+        empty($config[1]) && $config[1] = 'current';
+
+        empty($config[2]) && $config[2] = '';
+
+        $page = Page::getInstance($config[1]);
+
+        $page->template($config[0]);
+
+        $page->link($config[2]);
+
+        $total = Input::get('pt', -1);
+
+        if($total < 0)
+        {
+            $total = $this->count('clear');
+        }
+
+        $page->total($total);
+        
+        $this->limit($num, $page->offset($num));
+
+        return $this;
+    }
+
+
+    public function cache($key = false, $data = array())
+    {
+        $cache = isset($this->config['cache']) ? $this->config['cache'] : Config::$global['cache'];
+        if(empty($cache['mysql']))
+        {
+            return;
+        }
+
+        $handle = Handle::getInstance('mysql', $cache['mysql']);
+        if(!$key)
+        {
+            $keys = $handle->get($this->table);
+            if($keys)
+            {
+                foreach($keys as $k => $v)
+                {
+                    $handle->delete($k);
+                }
+            }
+        }
+        if($data)
+        {
+            $keys = $handle->get($this->table);
+            $keys[$key] = 1;
+
+            $handle->set($this->table, $keys);
+
+            return $handle->set($key, $data);
+        }
+        return $handle->get($key);
+    }
+
+    /**
+     * error
+     *
+     * @return error
+     */
+    public function error($msg, $sql = '')
+    {
+        if(isset($this->sql))
+        {
+            if($sql)
+            {
+                $msg = array('sql' => $sql, 'error' => $msg);
+            }
+            elseif(is_object($msg))
+            {
+                $msg = (array) $msg;
+            }
+            elseif(is_string($msg))
+            {
+                $msg = array('sql' => $msg);
+            }
+            Debug::wait($msg, 'Dever SQL DB Error!');
+        }
+        else
+        {
+            if(is_string($msg))
+            {
+                $msg = array('value' => $msg);
+            }
+            Debug::wait($msg, 'Dever NOSQL DB Error!');
+        }
+    }
+
+    /**
+     * log
+     *
+     * @return log
+     */
+    public function log($value, $param, $data = array())
+    {
+    	if(isset($this->sql))
+    	{
+    		Debug::log(array('sql' => $value, 'value' => $param, 'data' => $data), 'db');
+    	}
+    	else
+    	{
+    		Debug::log(array('value' => $value), 'db');
+    	}
+    }
+}

+ 7 - 0
vendor/dever-main/framework/src/Dever/Debug/Log.php

@@ -0,0 +1,7 @@
+<?php namespace Dever\Debug;
+
+
+class Log
+{
+	
+}

+ 245 - 0
vendor/dever-main/framework/src/Dever/Debug/Process.php

@@ -0,0 +1,245 @@
+<?php namespace Dever\Debug;
+
+use Dever;
+use Dever\Config\Load as Config;
+use Dever\Http\Input;
+use Dever\Http\Output;
+
+class Process
+{
+	static private $data;
+
+	static private $tool;
+
+	static private $time;
+
+	static private $memory;
+
+	static public function init()
+	{
+		if(isset(Config::$global['debug']['request']) && Config::$global['debug']['request'])
+		{
+			$request = Input::get(Config::$global['debug']['shell']) == 'request';
+			if(is_string(Config::$global['debug']['request']))
+			{
+				if(strpos(Config::$global['debug']['request'], Dever::ip()) !== false)
+				{
+					if($request)
+					{
+						return true;
+					}
+				}
+			}
+			elseif(Config::$global['debug']['request'] === 2 || $request)
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
+	static public function report()
+	{
+		ini_set('display_errors', true);
+		self::tool();
+	}
+
+	static private function tool()
+	{
+		if(self::$tool)
+		{
+			return true;
+		}
+		if(class_exists('\\Whoops\\Run'))
+		{
+			self::$tool = new \Whoops\Run;
+			self::$tool->pushHandler(new \Whoops\Handler\PrettyPageHandler);
+			if(\Whoops\Util\Misc::isAjaxRequest())
+			{
+			    self::$tool->pushHandler(new \Whoops\Handler\JsonResponseHandler);
+			}
+
+			self::$tool->register();
+
+			return true;
+		}
+
+		return false;
+	}
+
+	static public function log($msg, $type = 'log')
+	{
+		if(self::init())
+		//if(true)
+		{
+			if(isset($msg['value']) && isset($msg['sql']) && is_array($msg['value']))
+			{
+				foreach($msg['value'] as $k => $v)
+				{
+					$msg['sql'] = str_replace($k, $v, $msg['sql']);
+				}
+				unset($msg['value']);
+			}
+
+			$msg = Output::export(array('msg' => $msg, 'time' => array('current' => self::time(2), 'total' => self::time()),'memory' => array('current' => self::memory(2), 'total' => self::memory())), false, true);
+			
+			self::add($type, $msg);
+		}
+	}
+
+	static public function runtime()
+	{
+		if(self::init())
+		{
+			self::add('runtime', Output::export(self::loadfile(),false, true), 'Load Files');
+
+			$msg = Output::export(array('time' => self::time(), 'memory' => self::memory()), false, true);
+
+	        self::add('runtime', $msg, 'Total');
+		}
+	}
+
+	static private function time($state = 1)
+	{
+		$start = DEVER_START;
+		if($state == 2 && self::$time)
+		{
+			$start = self::$time;
+		}
+		list($a, $b) = explode(' ', $start); 
+        $s = ((float)$a + (float)$b);
+
+        self::$time = microtime();
+
+		list($a, $b) = explode(' ', self::$time); 
+        $e = ((float)$a + (float)$b);
+
+        return '[' . ($e - $s) . 'S]';
+	}
+
+	static private function memory($state = 1)
+	{
+		$memory = memory_get_usage();
+		if($state == 2 && self::$memory)
+		{
+			$memory = $memory - self::$memory;
+		}
+		self::$memory = $memory;
+		
+        return '[' . ($memory/1024) . 'KB]';
+	}
+
+	static private function loadfile()
+	{
+        return get_included_files();
+	}
+
+	static private function add($method, $msg, $key = false)
+	{
+		if($key)
+		{
+			self::$data[$method][$key] = $msg;
+		}
+		else
+		{
+			self::$data[$method][] = $msg;
+		}
+	}
+
+	static public function wait($msg = '', $notice = 'Dever Data Debug!')
+	{
+		if($msg && self::tool())
+		{
+			$handler = self::$tool->getHandlers();
+			if(self::$data && is_array(self::$data))
+			{
+				foreach(self::$data as $k => $v)
+				{
+					$handler[0]->addDataTable(ucwords($k), $v);
+				}
+			}
+			if(is_array($msg))
+			{
+				$msg = array('array' => Output::export($msg, false, true));
+			}
+			$handler[0]->addDataTable('Data', $msg);
+			throw new \RuntimeException($notice);
+		}
+		else
+		{
+			print_r($msg);
+		}
+		die;
+	}
+
+	static public function data()
+	{
+		if(self::init())
+		{
+			self::out();
+		}
+	}
+
+	static public function out()
+	{
+		self::runtime();
+
+		if(self::$data && is_array(self::$data))
+		{
+			if(self::tool())
+			{
+				$handler = self::$tool->getHandlers();
+
+				foreach(self::$data as $k => $v)
+				{
+					$handler[0]->addDataTable(ucwords($k), $v);
+				}
+				throw new \RuntimeException("Dever Runtime Debug!");
+			}
+			else
+			{
+				echo self::html();
+			}
+		}
+	}
+
+	static private function html($show = 'display:none;')
+	{
+		self::runtime();
+
+		$fix = 'fixed';
+		if(!$show)
+		{
+			$fix = '';
+		}
+		$html = '<div style="position:'.$fix.';z-index:10000;bottom:0;background:white;overflow:auto;width:100%;height:auto;">';
+		
+		if(self::$data)
+		{
+			foreach(self::$data as $k => $v)
+			{
+				$html .= '<a style="font-size:14px;font-weight:bold;margin-left:5px;" href="javascript:;" onclick="var a = $(this).next();if(a.get(0).style.display == \'none\'){a.show();$(this).parent().height(500)}else if(a.get(0).style.display != \'none\'){a.hide();$(this).parent().height(\'auto\')}">' . $k . '</a>';
+				
+				$html .= '<div style="'.$show.'">';
+				$html .= '<table border="1" style="width:100%;">';
+				
+				foreach($v as $i => $j)
+				{
+					$html .= '<tr>';
+					
+					$html .= '<td>' . $j . '</td>';
+					
+					$html .= '</tr>';
+				}
+				
+				$html .= '</table>';
+				
+				$html .= '</div>';
+			}
+		}
+
+		$html .= '</div>';
+		
+		return $html;
+	}
+}

+ 46 - 0
vendor/dever-main/framework/src/Dever/File/Path.php

@@ -0,0 +1,46 @@
+<?php namespace Dever\File;
+
+class Path
+{
+    /**
+     * create
+     * @param string $path
+     * @param string $file
+     *
+     * @return array
+     */
+    static public function create($path, $file = '')
+    {
+        if(!is_dir($path))
+        {
+            mkdir($path);
+            @chmod($path, 0755);
+            @system('chmod -R 777 ' . $path);
+        }
+
+        $file = str_replace('/', DIRECTORY_SEPARATOR, $file);
+        
+        if($file && strpos($file, DIRECTORY_SEPARATOR) !== false)
+        {
+            $array = explode(DIRECTORY_SEPARATOR, $file);
+            $count = count($array)-2;
+            for($i = 0; $i <= $count; $i++)
+            {
+                $path .= $array[$i] . DIRECTORY_SEPARATOR;
+                if(!is_dir($path))
+                {
+                    mkdir($path);
+                    @chmod($path, 0755);
+                    @system('chmod -R 777 ' . $path);
+                }
+            }
+            $path .= $array[$i];
+        }
+        else
+        {
+            $path .= $file;
+        }
+
+        return $path;
+    }
+}

+ 169 - 0
vendor/dever-main/framework/src/Dever/Http/Input.php

@@ -0,0 +1,169 @@
+<?php namespace Dever\Http;
+
+use Dever\Security\String;
+use Dever\Config\Load as Config;
+
+class Input
+{
+	/**
+     * term
+     *
+     * @var array
+     */
+	static public $request = array();
+
+	/**
+     * term
+     *
+     * @var bool
+     */
+	static public $term = false;
+
+	/**
+     * init
+     *
+     * @return array
+     */
+	static public function init()
+	{
+		global $argc,$argv;
+
+		#如果参数大于 ,就说明有参数
+		if($argc > 1)
+		{
+			#分析并保存Term数据
+			$term = array();
+			$key = '';
+			#第一位是程序名称,不用分析
+			for($i=1; $i<$argc; $i++)
+			{
+				#以“-”开头,说明是变量,保存Key值
+				if(substr($argv[$i],0,1) == '-' || substr($argv[$i],0,1) == '^')
+				{
+					#上一个Key还未失效,就赋值为空
+					if($key != '')
+					{
+						$term[$key] = $key;
+					}
+					$key = substr($argv[$i],1);
+					continue;
+				}
+				#有Key设置为key,否则设置此变量为Key
+				if($key != '')
+				{
+					$term[$key] = $argv[$i];
+					$key = '';
+				}
+				else
+				{
+					$term[$argv[$i]] = $argv[$i];
+				}
+			}
+
+			self::$request = $term;
+			self::$term = true;
+		}
+		else
+		{
+			self::$request = array_merge($_GET, $_POST, $_FILES);
+			self::$term = false;
+		}
+
+		return true;
+	}
+
+	/**
+     * get
+     * @param string $name
+     *
+     * @return array
+     */
+	static public function get($name = false, $default = '')
+	{
+		if(!$name) return self::$request;
+
+		if($default && $default == '-u')
+		{
+			$array = array('update_', 'set_', 'add_');
+			foreach($array as $k => $v)
+			{
+				if(isset(self::$request[$v . $name]))
+				{
+					return String::xss(self::$request[$v . $name]);
+				}
+			}
+			return false;
+		}
+		
+		if(is_string($name) && isset(self::$request[$name]) && self::$request[$name])
+		{
+			$default = String::xss(self::$request[$name]);
+		}
+
+		if(isset(Config::$global['host']['url_encode']))
+		{
+			$config = Config::$global['host']['url_encode'];
+			if($config && in_array($name, $config) && is_string($default))
+			{
+				$method = Config::$global['host']['url_encode_method'][1];
+				$default = $method($default);
+			}
+		}
+		return $default;
+	}
+
+	/**
+     * prefix 获取包含有该前缀的值
+     * @param string $name
+     *
+     * @return array
+     */
+	static public function prefix($name)
+	{
+		$key = 'prefix_' . $name;
+		if(isset(self::$request[$key]))
+		{
+			return self::$request[$key];
+		}
+		self::$request[$key] = array();
+
+		foreach(self::$request as $k => $v)
+		{
+			if(strpos($k, $name) === 0)
+			{
+				self::$request[$key][$k] = String::xss($v);
+			}
+		}
+
+		return self::$request[$key];
+	}
+
+	/**
+     * set
+     * @param string $name
+     *
+     * @return array
+     */
+	static public function set($name, $value = '', $prefix = false)
+	{
+		if($name == 'all' && is_array($value))
+		{
+			self::$request = array_merge(self::$request, $value);
+		}
+		else
+		{
+			self::$request[$name] = $value;
+		}
+		
+		if($prefix)
+		{
+			$prefix = 'prefix_' . $prefix;
+			if(isset(self::$request[$prefix]))
+			{
+				self::$request[$prefix][$name] = $value;
+			}
+		}
+
+		return $value;
+	}
+}

+ 243 - 0
vendor/dever-main/framework/src/Dever/Http/Output.php

@@ -0,0 +1,243 @@
+<?php namespace Dever\Http;
+
+use Dever\Config\Lang;
+use Dever\Config\Load as Config;
+use Dever\Http\Url;
+use Dever\Debug\Process as Debug;
+use Dever\Page\Main as Page;
+
+class Output
+{
+	
+	static public function result($msg, $print = true, $array = true)
+	{
+		$json 		= Input::get('json', false);
+		$callback 	= Input::get('callback', false);
+		$function 	= Input::get('function', false);
+
+		/*
+		if(!is_array($msg) && ($callback || $array == true))
+		{
+			$result = self::msg($msg, array(), 1);
+		}
+		else
+		{
+			$result = self::msg($msg, array(), 1);
+		}
+		*/
+		if($array == false)
+		{
+			$result = $msg;
+		}
+		else
+		{
+			$result = self::msg($msg, array(), 1);
+		}
+
+		if(is_array($result))
+		{
+			//JSON_FORCE_OBJECT
+			$result = json_encode($result);
+		}
+		
+		($json != false && is_array($result)) && $result = json_encode($result);
+		$callback != false && $callback != '?'	&& $result = $callback . '('.$result.')';
+		$function != false  && $result = '<script>parent.'.$function.'('.$result.')'.'</script>';
+
+		if($print == true)
+		{
+			self::export($result, true);
+		}
+
+		return $result;
+	}
+
+	/**
+     * export
+     * @param string $text
+     *
+     * @return string
+     */
+	static public function export($text, $exit = false, $return = false)
+	{
+		if(is_array($text))
+		{
+			$callback 	= Input::get('callback', false);
+			if($callback)
+			{
+				$content = $callback . '('.json_encode($text).')';
+			}
+			else
+			{
+				$content = "<pre>\n";
+		        $content .= htmlspecialchars(print_r($text, true));
+		        $content .= "\n</pre>\n";
+			}
+
+			if($return) return $content;
+			print_r($content);
+		}
+		else
+		{
+			if($return) return $text;
+			echo $text;
+		}
+
+		if($exit == true)
+		{
+			Debug::data();
+			
+			die;
+		}
+	}
+
+	/**
+     * msg
+     * @param string $msg
+     *
+     * @return string
+     */
+   static public function msg($msg, $param = array(), $status = 2)
+   {
+   		$send = array();
+   		if(is_array($msg))
+   		{
+   			$send = $msg;
+   		}
+   		else
+   		{
+   			if(is_numeric($msg))
+			{
+				$send['code'] = $msg;
+				$send['msg'] = Lang::get($msg, $param);
+			}
+			else
+			{
+				if(is_numeric($param))
+				{
+					$send['code'] = $param;
+					$param = array();
+				}
+				$send['msg'] = Lang::get($msg, $param);
+				if(empty($send['code']))
+				{
+					$send['status'] = $status;
+				}
+			}
+   		}
+
+		if($status == 1)
+		{
+			$send['code'] = 1;
+
+			$page = self::page();
+			if($page)
+			{
+				$send['page'] = $page;
+			}
+		}
+
+		$eof = Input::get('eof');
+		if($eof == 1)
+		{
+			$send['eof'] = 1;
+		}
+
+		return $send;
+   }
+
+   /**
+     * page
+     * @param string $msg
+     *
+     * @return string
+     */
+	static public function page($method = 'current', $page = array(), $state = true)
+	{
+		if($state == false)
+		{
+			Config::$global['page'][$method] = $state;
+		}
+		if($page)
+		{
+			Config::$global['page'][$method] = $page;
+		}
+		elseif(empty(Config::$global['page'][$method]))
+		{
+			Config::$global['page'][$method] = false;
+			$page = Page::getInstance('current');
+			$total = $page->total();
+			if($total > 0)
+			{
+				$current = $page->current();
+				$all = $page->getAllPage();
+				$status = 1;
+				if($current >= $all)
+				{
+					$status = 0;
+				}
+				Config::$global['page'][$method] = array
+				(
+					'total' => $total,
+					'current_page' => $current,
+					'total_page' => $all,
+					'next_page' => $page->next(),
+					'prev_page' => $page->prev(),
+					'html' => $page->get(),
+					'status' => $status,
+				);
+			}
+		}
+
+		return Config::$global['page'][$method];
+	}
+	
+	/**
+     * out
+     * @param string $msg
+     *
+     * @return string
+     */
+	static public function abert($msg, $param = array())
+	{
+		$send = self::msg($msg, $param, 2);
+
+		if($param)
+		{
+			$send['param'] = $param;
+		}
+		
+		$callback 	= Input::get('callback', false);
+		$json 		= Input::get('json', false);
+		$function 	= Input::get('function', false);
+		
+		if($callback || $json || $function || strpos($msg, '_array'))
+		{
+			self::result($send);
+		}
+		else
+		{
+			self::html($send);die;
+		}
+		//self::export($send, true);
+	}
+	
+	/**
+     * out
+     * @param string $msg
+     *
+     * @return string
+     */
+	static public function html($msg)
+	{
+		$html = '' . $msg['msg'] . '(状态码:'.$msg['status'].')';
+		$host = Url::get('');
+		$file = DEVER_APP_PATH . 'config/html/404.html';
+		if(is_file($file))
+		{
+			include($file);
+			return;
+		}
+		include(DEVER_PATH . 'config/html/index.html');
+	}
+}

+ 232 - 0
vendor/dever-main/framework/src/Dever/Http/Url.php

@@ -0,0 +1,232 @@
+<?php namespace Dever\Http;
+
+use Dever\Http\Output;
+use Dever\Config\Load as Config;
+use Dever\Config\Project;
+use Dever\Routing\Uri;
+
+class Url
+{
+	/**
+     * config
+     *
+     * @var array
+     */
+    static public $config;
+
+	/**
+     * link
+     * @param string $value
+     *
+     * @return array
+     */
+	static public function get($value = false, $project = false, $replace = false)
+	{
+		if($replace)
+		{
+			# 这里貌似暂时没啥用了。先保留吧。
+			return str_replace('{'.$replace.'}', $value, Config::$global['host']['domain']);
+		}
+		
+		if($value === false)
+		{
+			$value = Uri::$url ? Uri::$url : '';
+		}
+
+		# 为value增加默认参数
+		if(isset(Config::$global['base']['url']) && Config::$global['base']['url'])
+		{
+			if(strpos($value, '?') === false)
+			{
+				$value .= '?' . Config::$global['base']['url'];
+			}
+			else
+			{
+				$value .= '&' . Config::$global['base']['url'];
+			}
+		}
+		
+		if(strpos($value, 'http://') !== false)
+		{
+			return $value;
+		}
+
+		$host = '';
+		self::host($host, $value, $project);
+		
+		$key = $value;
+
+		if(isset(self::$config['url']) && isset(self::$config['url'][$key]))
+		{
+			return self::$config['url'][$key];
+		}
+
+		Config::get('route', $project);
+
+		if(Config::$global['route'])
+		{
+			if(strpos($value, '?') !== false)
+			{
+				$arg = explode('?', $value);
+				$value = $arg[0];
+			}
+
+			if($uri = array_search($value, Config::$global['route']))
+			{
+				$value = $uri;
+			}
+			if(isset($arg[1]) && $arg[1])
+			{
+				parse_str($arg[1], $out);
+
+				$str = $pre = '';
+				$i = 1;
+				self::$config['link_key'] = self::$config['link_value'] = array();
+				self::$config['link_source'] = $arg[0];
+				foreach($out as $k => $v)
+				{
+					if($i > 1)
+					{
+						$pre = '&';
+					}
+					$str .= $pre . $k . '=$' . $i;
+					$i++;
+					
+					self::$config['link_key'][] = $k;
+					self::$config['link_value'][] = $v;
+				}
+				
+				self::$config['link_index'] = 0;
+
+				$result = '';
+
+				if($key = array_search($value . '?' . $str, Config::$global['route']))
+				{
+					$result = preg_replace_callback('/\(.*?\)/', 'self::link', $key);
+				}
+
+				if(!$result || $result == $value)
+				{
+					$value = $value . '?' . $arg[1];
+				}
+				else
+				{
+					$value = $result;
+				}
+			}
+			else
+			{
+				$index = strpos($value, '?');
+				if($index === false)
+				{
+					$value = preg_replace('/&/', '?', $value, 1);
+				}
+			}
+		}
+
+		if($value && isset(Config::$global['host']['workspace']) && strpos($host, Config::$global['host']['workspace']) !== false)
+		{
+			$path = str_replace(Config::$global['host']['workspace'], '', $host);
+			if($path && strpos($value, $path) !== false)
+			{
+				$value = str_replace($path, '', $value);
+			}
+		}
+
+		return self::$config['url'][$key] = $host  . Uri::$type . $value;
+	}
+
+	static private function host(&$host, &$value, &$project)
+	{
+		if(strpos($value, '/') !== false && (strpos($value, '.') !== false || strpos($value, '--') !== false))
+		{
+			$temp = explode('/', $value);
+			$config = Project::load($temp[0]);
+			if($config)
+			{
+				$value = $temp[1];
+				$project = $temp[0];
+				$host = $config['url'];
+			}
+			unset($temp);
+		}
+		elseif($project)
+		{
+			$config = Project::load($project);
+			if($config)
+			{
+				$host = $config['url'];
+			}
+		}
+
+		if(!$host)
+		{
+			$host = Config::$global['host']['base'];
+		}
+	}
+
+	static private function link($param)
+	{
+		if(isset($param[0]) && $param[0] && isset(self::$config['link_value']) && isset(self::$config['link_value'][self::$config['link_index']]))
+		{
+			if(isset(Config::$global['host']['url_encode']))
+			{
+				$config = Config::$global['host']['url_encode'];
+				if($config)
+				{
+					$filter = isset(Config::$global['host']['url_encode_filter']) ? Config::$global['host']['url_encode_filter'] : false;
+					if($filter && self::$config['link_source'])
+					{
+						foreach($filter as $k => $v)
+						{
+							if(strpos(self::$config['link_source'], $v) !== false)
+							{
+								$config = false;
+								break;
+							}
+						}
+					}
+
+					if($config && is_numeric(self::$config['link_value'][self::$config['link_index']]) && in_array(self::$config['link_key'][self::$config['link_index']], $config))
+					{
+						$method = Config::$global['host']['url_encode_method'][0];
+						self::$config['link_value'][self::$config['link_index']] = $method(self::$config['link_value'][self::$config['link_index']]);
+					}
+				}
+			}
+
+			$param[0] = self::$config['link_value'][self::$config['link_index']];
+		}
+		self::$config['link_index']++;
+		
+		return $param[0];
+	}
+
+	/**
+     * location
+     * @param string $value
+     *
+     * @return mixed
+     */
+	static public function location($value, $type = 1)
+	{
+		if(strpos($value, 'http://') === false && strpos($value, 'https://') === false)
+		{
+			$value = self::get($value);
+		}
+		switch($type)
+		{
+			case 2 :
+				$html = '<script>location.href="' . $value . '"</script>';
+				Output::abert($html);
+				die;
+				break;
+
+			default : 
+				header('HTTP/1.1 301 Moved Permanently');
+				header('Location: ' . $value);
+				die;
+				break;
+		}
+	}
+}

+ 1419 - 0
vendor/dever-main/framework/src/Dever/Img/Handle.php

@@ -0,0 +1,1419 @@
+<?php namespace Dever\Img;
+
+use Imagick;
+use ImagickDraw;
+
+class Handle
+{
+    /**
+     * @desc 使用的图片转换类型,默认是gd库,也可以用imagemagick,值为im
+     * @var string
+     */
+    private $_type = 'im';//另一个值是im
+
+    /**
+     * @desc 进行缩略图 值为'600_100,100_200'
+     * @var string
+     */
+    private $_thumb = '';
+
+    /**
+     * @desc 进行裁切图 值为'600_100,100_200'
+     * @var string
+     */
+    private $_crop = '';
+
+    /**
+     * @desc 如果文件存在,值为true则强制再次操作,默认为false
+     * @var string
+     */
+    private $_setup = false;
+
+    /**
+     * @desc 图片水平位置 0=>100 1=>100
+     * @var string
+     */
+    private $_position = array();
+
+    /**
+     * @desc 源文件
+     * @var string
+     */
+    private $_source;
+    
+    /**
+     * @desc 裁切图片时候需要抛弃的大小
+     * @var string
+     */
+    private $_dropSize = array();
+
+    /**
+     * @desc 目标文件
+     * @var string
+     */
+    private $_dest = array();
+
+    /**
+     * @desc 添加水印图片
+     * @var array
+     */
+    private $_mark = array();
+
+    /**
+     * @desc 添加文字
+     * @var array
+     */
+    private $_txt = array();
+
+    /**
+     * @desc image的源信息
+     * @var array
+     */
+    private $_image = null;
+
+    /**
+     * @desc image的类型
+     * @var array
+     */
+    private $_imageType = null;
+    
+    /**
+     * @desc 图片压缩的清晰度
+     * @var int
+     */
+    private $_quality = 20;
+
+    /**
+     * @desc 生成的图片名
+     * @var int
+     */
+    private $_name = null;
+
+    /**
+     * @desc 设置图片库类型
+     * @param type(string) 类型
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setType($type)
+    {
+        $this->_type = $type;
+        return $this;
+    }
+    
+    /**
+     * @desc 设置清晰度
+     * @param quality(int) 清晰度
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setQuality($quality)
+    {
+        $this->_quality = $quality;
+        return $this;
+    }
+
+    /**
+     * @desc 设置强制功能
+     * @param setup(bool) 是否强制再次生成重复的文件
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setSetup($setup)
+    {
+        $this->_setup = $setup;
+        return $this;
+    }
+
+    /**
+     * @desc 设置缩略图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setThumb($thumb)
+    {
+        $this->_thumb = $thumb;
+        
+        return $this;
+    }
+
+    /**
+     * @desc 设置裁切图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setCrop($crop)
+    {
+        $this->_crop = $crop;
+        return $this;
+    }
+
+    /**
+     * @desc 设置生成的文件名
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setName($name)
+    {
+		if(is_string($name)) $name = explode(',', $name);
+        $this->_name = $name;
+        return $this;
+    }
+
+    /**
+     * @desc 设置位置
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setPosition($position)
+    {
+        $this->_position = $position;
+        return $this;
+    }
+
+    /**
+     * @desc 设置水印
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setMark($mark)
+    {
+        $this->_mark = $mark;
+        $this->_check('mark', 'water');
+        $this->_check('mark', 'position');
+        return $this;
+    }
+
+    /**
+     * @desc 设置文字
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setTxt($txt)
+    {
+        $this->_txt = $txt;
+        
+        return $this;
+    }
+
+    /**
+     * @desc 设置源文件
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function setSource($source)
+    {
+        $this->_source = $source;
+        $this->_check('source');
+        $this->_image();
+        return $this;
+    }
+
+    /**
+     * @desc 获取生成的图片名字
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function getName($name = false, $key = false)
+    {
+		if($this->_name)
+		{
+			if($key)
+			{
+				return $this->_name[$key];
+			}
+			return $this->_name[0];
+		}
+		else
+		{
+			return $this->_source . $name;
+		}
+    }
+
+    /**
+     * @desc 获取目标文件
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function getDest($key = false)
+    {
+        return ($key && isset($this->_dest[$key])) ? $this->_dest[$key] : $this->_desc;
+    }
+    
+    /**
+     * @desc 获取宽高
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function getSize($source)
+    {
+		$this->setSource($source);
+		$this->_image();
+		return array($this->_image->getImageWidth(), $this->_image->getImageHeight());
+	}
+
+    /**
+     * @desc 添加水印图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function mark($source, $water, $setup = false, $name = false)
+    {
+        if($setup == true)
+        {
+            $this->setSetup($setup);
+        }
+        $this->setSource($source);
+        if($name) $this->setName($name);
+        $this->setMark($water);
+        //if($position) $this->setPosition($position);
+        $this->loadMethod('mark');
+        return $this->getDest('mark');
+    }
+    
+    /**
+     * @desc 对图片进行压缩处理
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function compress($source, $quality = 20, $name = false)
+    {
+        $this->setSource($source);
+        if($name) $this->setName($name);
+        $this->setQuality($quality);
+        $this->loadMethod('compress');
+        return $this->getDest('compress');
+    }
+
+    /**
+     * @desc 构造函数 可批量建立
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function __construct($config = array())
+    {
+        if($config)
+        {
+            $this->init($config);
+        }
+    }
+
+    /**
+     * @desc 批量建立
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function init($config)
+    {
+        $this->setSource($config['source']);
+        if(isset($config['setup']) && $config['setup'] == true)
+        {
+            $this->setSource($config['setup']);
+        }
+        unset($config['source']);
+        foreach($config as $k => $v)
+        {
+            $this->$k($config['source'], $v);
+        }
+        return $this->getDest();
+    }
+
+    /**
+     * @desc 建立缩略图(原比例缩略)
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function thumb($source, $thumb, $setup = false, $name = false)
+    {
+        if($setup == true)
+        {
+            $this->setSetup($setup);
+        }
+        $this->setSource($source);
+        if($name) $this->setName($name);
+        $this->setThumb($thumb);
+        $this->loadMethod('thumb');
+        $this->_name = false;
+        return $this->getDest('thumb');
+    }
+
+    /**
+     * @desc 建立剪切图(从图中剪切)
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function crop($source, $crop, $position = false, $setup = false, $name = false)
+    {
+        if($setup == true)
+        {
+            $this->setSetup($setup);
+        }
+        $this->setSource($source);
+        if($position) $this->setPosition($position);
+        if($name) $this->setName($name);
+        $this->setCrop($crop);
+        $this->loadMethod('crop');
+        $this->_name = false;
+        return $this->getDest('crop');
+    }
+    
+    /**
+     * @desc 建立剪切图(从图中剪切)
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function thumbAndCrop($source, $size, $dropSize = array(), $position = false, $setup = true, $name = false)
+    {
+        if($setup == true)
+        {
+            $this->setSetup($setup);
+        }
+        
+        $this->setSource($source);
+        if($position) $this->setPosition($position);
+        if($name) $this->setName($name);
+        $this->setCrop($size);
+        
+        if($this->_imageType != 'gif')
+        {
+			$this->setThumb($size);
+			$this->_next = true;
+			$this->loadMethod('thumb');
+			$this->_dropSize = $dropSize;
+		}
+        
+        $this->loadMethod('crop');
+        return $this->getDest('crop');
+    }
+
+    /**
+     * @desc 加入文字
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function txt($source, $txt, $setup = false, $name = false)
+    {
+        if($setup == true)
+        {
+            $this->setSetup($setup);
+        }
+        $this->setSource($source);
+        if($name) $this->setName($name);
+        $this->setTxt($txt);
+        $this->loadMethod('txt');
+        return $this->getDest('txt');
+    }
+
+    /**
+     * @desc 载入方法
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function loadMethod($method)
+    {
+        if($this->_type == 'im' && !class_exists('Imagick')) $this->_type = 'gd';
+        $method = '_' . $this->_type . '_create_' . $method;
+        $this->$method();
+    }
+
+    /**
+     * @desc 对变量进行检测
+     * @param name(string) 变量名称
+     * @author leo(suwi.bin)
+     * @date 2012-04-5
+     */
+    private function _check($name, $key = false)
+    {
+        $name = '_' . $name;
+        if($name == '_mark')
+        {
+			return $this->_mark[$key];
+		}
+        if(isset($this->$name) && $this->$name)
+        {
+			if($key == false)
+			{
+				return $this->$name;
+			}
+			else
+			{
+				return $this->$name[$key];
+			}
+        }
+        else
+        {
+            $this->_error($name . ' error');
+        }
+    }
+
+    /**
+     * @desc 匹配错误
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _error($string, $type = 1)
+    {
+        $errstr = '' ;
+        $errstr .= "Img Tool Error:" . $string . "\n";
+        return $errstr;
+    }
+
+    /**
+     * @desc 获取文件源信息
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _image()
+    {
+        $this->_check('source');
+        switch($this->_type)
+        {
+            case 'gd' :
+                $this->_image = $this->_gd_get($this->_source);
+                break;
+            case 'im' :
+                $this->_image = new Imagick($this->_source);
+                $this->_imageType = strtolower($this->_image->getImageFormat());
+                break;
+        }
+        return $this->_image;
+    }
+    
+    /*********************
+     * gd库函数
+     *********************/
+
+    /**
+     * @desc 水印
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_create_mark()
+    {
+        $this->_check('image');
+        $this->_check('mark', 'water');
+        $this->_check('mark', 'position');
+
+        $this->_dest['mark'] = $this->getName('_mark.jpg');
+
+        if($this->_setup == true || !file_exists($this->_dest['mark']))
+        {
+            $water  = $this->_gd_get($this->_mark['water']);
+            $source_x = imagesx($this->_image);
+            $source_y = imagesy($this->_image);
+            $water_x = imagesx($water);
+            $water_y = imagesy($water);
+            $xy      = $this->_get_mark($source_x, $source_y, $water_x, $water_y);
+
+            if($xy[2] == false)
+            {
+                $this->_gd_destroy($this->_image);
+                $this->_gd_destroy($water);
+                return;
+            }
+
+            $im = $this->_gd_copy($water, $water_x, $water_y, 0, 0, $l, $t, $this->_image);
+
+            imagejpeg($im, $this->_dest['mark']);
+
+            $this->_gd_destroy($this->_image);
+            $this->_gd_destroy($water);
+        }
+        $this->_image = false;
+    }
+
+    /**
+     * @desc 建立缩略图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_create_thumb()
+    {
+        $this->_check('image');
+        $this->_check('thumb');
+        if(!is_array($this->_thumb))
+        {
+			$array = explode(',',$this->_thumb);
+		}
+		else
+		{
+			$array = $this->_thumb;
+		}
+        $source_x = imagesx($this->_image);
+        $source_y = imagesy($this->_image);
+        $source_w = $source_x/$source_y;
+        $source_h = $source_y/$source_x;
+        foreach($array as $k => $v)
+        {
+            $this->_dest['thumb'][$k] = $this->getName('_' . $v . '_thumb.jpg', $k);
+            if($this->_setup == true || !file_exists($this->_dest['thumb'][$k]))
+            {
+                $offset = explode('_',$v);
+                if(isset($offset[2]) && $offset[2] == 1)
+                {
+                    if($source_x > $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($offset[1] > 0 && $source_y > $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    else
+                    {
+                        $dest_x = $source_x;
+                        $dest_y = $source_y;
+                    }
+                }
+                elseif(isset($offset[2]) && $offset[2] == 2)
+                {
+                    //按照一定比例
+                    if($source_x > $source_y && $source_y > $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y > $source_x && $source_x > $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    else
+                    {
+                        $dest_x = $source_x;
+                        $dest_y = $source_y;
+                    }
+                }
+                else
+                {
+                    $dest_x = $offset[0];
+                    $dest_y = $offset[1];
+                }
+
+                $im = $this->_gd_copy($this->_image,$dest_x,$dest_y,$source_x,$source_y,0,0,false,1);
+
+                imagejpeg($im, $this->_dest['thumb'][$k]);
+                $this->_gd_destroy($im);
+            }
+        }
+
+        $this->_gd_destroy($this->_image);
+        $this->_image = false;
+    }
+
+    /**
+     * @desc 建立剪切图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_create_crop()
+    {
+        $this->_check('image');
+        $this->_check('crop');
+        //$this->_check('position');
+        if(!is_array($this->_crop))
+        {
+			$array = explode(',',$this->_crop);
+		}
+		else
+		{
+			$array = $this->_crop;
+		}
+        $source_x = imagesx($this->_image);
+        $source_y = imagesy($this->_image);
+        foreach($array as $k => $v)
+        {
+            $this->_dest['crop'][$k] = $this->getName('_' . $v . '_crop.jpg', $k);
+            if($this->_setup == true || !file_exists($this->_dest['crop'][$k]))
+            {
+                $offset = explode('_',$v);
+                $x = 0;
+                $y = 0;
+                if($this->_position)
+                {
+                    $x = $this->_position[0];
+                    $y = $this->_position[1];
+                }
+                $im = $this->_gd_copy($this->_image,$offset[0],$offset[1],$offset[0],$offset[1],$x,$y);
+
+                imagejpeg($im, $this->_dest['crop'][$k]);
+                $this->_gd_destroy($im);
+            }
+        }
+        $this->_gd_destroy($this->_image);
+        $this->_image = false;
+    }
+    
+    /**
+     * @desc 添加水印文字
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_create_txt()
+    {
+        $this->_check('source');
+        $this->_check('image');
+        //$this->_check('txt','file');
+        $this->_check('txt','color');
+        $this->_check('txt','size');
+        $this->_check('txt','angle');
+        $this->_check('txt','name');
+        //$this->_check('txt','left');
+        //$this->_check('txt','top');
+        //$this->_check('txt','bgcolor');
+        //$this->_check('txt','font');
+
+        $this->_dest['txt'] = isset($this->_txt['file']) ? $this->_txt['file'] : $this->getName('_txt.jpg');
+
+        if($this->_setup == true || !file_exists($this->_dest['txt']))
+        {
+
+            $color = $this->_txt['color'];
+            $this->_txt['left'] = isset($this->_txt['left']) ? $this->_txt['left'] : 0;
+            $this->_txt['top'] = isset($this->_txt['top']) ? $this->_txt['top'] : 0;
+            if(!empty($color) && (strlen($color)==7))
+            { 
+                $R = hexdec(substr($color,1,2)); 
+                $G = hexdec(substr($color,3,2)); 
+                $B = hexdec(substr($color,5)); 
+                putenv('GDFONTPATH=' . realpath('.'));
+                $fontFile = isset($this->_txt['font']) ? $this->_txt['font'] : "SIMSUN.TTC";
+                imagettftext($this->_image, $this->_txt['size'],$this->_txt['angle'], $this->_txt['left'], $this->_txt['top'], imagecolorallocate($this->_image, $R, $G, $B),$fontFile,$this->_txt['name']);
+            }
+
+            imagejpeg($this->_image, $this->_dest['txt']);
+            $this->_gd_destroy($this->_image);
+        }
+        $this->_image = false;
+    }
+
+    /**
+     * @desc 销毁资源
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_destroy($im)
+    {
+        imagedestroy($im);
+        return;
+    }
+
+    /**
+     * @desc copy
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_copy($im,$w,$h,$x,$y,$l,$t,$dim = false,$ti = 1)
+    {
+        if(false == $dim)
+        {
+            $dim = $this->_gd_create($w, $h,$ti); // 创建目标图gd2
+            imagecopyresized($dim,$im,0,0,$l,$t,$w,$h,$x,$y);
+        }
+        else
+        {
+
+            imagecopy($dim, $im, $l,$t, 0, 0, $w,$h);
+            //imagecopyresampled($dim, $im, $l,$t, 0, 0, $w,$h,$x,$y);
+        }
+        return $dim;
+    }
+
+    /**
+     * @desc 获取数据源
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_get($image)
+    {
+        $imgstream = file_get_contents($image);
+        $im = imagecreatefromstring($imgstream);
+        return $im;
+    }
+
+    /**
+     * @desc 创建背景图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _gd_create($w,$h,$t = 1)
+    {
+        $dim = imagecreatetruecolor($w,$h); // 创建目标图gd2
+
+        //透明背景
+        if($t == 2)
+        {
+            
+            imagealphablending($dim, false);
+            imagesavealpha($dim,true);
+            $transparent = imagecolorallocatealpha($dim, 255, 255, 255, 127);
+            imagefilledrectangle($dim, 0, 0, $w, $h, $transparent);
+            
+        }
+        
+        
+        //空白背景
+        if($t == 1)
+        {
+            $wite = ImageColorAllocate($dim,255,255,255);//白色
+            imagefilledrectangle($dim, 0, 0, $w,$h, $wite);
+            imagefilledrectangle($dim, $w, $h, 0,0, $wite);
+            ImageColorTransparent($dim, $wite);
+        }
+        
+        return $dim;
+    }
+
+    /*********************
+     * im库函数
+     *********************/
+
+    /**
+     * @desc 建立缩略图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _im_create_thumb()
+    {
+        $this->_check('source');
+        $this->_check('image');
+        $this->_check('thumb');
+        $source_x   = $this->_image->getImageWidth();
+        $source_y   = $this->_image->getImageHeight();
+        $source_w = $source_x/$source_y;
+        $source_h = $source_y/$source_x;
+
+        if(!is_array($this->_thumb))
+        {
+			$array = explode(',',$this->_thumb);
+		}
+		else
+		{
+			$array = $this->_thumb;
+		}
+        foreach($array as $k => $v)
+        {
+            $this->_dest['thumb'][$k] = $this->getName('_' . $v . '_thumb.jpg', $k);
+
+            if($this->_setup == true || !file_exists($this->_dest['thumb'][$k]))
+            {
+                $offset = explode('_',$v);
+
+                if(isset($offset[2]) && $offset[2] == 1)
+                {
+                    //完全等比例
+                    if($source_x > $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($offset[1] > 0 && $source_y > $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    else
+                    {
+                        $dest_x = $source_x;
+                        $dest_y = $source_y;
+                    }
+                }
+                elseif(isset($offset[2]) && $offset[2] == 2)
+                {
+                    //按照一定比例
+                    if($offset[0] == 0 && $offset[1] > 0)
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($offset[1] > 0 && $source_x > $source_y && $source_y > $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y > $source_x && $source_x > $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($source_y == $source_x && $offset[0] == $offset[1])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_x > $source_y && $source_y < $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y > $source_x && $source_x < $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($source_x > $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    else
+                    {
+                        $dest_x = $source_x;
+                        $dest_y = $source_y;
+                    }
+                }
+                elseif(isset($offset[2]) && $offset[2] == 3)
+                {
+                    //按照比例缩放,如有多余则留白(或黑...如果实在留不了白的话)
+                    $b = $offset[0]/$offset[1];
+                    $l = $source_x/$source_y;
+                    
+                    if($b > $l)
+                    {
+						$dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+					}
+                    else
+                    {
+						$dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+					}
+                }
+                elseif(isset($offset[2]) && $offset[2] == 4)
+                {
+                    //按照一定比例
+                    if($offset[0] == 0 && $offset[1] > 0)
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($offset[1] > 0 && $source_x > $source_y && $source_y >= $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y > $source_x && $source_x >= $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($source_y == $source_x && $offset[0] < $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y == $source_x && $offset[0] > $offset[1])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    elseif($source_y == $source_x && $offset[0] == $offset[1])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_x > $source_y && $source_y < $offset[1])
+                    {
+                        $dest_x = $offset[1]*$source_w;
+                        $dest_y = $offset[1];
+                    }
+                    elseif($source_y > $source_x && $source_x < $offset[0])
+                    {
+                        $dest_x = $offset[0];
+                        $dest_y = $offset[0]*$source_h;
+                    }
+                    else
+                    {
+                        $dest_x = $source_x;
+                        $dest_y = $source_y;
+                    }
+                }
+                else
+                {
+                    //直接放大和缩小
+                    $dest_x = $offset[0];
+                    $dest_y = $offset[1];
+                }
+				//echo $dest_y;die;
+				$this->_image = new Imagick($this->_source);  
+				$this->_image->thumbnailImage($dest_x, $dest_y);
+                
+                if(isset($offset[2]) && $offset[2] == 3)
+                {
+					/* 按照缩略图大小创建一个有颜色的图片 */  
+					$canvas = new Imagick();  
+					$color = new ImagickPixel("white");
+					$canvas->newImage($offset[0], $offset[1], $color, 'png');
+					//$canvas->paintfloodfillimage('transparent',2000,NULL,0,0);
+					/* 计算高度 */  
+					$x = ($offset[0] - $dest_x)/2;  
+					$y = ($offset[1] - $dest_y)/2;  
+					/* 合并图片  */  
+					$canvas->compositeImage($this->_image, imagick::COMPOSITE_OVER, $x, $y);
+					
+					$canvas->setCompression(Imagick::COMPRESSION_JPEG); 
+					$canvas->setCompressionQuality(100);
+
+					$canvas->writeImage($this->_dest['thumb'][$k]);
+
+					
+					if(isset($offset[3]) && $offset[3] && $this->_dest['thumb'][$k])
+					{
+						$offset[3] = $offset[3] * 1024;
+						$size = abs(filesize($this->_dest['thumb'][$k]));
+						if($size > $offset[3])
+						{
+							$this->_compress($canvas, $offset[3], 80, $this->_dest['thumb'][$k]);
+						}
+					}
+					
+					$canvas = false;
+				}
+				else
+				{
+					//$this->_image->setCompression(Imagick::COMPRESSION_JPEG); 
+					$this->_image->setCompressionQuality(90);
+					if($this->_imageType == 'gif')
+					{
+						$this->_image->writeImages($this->_dest['thumb'][$k], true);
+					}
+					else
+					{
+						$this->_image->writeImage($this->_dest['thumb'][$k]);
+					}
+				}
+            }
+        }
+        
+        $this->_name = false;
+
+        //$this->_image = false;
+    }
+    /**
+     * @desc 建立原图压缩图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _im_create_compress()
+    {
+		$this->_check('source');
+		$this->_check('quality');
+		$this->_dest['compress'] = $this->getName('_compress.jpg');
+		
+
+		if(strstr($this->_dest['compress'], '.png'))
+        {
+            $this->_image->stripImage();
+            $this->_image->setImageType(Imagick::IMGTYPE_PALETTE);
+            $this->_image->writeImage($this->_dest['compress']);      
+        }
+        else
+        {
+            $this->_image->setCompression(Imagick::COMPRESSION_JPEG); 
+    		$this->_image->setImageCompressionQuality($this->_quality);
+    		$this->_image->writeImage($this->_dest['compress']);
+        }
+
+        $this->_image = false;
+	}
+    
+    /**
+     * @desc 对图片进行压缩
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _compress($canvas, $max, $num, $file)
+    {
+		$num = $num - 10;
+		$temp = $file . '_temp_'.$num.'.jpg';
+		$canvas->setCompressionQuality($num);
+		$canvas->stripImage();
+		
+		$canvas->writeImage($temp);
+			
+		$size = abs(filesize($temp));
+		if($size > $max && $num > 0)
+		{
+			unlink($temp);
+			return $this->_compress($canvas, $max, $num, $file);
+		}
+		else
+		{
+			$canvas->destroy();
+			copy($temp, $file);
+			unlink($temp);
+		}
+	}
+
+    /**
+     * @desc 建立裁切图
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _im_create_crop()
+    {
+        $this->_check('source');
+        $this->_check('image');
+        $this->_check('crop');
+        
+        if(!is_array($this->_crop))
+        {
+			$array = explode(',',$this->_crop);
+		}
+		else
+		{
+			$array = $this->_crop;
+		}
+        foreach($array as $k => $v)
+        {
+			if($this->_name)
+			{
+				$this->_dest['crop'][$k] = $this->getName('_' . $v . '_crop.jpg', $k);
+			}
+			else
+			{
+				$this->_dest['crop'][$k] = (isset($this->_dest['thumb'][$k]) && $this->_dest['thumb'][$k]) ? $this->_dest['thumb'][$k] : $this->getName('_' . $v . '_crop.jpg', $k);
+			}
+            
+            if($this->_dropSize)
+			{
+				$this->_image = new Imagick($this->_dest['crop'][$k]);
+				$source_x   = $this->_image->getImageWidth();
+				$source_y   = $this->_image->getImageHeight();
+			}
+			else
+			{
+				$imageInfo = getimagesize($this->_source);
+				$source_x   = $imageInfo[0];
+				$source_y   = $imageInfo[1];
+			}
+			
+            if($this->_setup == true || !file_exists($this->_dest['crop'][$k]))
+            {
+				$offset = explode('_',$v);
+				if(isset($this->_dropSize[$k]) && $this->_dropSize[$k])
+				{
+					$offset[0] += $this->_dropSize[$k];
+					$offset[1] += $this->_dropSize[$k];
+				}
+				
+                if($this->_position)
+                {
+					# 加入根据百分比计算裁图
+					if($this->_position[0] <= 0)
+					{
+						$this->_position[0] = $source_x/2 - $offset[0]/2;
+					}
+					elseif(strstr($this->_position[0], '%'))
+                    {
+						$this->_position[0] = $source_x * intval(str_replace('%', '', $this->_position[0]))/100;
+					}
+					if($this->_position[1] <= 0)
+					{
+						$this->_position[1] = $source_y/2 - $offset[1]/2;
+					}
+					elseif(strstr($this->_position[1], '%'))
+                    {
+						$this->_position[1] = $source_y * intval(str_replace('%', '', $this->_position[1]))/100;
+					}
+					$x = $this->_position[0];
+					$y = $this->_position[1];
+                }
+                else
+                {
+					$x = $source_x/2 - $offset[0]/2;
+					$y = $source_y/2 - $offset[1]/2;
+				}
+				if($x < 0)
+				{
+					$x = 0;
+				}
+				if($y < 0)
+				{
+					$y = 0;
+				}
+
+                if($this->_imageType == 'gif')
+                {
+                    $this->_im_gif($offset[0], $offset[1], $x, $y);
+                }
+                else
+                {  
+                    $this->_image->cropImage($offset[0], $offset[1], $x, $y);
+                }
+                
+                if(isset($offset[2]) && $offset[2] == 3 && isset($offset[3]) && $offset[3] > 0)
+                {
+					$this->_image->writeImage($this->_dest['crop'][$k]);
+					$offset[3] = $offset[3] * 1024;
+					$size = abs(filesize($this->_dest['crop'][$k]));
+					if($size > $offset[3])
+					{
+						$this->_compress($this->_image, $offset[3], 80, $this->_dest['crop'][$k]);
+					}
+				}
+				else
+				{
+					//$this->_image->setCompression(Imagick::COMPRESSION_JPEG); 
+					$this->_image->setCompressionQuality(90);
+					if($this->_imageType == 'gif')
+					{
+						$this->_image->writeImages($this->_dest['crop'][$k], true);
+					}
+					else
+					{
+						$this->_image->writeImage($this->_dest['crop'][$k]);
+					}
+				}
+            }
+        }
+
+        $this->_image = false;
+    }
+
+    private function _im_gif($w, $h, $x, $y, $d = false, $num = false)
+    {
+		$canvas = new Imagick();
+
+		$canvas->setFormat("gif");
+
+        $this->_image->coalesceImages();
+        
+        $num = $num ? $num : $this->_image->getNumberImages();
+
+        for($i = 0; $i < $num; $i++)
+        {
+			$this->_image->setImageIndex($i);
+					
+			$img = new Imagick();
+			$img->readImageBlob($this->_image);
+			
+			if($d != false)
+			{
+				$img->drawImage($d);
+			}
+			else
+			{
+				$img->cropImage($w, $h, $x, $y);
+			}
+
+			$canvas->addImage($img);
+			$canvas->setImageDelay($img->getImageDelay());
+			if($d == false) $canvas->setImagePage($w, $h, 0, 0);
+			
+			$img->destroy();
+			
+			unset($img);
+        }
+        
+        $this->_image->destroy();
+        $this->_image = $canvas;
+    }
+
+    /**
+     * @desc 建立水印
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _im_create_mark()
+    {
+        $this->_check('source');
+        $this->_check('image');
+        $this->_check('mark', 'water');
+        $this->_check('mark', 'position');
+
+        $this->_dest['mark'] = $this->getName('_mark.jpg');
+
+        if($this->_setup == true || !file_exists($this->_dest['mark']))
+        {
+            $water = new Imagick($this->_mark['water']);
+            $draw = new ImagickDraw();
+
+            $source_x   = $this->_image->getImageWidth();
+            $source_y   = $this->_image->getImageHeight();
+            $water_x    = $water->getImageWidth();
+            $water_y    = $water->getImageHeight();
+            $xy         = $this->_get_mark($source_x, $source_y, $water_x, $water_y);
+
+
+            $draw->composite($water->getImageCompose(), $xy[0], $xy[1], $water_x, $water_y, $water);
+      
+            if($this->_imageType == 'gif')
+            {
+                $this->_im_gif(0, 0, 0, 0, $draw);
+            }
+            else
+            {
+                $this->_image->drawImage($draw);
+            }
+	
+            $this->_image->writeImage($this->_dest['mark']);
+        }
+
+        $this->_image = false;
+    }
+
+    /**
+     * @desc 建立文字
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _im_create_txt()
+    {
+        $this->_check('source');
+        $this->_check('image');
+        //$this->_check('txt','file');
+        $this->_check('txt','color');
+        $this->_check('txt','size');
+        $this->_check('txt','angle');
+        $this->_check('txt','name');
+        //$this->_check('txt','left');
+        //$this->_check('txt','top');
+        //$this->_check('txt','bgcolor');
+        //$this->_check('txt','font');
+
+        $this->_dest['txt'] = isset($this->_txt['file']) ? $this->_txt['file'] : $this->getName('_txt.jpg');
+
+        if($this->_setup == true || !file_exists($this->_dest['txt']))
+        {
+
+            $draw = new ImagickDraw();
+            if(isset($this->_txt['font']))          $draw->setFont($this->_txt['font']);
+            if(isset($this->_txt['size']))          $draw->setFontSize($this->_txt['size']);
+            if(isset($this->_txt['color']))         $draw->setFillColor($this->_txt['color']);
+            if(isset($this->_txt['bgcolor']))       $draw->setTextUnderColor($this->_txt['bgcolor']);
+              
+            if($this->_imageType == 'gif')
+            {  
+                foreach($this->_image as $frame)
+                {
+                    $frame->annotateImage($draw, 0, 0, $this->_txt['angle'], $this->_txt['name']);
+                }
+            }
+            else
+            {
+                $this->_image->annotateImage($draw, 0, 0, $this->_txt['angle'], $this->_txt['name']);
+            }
+
+            $this->_image->writeImage($this->_dest['txt']);
+        }
+
+        $this->_image = false;
+    }
+
+    private function _get_mark($source_x, $source_y, $water_x, $water_y)
+    {
+        $this->_check('mark', 'position');
+        $l = 0;
+        $t = 0;
+        $state = true;
+        if($this->_mark['position'])
+        {
+            switch($this->_mark['position'])
+            {
+                case 1:
+                    //左上
+                    break;
+                case 2:
+                    //左下
+                    $t = $source_y - $water_y;
+                    break;
+                case 3:
+                    //右上
+                    $l = $source_x - $water_x;
+                    break;
+                case 4:
+                    //右下
+                    $l = $source_x - $water_x;
+                    $t = $source_y - $water_y;
+                    break;
+                case 5:
+                    //中间
+                    $l = $source_x/2 - $water_x/2;
+                    $t = $source_y/2 - $water_y/2;
+                    break;
+                default :
+                    $state = false;
+                    break;
+            }
+        }
+        return array($l, $t, $state);
+    }
+    
+    /**
+     * @desc 判断是否网络文件,如果是,则生成一个本地路径
+     * @param $file 网络文件地址
+     * @param $path 生成的路径,默认为项目根目录下的'data/upload'
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function _setFileName($file, $path = '/data/upload/')
+    {
+		if(strstr($file, 'http://'))
+		{
+			$array = explode('/', $file);
+			$filename = $array[count($array)-1];
+			$file = siscon::path(siscon::path(siscon::path(siscon::path(PROJECT_ROOT_PATH . $path) . date("Y") . '/') . date("m") . '/') . date("d") . '/') . $filename;
+		}
+		return $file;
+	}
+	
+	/**
+     * @desc 对网络文件进行拷贝复制到本地
+     * @param $file 网络文件地址
+     * @param $path 生成的路径,默认为项目根目录下的'data/upload'
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    public function copyFile($file, $path = '/data/upload/')
+    {
+		if(strstr($file, 'http://'))
+		{
+			$new = $this->_setFileName($file);
+			if(!is_file($new))
+			{
+				$content = file_get_contents($file);
+				file_put_contents($new, $content);
+			}
+			$file = $new;
+		}
+		return $file;
+	}
+}

+ 657 - 0
vendor/dever-main/framework/src/Dever/Page/Main.php

@@ -0,0 +1,657 @@
+<?php namespace Dever\Page;
+
+use Dever\Http\Input;
+use Dever\Config\Load as Config;
+use Dever\Routing\Uri;
+use Dever\Http\Url;
+
+class Main
+{
+    /**
+     * PAGE
+     *
+     * @var string
+     */
+    const PAGE = 'page/';
+    
+    /**
+     * total
+     *
+     * @var int
+     */
+    public $total;
+
+    /**
+     * num
+     *
+     * @var int
+     */
+    public $num;
+
+    /**
+     * maxpage
+     *
+     * @var int
+     */
+    public $maxpage;
+
+    /**
+     * page
+     *
+     * @var int
+     */
+    public $page;
+
+    /**
+     * prev
+     *
+     * @var int
+     */
+    public $prev;
+
+    /**
+     * next
+     *
+     * @var int
+     */
+    public $next;
+
+    /**
+     * current
+     *
+     * @var int
+     */
+    public $current;
+
+    /**
+     * template
+     *
+     * @var string
+     */
+    public $template;
+
+    /**
+     * html
+     *
+     * @var string
+     */
+    public $html;
+    
+    /**
+     * link
+     *
+     * @var string
+     */
+    public $link;
+    
+    /**
+     * ext
+     *
+     * @var string
+     */
+    public $ext = '';
+
+    /**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * getInstance
+     * 
+     * @return Dever\Plad\Page;
+     */
+    static public function getInstance($key)
+    {
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self();
+        }
+
+        return self::$instance[$key];
+    }
+
+    /**
+     * getPage
+     * 
+     * @return Dever\Plad\Page;
+     */
+    static public function getPage($key, $total = false, $template = '')
+    {
+        if(is_numeric($total) && $total > 0)
+        {
+            self::getInstance($key)->total($total);
+            self::getInstance($key)->offset(1);
+            self::getInstance($key)->template($key);
+            self::getInstance($key)->link();
+        }
+
+        $result = self::getInstance($key)->handle($template);
+
+        if($total == 'NEXT')
+        {
+            if(self::getInstance($key)->next)
+            {
+                $result = self::getInstance($key)->href(self::getInstance($key)->next);
+            }
+            else
+            {
+                $result = '';
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * getTotal
+     * 
+     * @return Dever\Plad\Page;
+     */
+    static public function getTotal($key)
+    {
+        return self::getInstance($key)->total();
+    }
+
+    /**
+     * getHtml
+     * 
+     * @return Dever\Plad\Page;
+     */
+    static public function getHtml($key, $template = '')
+    {
+        return self::getPage($key, false, $template);
+    }
+
+    /**
+     * __construct
+     *
+     * @return mixd
+     */
+    private function __construct()
+    {
+        $this->maxpage = 10;
+    }
+
+    /**
+     * getCurrent
+     *
+     * @return int
+     */
+    public function current($name = 'pg')
+    {
+        $this->current = Input::get($name, 1);
+
+        return $this->current;
+    }
+    
+    /**
+     * getPage
+     *
+     * @return int
+     */
+    public function getAllPage()
+    {
+        if(!$this->total)
+        {
+            return 0;
+        }
+        $this->page = ceil($this->total / $this->num);
+
+        return $this->page;
+    }
+
+    /**
+     * offset
+     *
+     * @return int
+     */
+    public function offset($num)
+    {
+        $this->num = $num;
+
+        $offset = $this->num * ($this->current()-1);
+        
+        return $offset;
+    }
+
+    /**
+     * total
+     *
+     * @return mixd
+     */
+    public function total($total = false)
+    {
+        if(!$total)
+        {
+            return $this->total ? $this->total : 0;
+        }
+        
+        $this->total = $total;
+    }
+
+    /**
+     * maxpage
+     *
+     * @return mixd
+     */
+    public function maxpage($maxpage)
+    {
+        $this->maxpage = $maxpage;
+    }
+
+    /**
+     * link
+     *
+     * @return mixd
+     */
+    public function link($link = '')
+    {
+        if(!$link) $link = Uri::$url;
+
+        if(strpos($link, 'pg=') !== false)
+        {
+            $link = preg_replace('/[?|&]pg=(\d+)/i', '', $link);
+        }
+
+        if(strpos($link, 'pt=') !== false)
+        {
+            $link = preg_replace('/[?|&]pt=(\d+)/i', '', $link);
+        }
+
+        # search
+        if(strpos($link, 'search_') === false)
+        {
+            $search = Input::prefix('search_');
+
+            if($search)
+            {
+                $link .= '&' . http_build_query($search);
+            }
+        }
+        
+        $this->link = $link;
+        
+        return $this->link;
+    }
+
+    /**
+     * template
+     *
+     * @return mixd
+     */
+    public function template($template)
+    {
+        $this->template = $template;
+    }
+
+    /**
+     * data
+     *
+     * @return mixd
+     */
+    public function data($content, $total = 0)
+    {
+        $this->total = $total;
+        if($content)
+        {
+            if($this->total <= 0)
+            {
+                $this->total = count($content);
+            }
+
+            $this->current();
+
+            $data = isset($content[$this->current-1]) ? $content[$this->current-1] : array();
+            
+            return $data;
+        }
+        
+        return array();
+    }
+
+    /**
+     * count
+     *
+     * @return mixd
+     */
+    public function count($sql, $offset, $total = 0, $db)
+    {
+        $this->total = $total;
+        $data_sql = $sql . ' LIMIT ' . $offset . ', ' . $this->num;
+        $query = $db->query($data_sql);
+        if($query)
+        {
+            $data = $db->query($data_sql)->fetchAll();
+
+            if($this->total <= 0)
+            {
+                if(strstr($sql, 'from '))
+                {
+                    $temp = explode('from ', $sql);
+                }
+                if(strstr($sql, 'FROM '))
+                {
+                    $temp = explode('FROM ', $sql);
+                }
+
+                if(isset($temp[1]))
+                {
+                    if(strstr($temp[1], ' order '))
+                    {
+                        $temp = explode(' order ', $temp[1]);
+                        $sql = $temp[0];
+                    }
+                    elseif(strstr($temp[1], ' ORDER '))
+                    {
+                        $temp = explode('ORDER', $temp[1]);
+                        $sql = $temp[0];
+                    }
+                    else
+                    {
+                        $sql = $temp[1];
+                    }
+                    
+                    $sql = 'SELECT count(1) as num FROM ' . $sql;
+                    $this->total = $db->query($sql)->fetchColumn();
+                }
+            }
+            
+            return $data;
+        }
+        
+        return array();
+    }
+
+    /**
+     * handle
+     *
+     * @return mixd
+     */
+    public function handle($template = '')
+    {
+        if($this->total < 1)
+        {
+            return '';
+        }
+
+        # total page
+        $this->getAllPage();
+        //$this->page = ceil($this->total / $this->num);
+
+        # current page
+        if($this->page < $this->current)
+        {
+            $this->current = $this->page;
+        }
+
+        if($this->page <= 1)
+        {
+            return '';
+        }
+
+        if($this->total > $this->num)
+        {
+            if($this->current > 1)
+            {
+                $this->prev = $this->current-1;
+            }
+
+            if($this->current < $this->page)
+            {
+                $this->next = $this->current+1;
+            }
+            
+
+            if($this->page <= $this->maxpage)
+            {
+                $this->start = 1;
+                $this->end   = $this->page;
+            }
+            else
+            {
+                $page = intval($this->maxpage/2);
+                if($this->current < $page)
+                {
+                    $this->start = 1;
+                }
+                elseif($this->current <= ($this->page - $this->maxpage))
+                {
+                    $this->start = $this->current - $page;
+                }
+                elseif($this->current > $this->page - $this->maxpage && $this->current <= $this->page - $page)
+                {
+                    $this->start = $this->current - $page;
+                }
+                elseif($this->current > $this->page - $page)
+                {
+                    $this->start = $this->page - $this->maxpage + 1;
+                }
+                $this->end = $this->start + $this->maxpage - 1;
+
+                if($this->start < 1)
+                {
+                    $this->end = $this->current + 1 - $this->start;
+                    $this->start = 1;
+                    if(($this->end - $this->start) < $this->maxpage)
+                    {
+                        $this->end = $this->maxpage;
+                    }
+                }
+                elseif($this->end > $this->page)
+                {
+                    $this->start = $this->page-$this->maxpage+1;
+                    $this->end      = $this->page;
+                }
+            }
+        }
+
+        return $this->getTemplate($template);
+    }
+
+    /**
+     * get
+     *
+     * @return string
+     */
+    public function getTemplate($template = '')
+    {
+        $template = $template ? $template : $this->template;
+        $file = DEVER_APP_PATH . self::PAGE . $template . '.php';
+        
+        if(is_file($file))
+        {
+            $page = $this;
+
+            include($file);
+
+            return $page->get();
+        }
+
+        return '';
+    }
+
+    /**
+     * get
+     *
+     * @return string
+     */
+    public function get()
+    {
+        return $this->html;
+    }
+
+    /**
+     * html
+     *
+     * @return string
+     */
+    public function html($parent, $child, $prev = array('prev', 'prev'), $next = array('next', 'next'), $current = array('page','current', '', false), $start = false, $end = false, $jump = false, $ext = '')
+    {
+        if($ext)
+        {
+            $this->ext = $ext;
+        }
+        
+        $html = '';
+
+        if(empty($current[2]))
+        {
+            $current[2] = '';
+        }
+
+        if($start && $this->current > 1)
+        {
+            $html .= $this->set($child, $start[1], 1, $start[0], $current[2]);
+        }
+
+        if($this->prev)
+        {
+            # prev
+            $html .= $this->set($child, $prev[1], $this->prev, $prev[0], $current[2]);
+        }
+        elseif(isset($prev[2]))
+        {
+            $html .= $this->set($child, $prev[1], $this->current, $prev[0], $current[2]);
+        }
+        
+
+        if($current[1])
+        {
+            $i = $this->start;
+
+            for($i; $i <= $this->end; $i++)
+            {
+                $class = $current[0];
+                if($i == $this->current)
+                {
+                    if(isset($current[3]) && $current[3] == true)
+                    {
+                        $class = $current[1];
+                    }
+                    else
+                    {
+                        if($class) $class .= ' ';
+                        $class .= $current[1];
+                    }
+                    
+                }
+
+                $html .= $this->set($child, $class, $i, $i, $current[2]);
+            }
+        }
+        
+
+        if($this->next)
+        {
+            # next
+            $html .= $this->set($child, $next[1], $this->next, $next[0], $current[2]);
+        }
+        elseif(isset($next[2]))
+        {
+            $html .= $this->set($child, $next[1], $this->end, $next[0], $current[2]);
+        }
+
+        if($end && $this->current < $this->page)
+        {
+            $html .= $this->set($child, $end[1], $this->page, $end[0], $current[2]);
+        }
+        
+        if($jump)
+        {
+            $click = 'onclick="var link=\''.$this->href('{1}').'\';location.href=link.replace(\'{1}\', document.getElementById(\'dever_page\').value)"';
+            $html .= str_replace('{click}', $click, $jump);
+        }
+
+        $this->html = $this->tag($parent, $html);
+    }
+
+    /**
+     * set
+     *
+     * @return string
+     */
+    public function set($child, $class, $num, $name, $type = '')
+    {
+        if($type == 'parent')
+        {
+            $child[1] = 'class="'.$class.'"';
+            $class = '';
+        }
+
+        if($child[0] == 'a')
+        {
+            $child[1] = $this->attr($class, $this->href($num));
+            $content = $name;
+        }
+        else
+        {
+            $content = $this->tag(array('a', $this->attr($class, $this->href($num))), $name);
+        }
+
+        return $this->tag($child, $content);
+    }
+
+    /**
+     * tag
+     *
+     * @return string
+     */
+    public function tag($tag, $content)
+    {
+        if(!$tag)
+        {
+            return $content;
+        }
+        $attr = '';
+        if(is_array($tag))
+        {
+            $temp = $tag;unset($tag);
+            $tag = $temp[0];
+            $attr = $temp[1];
+        }
+        return '<' . $tag . ' ' . $attr . '>' . $content . '</' . $tag . '>';
+    }
+
+    /**
+     * next
+     *
+     * @return string
+     */
+    public function next()
+    {
+        return $this->current < $this->page ? $this->current+1 : $this->page;
+    }
+
+    /**
+     * next
+     *
+     * @return string
+     */
+    public function prev()
+    {
+        return $this->current > 1 ? $this->current-1 : 1;
+    }
+
+    /**
+     * href
+     *
+     * @return string
+     */
+    public function href($page = false)
+    {
+        $page = $page ? $page : $this->current;
+        return Url::get($this->link . '&pg=' . $page . '&pt=' . $this->total) . $this->ext;
+    }
+
+    /**
+     * attr
+     *
+     * @return string
+     */
+    public function attr($class, $href)
+    {
+        return ' class="'.$class.'" href="'.$href.'" ';
+    }
+}

+ 806 - 0
vendor/dever-main/framework/src/Dever/Routing/Load.php

@@ -0,0 +1,806 @@
+<?php namespace Dever\Routing;
+
+use Dever;
+use Dever\Data\Model;
+use Dever\Http\Output;
+use Dever\Http\Input;
+use Dever\Config\Project;
+use Dever\Security\Api;
+use Dever\Config\Load as Config;
+use Dever\Debug\Process as Debug;
+use Dever\Routing\Step;
+use Dever\Routing\Uri;
+
+class Load
+{
+    /**
+     * database 定义database目录
+     *
+     * @var string
+     */
+    const DATABASE =  'database/';
+
+    /**
+     * library 定义library目录
+     *
+     * @var string
+     */
+    const LIBRARY =  'src/';
+
+    /**
+     * service 定义service目录
+     *
+     * @var string
+     */
+    const SERVICE =  'service/';
+
+    /**
+     * NAME 定义类库开发的命名空间
+     *
+     * @var string
+     */
+    const NAME =  'DeverApp\\';
+
+    /**
+     * SERVER_NAME 定义业务类的命名空间
+     *
+     * @var string
+     */
+    const SERVER_NAME =  'DeverService\\';
+
+    /**
+     * config
+     *
+     * @var array
+     */
+    protected $config;
+
+    /**
+     * setting
+     *
+     * @var array
+     */
+    protected $setting;
+
+    /**
+     * class
+     *
+     * @var array
+     */
+    protected $class;
+
+    /**
+     * data
+     *
+     * @var array
+     */
+    protected $data;
+
+    /**
+     * param
+     *
+     * @var array
+     */
+    protected $param;
+
+    /**
+     * path
+     *
+     * @var string
+     */
+    protected $path;
+
+    /**
+     * attr
+     *
+     * @var string
+     */
+    protected $attr;
+
+    /**
+     * load
+     *
+     * @var array
+     */
+    protected $load;
+
+    /**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * get
+     *
+     * @param  string  $method
+     * @param  array  $param
+     * @return \Dever\Routing\Loader
+     */
+    static public function get($method, $param = array())
+    {
+        if(empty(self::$instance))
+        {
+            self::$instance = new self();
+            spl_autoload_register(array(self::$instance, 'autoload'));
+        }
+
+        if(strpos($method, '?'))
+        {
+            $temp = explode('?', $method);
+            $method = $temp[0];
+            parse_str($temp[1], $param);
+        }
+
+        return self::$instance->load($method, $param);
+    }
+
+    /**
+     * load file
+     *
+     * @param  string  $method
+     * @param  array  $param
+     * @return \Dever\Routing\Loader
+     */
+    static public function object($method, $param = array())
+    {
+        return (object) self::get($method, $param);
+    }
+
+    /**
+     * autoload
+     *
+     * @return mixed
+     */
+    private function autoload($class)
+    {
+        $temp = explode('\\', $class);
+        if(strpos($class, self::NAME) !== false && isset($temp[1]))
+        {
+            $project = Project::load(strtolower($temp[1]));
+            if($project)
+            {
+                $file = $project['path'] . self::LIBRARY . str_replace($temp[0] . '/' . $temp[1] . '/', '', str_replace('\\', '/', $class)) . '.php';
+                if(is_file($file))
+                {
+                    $this->file($file);
+                }
+                else
+                {
+                    Output::abert('file_exists', $file);
+                }
+            }
+        }
+    }
+
+    /**
+     * setup 如果需要调取其他项目里的类,必须通过该方式
+     *
+     * @return mixed
+     */
+    private function load($key, $param = array())
+    {
+        //Config::$global['load'][$key] = true;
+        //$this->initParam($param);
+
+        $state = false;
+
+        $attr = '';
+        if(strpos($key, '#') !== false)
+        {
+            $temp = explode('#', $key);
+
+            $key = $temp[0];
+
+            $attr = $temp[1];
+        }
+
+        if(isset($param['cache']) && $param['cache'])
+        {
+            $state = true;
+        }
+        elseif(isset($this->param[$key]) && $this->param[$key] != $param)
+        {
+            $state = true;
+        }
+
+        $this->param[$key] = $param;
+        
+        unset($param);
+
+        # 增加缓存
+        $this->data[$key] = $this->cache($key);
+
+        if(!$this->data[$key])
+        {
+            if(empty($this->config[$key]))
+            {
+                $this->config($key, $state);
+            }
+
+            if($state == true || empty($this->data[$key]))
+            {
+                $this->import(array('model','library','service'), $key);
+                //$this->path = false;
+            }
+
+            $this->cache($key, $this->data[$key]);
+        }
+
+        if($attr)
+        {
+            if(isset($this->data[$key][$attr]))
+            {
+                return $this->data[$key][$attr];
+            }
+            return false;
+        }
+
+        return $this->data[$key];
+    }
+
+    /**
+     * cache
+     *
+     * @return mixed
+     */
+    private function cache($key, $data = false, $type = 'load')
+    {
+        if(isset($this->param[$key]) && $this->param[$key])
+        {
+            $key = $key . '_' . md5(serialize($this->param[$key]));
+        }
+        else
+        {
+            $param = Input::get();
+            $key = $key . '_' . md5(serialize($param));
+        }
+
+        return Dever::cache($key, $data, 0, $type);
+    }
+
+    /**
+     * config
+     *
+     * @return mixed
+     */
+    public function config($key, &$state)
+    {
+        if(strpos($key, 'http://') !== false)
+        {
+            $this->api($key, $key, '');
+            $state = false;
+            return;
+        }
+        $file = false;
+        $namespace = false;
+        if(strpos($key, '/') !== false)
+        {
+            $temp = explode('/', $key);
+
+            $method = $temp[1];
+
+            $file = $temp[0];
+            if($file && strpos($file, '.') !== false)
+            {
+				$temp = explode('.', $file);
+				$file = $temp[0];
+				$namespace = $temp[1];
+				
+				# 处理后台和公开的命名空间
+				if($namespace == 'manage')
+				{
+					//self::get('manage/auth.init');
+				}
+				elseif($namespace != 'public')
+				{
+					return;
+				}
+			}
+            elseif(!$file && strpos($key, '-') !== false && isset(Config::$global['manage']['project']) && Config::$global['manage']['project'])
+            {
+                $file = Config::$global['manage']['project'];
+                Config::$global['manage']['project'] = '';
+            }
+        }
+        else
+        {
+            $method = $key;
+        }
+
+        $file = $file ? $file : DEVER_APP_NAME;
+        $path = false;
+        //$api = DEVER_APP_NAME . '_api';
+        $api = 'api';
+
+        if(isset(Config::$global['host'][$api]) && isset(Config::$global['host'][$api][$file]) && strpos(Config::$global['host'][$api][$file], 'http://') === false)
+        {
+            if($state == true || empty($this->data[$key]))
+            {
+                $path = $this->api($method, $key, Config::$global['host'][$api][$file]);
+            }
+
+            if(!$path)
+            {
+                $state = false;
+
+                return;
+            }
+        }
+
+        $project = Project::load($file);
+        if($project)
+        {
+            $this->path = $path ? $path : $project['path'];
+            $file = isset($project['lib']) ? $project['lib'] : $project['name'];
+        }
+        elseif($path)
+        {
+            $this->path = $path;
+            $project['name'] = $file;
+            $project['lang'] = $file;
+        }
+        else
+        {
+            Output::abert('project_exists', $file);
+        }
+        
+        if(isset($this->param[$key]['CHECK']))
+        {
+			Api::check($method, $this->path);
+		}
+
+        $this->config[$key] = array
+        (
+            'method' => $method,
+            'file'   => $file,
+            'project' => $project['name'],
+            'project_name' => $project['lang'],
+            'path'   => $this->path,
+            'namespace' => $namespace
+        );
+    }
+
+    /**
+     * initApiParam
+     *
+     * @return mixed
+     */
+    private function initApiParam(&$param)
+    {
+        if($page = Input::get('pg'))
+        {
+            $param['pg'] = $page;
+        }
+        if($total = Input::get('pt'))
+        {
+            $param['pt'] = $total;
+        }
+        $param['json'] = 1;
+        $param['cache'] = 1;
+    }
+
+    /**
+     * api 载入接口操作
+     *
+     * @return mixed
+     */
+    public function api($method, $key, $api = '')
+    {
+        $this->data[$key] = $this->cache($key, false, 'api');
+
+        if($this->data[$key])
+        {
+            return false;
+        }
+
+        if($api && is_string($api) && strpos($api, 'http') === false)
+        {
+            return $api;
+        }
+        elseif($api && is_array($api) && isset($api[1]) && $api[1])
+        {
+            return $api[1];
+        }
+        else
+        {
+            if(is_array($api))
+            {
+                $api = $api[0];
+            }
+            $server = 'curl';
+            if(isset(Config::$global['host']['api_server']) && isset(Config::$global['host']['api_server']['type']))
+            {
+                $server = Config::$global['host']['api_server']['type'];
+            }
+
+            $this->initApiParam($this->param[$key]);
+
+            if($api && $server == 'tcp' && class_exists('\Swoole\Server'))
+            {
+                //$api .= 'swoole.server';
+
+                $config = parse_url($api);
+
+                $config['port'] = Config::$global['host']['api_server']['port'];
+
+                $config['host'] = isset(Config::$global['host']['api_server']['host']) ? Config::$global['host']['api_server']['host'] : $config['host'];
+
+                $class = \Dever\Server\Swoole::getInstance($config['port'], $config['host']);
+
+                $data = $class->api($key, $this->param[$key]);
+
+                if(!$data)
+                {
+                    $api .= $method;
+
+                    $data = Dever::curl($api, $this->param[$key]);
+                }
+                else
+                {
+                    $api = $config['host'] . ':' . $config['port'] . '--' . $method;
+                }
+            }
+            elseif($api && $server == 'rpc' && class_exists('\Yar_Server'))
+            {
+                $api .= 'rpc.server';
+
+                $data = \Dever\Server\Rpc::api($api, $method, $this->param[$key]);
+
+                $api .= '--' . $method;
+            }
+            else
+            {
+                $api .= $method;
+
+                $data = Dever::curl($api, $this->param[$key]);
+            }
+        }
+        
+
+        $this->log('api', $api, $this->param[$key], $data);
+
+        if(is_array($data))
+        {
+            $this->data[$key] = $data;
+        }
+        else
+        {
+            $data = json_decode($data, true);
+
+
+            if(isset($data['page']))
+            {
+                Config::$global['page'] = $data['page'];
+            }
+
+            if(isset($data['status']) && $data['status'] == 2)
+            {
+                throw new \Exception($data['msg']);
+                die;
+            }
+            elseif(isset($data['data']))
+            {
+                $this->data[$key] = $data['data'];
+            }
+            elseif(isset($data['code']) || (isset($data['status']) && $data['status'] == 2))
+            {
+                Dever::abert($data['msg']);
+            }
+            else
+            {
+                $this->data[$key] = $data;
+            }
+        }
+
+        $this->cache($key, $this->data[$key], 'api');
+
+        return false;
+    }
+
+    /**
+     * model 载入数据与类操作
+     *
+     * @return string
+     */
+    private function import($method, $key)
+    {
+        if(isset($this->param[$key]) && is_array($this->param[$key]) && $this->param[$key])
+        {
+            foreach($this->param[$key] as $k => $v)
+            {
+                Input::set($k, $v);
+            }
+        }
+        $this->data[$key] = false;
+
+        # 以后这里可以加入方法和类引用记录
+        foreach($method as $k => $v)
+        {
+            if(isset($this->config[$key]['method']))
+            {
+                $this->$v($key);
+
+                //$this->log($v, $key, (isset($this->param[$key]) ? $this->param[$key] : $this->param[$key]), $this->data[$key]);
+            }
+        }
+    }
+
+    /**
+     * model 载入数据库操作
+     *
+     * @return string
+     */
+    private function model($key)
+    {
+        if(strpos($this->config[$key]['method'], '-') !== false)
+        {
+            $method = explode('-', $this->config[$key]['method']);
+
+            $index = '';
+            //$class = $this->config[$key]['file']  . '-' . $method[0];
+            $class = $this->config[$key]['file']  . '-' . $this->config[$key]['method'];
+            if(isset($method[1]) && $method[1] && isset($method[2]) && $method[2])
+            {
+                $class .= '-' . $method[2];
+                $index = $method[2];
+            }
+
+            if(empty($this->class[$class]))
+            {
+                $this->setting[$class] = array();
+                
+                $this->setting[$class]['name'] = $method[0];
+
+                if(isset($this->config[$key]['base']) && isset($this->config[$key]['rel']))
+                {
+                    $path = DEVER_INCLUDE_PATH . $this->config[$key]['rel'];
+                }
+                else
+                {
+                    $path = $this->config[$key]['path'];
+                }
+
+                $file = $path . self::DATABASE . $method[0] . '.php';
+
+                if(is_file($file))
+                {
+                    //Output::abert('file_exists', $file);
+
+                    $this->setting[$class] = $this->file($file);
+                }
+
+                if(isset($this->setting[$class]['config']))
+                {
+                    Config::$global['model'][$method[0]] = $this->setting[$class]['config'];
+                }
+
+				if(isset($this->setting[$class]['top']))
+				{
+					if(is_string($this->setting[$class]['top']))
+					{
+                        if(strpos($this->setting[$class]['top'], '-') === false)
+                        {
+                            $this->setting[$class]['top_key'] = $this->setting[$class]['top'];
+
+                            $this->setting[$class]['top'] = $this->config[$key]['file'] . '-' . $this->setting[$class]['top'];
+                        }
+						else
+                        {
+                            $temp = explode('-', $this->setting[$class]['top']);
+                            
+                            $this->setting[$class]['top_key'] = $temp[1];
+                            $this->setting[$class]['top'] = $this->setting[$class]['top'];
+                        }
+					}
+					elseif(is_array($this->setting[$class]['top']))
+					{
+						$this->setting[$class]['top']['key'] = $this->config[$key]['file'] . '-' . $this->setting[$class]['top']['key'];
+					}
+				}
+
+                if(isset($this->setting[$class]['auth']) && is_array($this->setting[$class]['auth']))
+                {
+                    $this->setting[$class]['auth']['project'] = $this->config[$key]['project'];
+                    $this->setting[$class]['auth']['project_name'] = $this->config[$key]['project_name'];
+                }
+
+                $this->setting[$class]['project'] = $this->config[$key]['file'];
+
+                $this->class[$class] = new Model($this->setting[$class], $index);
+            }
+            
+            if(isset($method[1]) && $method[1])
+            {
+                if(isset(Config::$global['model'][$key]))
+                {
+                    if(isset($this->param[$key]))
+                    {
+                        $this->param[$key] += Config::$global['model'][$key];
+                    }
+                    else
+                    {
+                        $this->param[$key] = Config::$global['model'][$key];
+                    }
+                }
+
+                //$this->api($this->config[$key]['path'], $method[0] . '-' . $method[1]);
+				if($method[1] == 'createIndex')
+				{
+					$this->data[$key] = $this->class[$class]->index($this->param[$key]);
+				}
+                elseif(isset($this->param[$key]) && $this->param[$key])
+                {
+                    //$this->data[$key] = call_user_func_array(array($this->class[$class], 'method'), $this->param[$key]);
+                    $this->data[$key] = $this->class[$class]->method($method[1], $this->param[$key]);
+                }
+                else
+                {
+                    $this->data[$key] = $this->class[$class]->method($method[1]);
+                }
+            }
+            elseif(isset($method[2]) && $method[2])
+            {
+                $this->data[$key] = $this->setting[$class][$method[2]];
+            }
+            else
+            {
+				$this->data[$key] = $this->setting[$class];
+			}
+
+            //unset($this->config[$key]['method']);
+        }
+    }
+
+    /**
+     * library 载入基础类库
+     *
+     * @return string
+     */
+    private function library($key)
+    {
+        if(strpos($this->config[$key]['method'], '.') !== false)
+        {
+            $method = explode('.', $this->config[$key]['method']);
+
+            $class = ucfirst($this->config[$key]['namespace'] ? $this->config[$key]['namespace'] : $this->config[$key]['file']) . '\\' . ucfirst($method[0]);
+
+            if(empty($this->class[$class]))
+            {
+                if(isset($this->config[$key]['base']) && isset($this->config[$key]['rel']))
+                {
+                    $path = DEVER_INCLUDE_PATH . $this->config[$key]['rel'];
+                }
+                else
+                {
+                    $path = $this->config[$key]['path'];
+                }
+
+                $file = $path . self::LIBRARY . str_replace('\\', '/', $class) . '.php';
+
+                if(!is_file($file))
+                {
+                    Output::abert('file_exists', $file);
+                }
+                require $file;
+
+                $className = self::NAME . $class;
+
+                $this->data[$key] = $this->class[$class] = new $className();
+            }
+
+            if(isset($method[1]) && $method[1])
+            {
+                $this->call($method[1], $key, $class);
+            }
+            else
+            {
+                $this->data[$key] = $this->data[$key] ? $this->data[$key] : $this->class[$class];
+            }
+
+            //unset($this->config[$key]['method']);
+        }
+    }
+
+    /**
+     * service 载入业务类库
+     *
+     * @return string
+     */
+    private function service($key)
+    {
+        if(strpos($this->config[$key]['method'], '!') !== false)
+        {
+            $method = explode('!', $this->config[$key]['method']);
+
+            $class = ucfirst($method[0]);
+
+            # 暂时不缓存类
+            $class_test = 'temp';
+
+            if(empty($this->class[$class_test]))
+            {
+                if(isset($this->config[$key]['base']) && isset($this->config[$key]['rel']))
+                {
+                    $path = DEVER_INCLUDE_PATH . $this->config[$key]['rel'];
+                }
+                else
+                {
+                    $path = $this->config[$key]['path'];
+                }
+
+                $file = $path . self::SERVICE . $class . '.php';
+
+                if(!is_file($file))
+                {
+                    Output::abert('file_exists', $file);
+                }
+                require_once $file;
+
+                $className = self::SERVER_NAME . ucfirst($this->config[$key]['namespace'] ? $this->config[$key]['namespace'] : $this->config[$key]['file']) . '\\' .$class;
+
+                $this->class[$class] = new $className();
+            }
+
+            $method[1] = 'handle';
+            /*
+            if(!$method[1])
+            {
+                $method[1] = 'handle';
+            }
+            */
+            $this->call($method[1], $key, $class);
+
+            //unset($this->config[$key]['method']);
+        }
+    }
+
+    private function call($method, $key, $class)
+    {
+        $this->step($method, $class);
+
+        if($this->param && isset($this->param[$key]))
+        {
+            # 以后升级实现可以多个参数的吧
+            //$this->data[$key] = call_user_func_array(array($this->class[$class], $method), $this->param[$key]);
+            
+            $this->data[$key] = $this->class[$class]->{$method}($this->param[$key]);
+        }
+        else
+        {
+            $this->data[$key] = $this->class[$class]->{$method}();
+        }
+    }
+
+    private function step($method, $class)
+    {
+        $key = '_step_';
+        if(strpos($method, $key) != false)
+        {
+            $config = explode($key, $method);
+
+            Step::init($config[0], $config[1], $key, $class);
+        }
+    }
+    
+    /**
+     * 载入文件
+     *
+     * @return string
+     */
+    private function file($file)
+    {
+		return include($file);
+	}
+
+    /**
+     * log
+     *
+     * @return log
+     */
+    private function log($type, $method, $param, $data = array())
+    {
+        Debug::log(array('method' => $method, 'param' => $param, 'data' => $data), $type);
+    }
+}

+ 108 - 0
vendor/dever-main/framework/src/Dever/Routing/Route.php

@@ -0,0 +1,108 @@
+<?php namespace Dever\Routing;
+
+use Dever;
+use Dever\Template\View;
+use Dever\Http\Output;
+use Dever\Http\Input;
+use Dever\Security\Api;
+use Dever\Debug\Process as Debug;
+use Dever\Config\Load as Config;
+use Dever\Config\Project;
+use Dever\Data\Opt;
+
+class Route
+{
+	public function runing()
+	{
+		$uri = Uri::get();
+
+		$state = self::def($uri);
+
+		if(!$state && !self::api($uri))
+		{
+			//$key = Uri::url();
+
+			$this->content = View::getInstance(Uri::file())->runing();
+		}
+		
+		return $this;
+	}
+
+	private function def($uri)
+	{
+		if($uri == 'tcp.deamon')
+		{
+			\Dever\Server\Swoole::daemon();
+			return true;
+		}
+		elseif($uri == 'rpc.server')
+		{
+			\Dever\Server\Rpc::init();
+			return true;
+		}
+
+		return false;
+	}
+
+	public function api($uri)
+	{
+		if(strpos($uri, '.') !== false || strpos($uri, '-*') !== false || strpos($uri, '!') !== false)
+		{
+			# 不允许带有_的直接浏览器访问
+			if(!defined('DEVER_DB_API') && strpos($uri, '._') !== false)
+			{
+				Output::abert('error_page');
+			}
+
+			Api::check($uri);
+
+			$this->content = Load::get($uri, array());
+			
+			Api::out($this->content, true);
+			
+			return true;
+		}
+		
+		return false;
+	}
+
+	public function output()
+	{
+		if(!isset($this->content))
+		{
+			return;
+		}
+
+		if(!$this->content)
+		{
+			Output::abert('error_page');
+		}
+
+		if(Project::load('manage'))
+		{
+			if(isset(Config::$global['base']['cron']) && Config::$global['base']['cron'] && DEVER_TIME%2 == 0)
+			{
+				Dever::load('manage/project.cron');
+			}
+			
+			if(isset(Config::$global['base']['opt']))
+			{
+				Opt::record();
+			}
+		}
+		
+		echo Output::result($this->content, false, false);
+
+		$this->debug();
+
+		die;
+	}
+
+	private function debug()
+	{
+		if(Debug::init() && is_string($this->content))
+		{
+			Debug::out();
+		}
+	}
+}

+ 72 - 0
vendor/dever-main/framework/src/Dever/Routing/Step.php

@@ -0,0 +1,72 @@
+<?php namespace Dever\Routing;
+
+use Dever\Security\Api;
+use Dever\Config\Load as Config;
+use Dever\Session\Save;
+use Dever\Http\Output;
+use Dever\Http\Input;
+
+class Step
+{
+    static protected $step;
+    static protected $key;
+    static protected $method;
+    static protected $save;
+    static protected $check = 'step_signature';
+    static protected $time = 500;
+
+    static public function init($method, $step, $key, $class)
+    {
+    	self::$save = new Save();
+    	self::$step = $step;
+    	self::$key = $key;
+    	self::$method = $method . $key;
+        if(self::$step == 1)
+        {
+        	self::create();
+        }
+        else
+        {
+        	self::check();
+        	self::create();
+        }
+    }
+
+    static private function create()
+    {
+    	$input = Input::prefix('step_');
+    	$param = $input + array('method' => self::$method . (self::$step + 1));
+
+        Config::$global['step'][self::$step] = Api::get($param);
+		self::$save->add(self::$check, Config::$global['step'][self::$step]['signature'], self::$time);
+    }
+
+    static private function check()
+    {
+    	$input = Input::prefix('step_');
+    	$param = $input + array('method' => self::$method . self::$step);
+
+        $signature = Api::result($param);
+
+        $save = self::$save->get(self::$check);
+
+        if($signature != $save)
+        {
+        	Output::abert('api_signature_exists');die;
+        }
+        else
+        {
+        	self::$save->un(self::$check);
+        }
+    }
+
+    static public function set($value)
+    {
+    	self::$save->add('data_' . (self::$step+1), $value, self::$time);
+    }
+
+    static public function get()
+    {
+    	return self::$save->get('data_' . self::$step);
+    }
+}

+ 213 - 0
vendor/dever-main/framework/src/Dever/Routing/Uri.php

@@ -0,0 +1,213 @@
+<?php namespace Dever\Routing;
+
+use Dever\Config\Load as Config;
+use Dever\Http\Input;
+
+class Uri
+{
+	/**
+     * explode
+     *
+     * @var string
+     */
+    const explode =  '/';
+    
+	/**
+	 * uri value
+	 *
+	 * @var string
+	 */
+	static public $value;
+
+	/**
+	 * method
+	 *
+	 * @var string
+	 */
+	static public $method;
+	
+	/**
+	 * uri type
+	 *
+	 * @var string
+	 */
+	static public $type = '?';
+	
+	/**
+	 * url
+	 *
+	 * @var string
+	 */
+	static public $url;
+
+	static public function get()
+	{
+		if(self::$value) return self::$value;
+
+		self::info();
+		
+		self::request();
+
+		self::$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
+
+		if(!self::$url && Input::$term == true && Input::get('send'))
+		{
+			self::$url = self::$value = str_replace(array('__', '^'), array('?', '&'), Input::get('send'));
+		}
+
+		empty(self::$value) && self::$value = 'home';
+
+		self::match();
+		
+		return self::$value;
+	}
+
+	static private function info()
+	{
+		if(isset($_SERVER['PATH_INFO']))
+		{
+			self::$type = '';
+
+			self::$value = trim($_SERVER['PATH_INFO'], self::explode);
+
+			self::$url = preg_replace('/^\//i', '', $_SERVER['REQUEST_URI']);
+		}
+	}
+
+	static private function request()
+	{
+		if(!isset($_SERVER['PATH_INFO']) && isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] && $_SERVER['REQUEST_URI'] != '/')
+		{
+			self::$type = '?';
+			$script = substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], 'index.php'));
+
+			if(strpos($_SERVER['REQUEST_URI'], '/index.php') !== false)
+			{
+				self::$value = str_replace($_SERVER['SCRIPT_NAME'] . '?', '', $_SERVER['REQUEST_URI']);
+			}
+			elseif($script != $_SERVER['REQUEST_URI'])
+			{
+				self::$value = str_replace($script . '?', '', $_SERVER['REQUEST_URI']);
+			}
+			self::$url = self::$value;
+		}
+	}
+
+	static public function match()
+	{
+		Config::get('route');
+
+		self::input();
+		
+		if(Config::$global['route'] && self::$value)
+		{
+			if(isset(Config::$global['route'][self::$value]))
+			{
+				self::$value = Config::$global['route'][self::$value];
+			}
+			else
+			{
+				self::grep();
+			}
+		}
+	}
+
+	static private function grep()
+	{
+		foreach(Config::$global['route'] as $k => $v)
+		{
+			$k = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $k));
+
+            if(preg_match('#^'.$k.'$#', self::$value))
+            {
+                if(strpos($v, '$') !== false && strpos($k, '(') !== false)
+                {
+                	$v = preg_replace('#^'.$k.'$#', $v, self::$value);
+                }
+
+                self::$value = $v;
+
+                self::$url = self::$value;
+            }
+		}
+		self::input();
+	}
+
+	static private function input()
+	{
+		if(strpos(self::$value, '?') !== false)
+		{
+			$temp = explode('?', self::$value);
+			self::$value = $temp[0];
+			parse_str($temp[1], $input);
+			Input::set('all', $input);
+
+			if(Input::$term == true && isset($input['dever_server']))
+			{
+				$_SERVER['DEVER_SERVER'] = $input['dever_server'];
+			}
+		}
+	}
+
+	static public function file()
+	{
+		self::tain();
+
+		if(strpos(self::$value, self::explode) !== false)
+		{
+			$array = explode(self::explode, self::$value);
+			
+			$file = self::parse($array);
+			
+			//$param = array_values($array);
+		}
+		else
+		{
+			$file = self::$value;
+		}
+		
+		return $file;
+	}
+
+	static public function url()
+	{
+		return self::$url;
+	}
+
+	static private function tain()
+	{
+		if(self::$method == 'GET' && !empty($_SERVER['REQUEST_URI']))
+		{
+			$request_uri = strtoupper(urldecode($_SERVER['REQUEST_URI']));
+			if(strpos($request_uri, '<') !== false || strpos($request_uri, '"') !== false || strpos($request_uri, 'CONTENT-TRANSFER-ENCODING') !== false)
+			{
+				error(\Lang::get('request_tainting'));
+			}
+			unset($request_uri);
+		}
+	}
+
+	static private function parse(&$array)
+	{
+		if(isset($array[2]) && empty($array[3]))
+		{
+			$file = $array[0] . self::explode . $array[1] . self::explode . $array[2];
+			unset($array[0]);
+			unset($array[1]);
+			unset($array[2]);
+		}
+		elseif(isset($array[1]))
+		{
+			$file = $array[0] . self::explode . $array[1];
+			unset($array[0]);
+			unset($array[1]);
+		}
+		elseif(isset($array[0]))
+		{
+			$file = $array[0];
+			unset($array[0]);
+		}
+
+		return $file;
+	}
+}

+ 299 - 0
vendor/dever-main/framework/src/Dever/Security/Api.php

@@ -0,0 +1,299 @@
+<?php namespace Dever\Security;
+
+use Dever\Http\Input;
+use Dever\Http\Output;
+use Dever\Config\Load as Config;
+use Dever\Config\Project;
+use Dever\Routing\Load;
+use Dever\Debug\Process as Debug;
+use Dever\Security\Internal;
+
+class Api
+{
+	/**
+	 * prefix
+	 *
+	 * @var string
+	 */
+	const PREFIX = 'api_';
+	
+	/**
+	 * time
+	 *
+	 * @var int
+	 */
+	const TIME = 300;
+
+	/**
+     * path 定义api目录
+     *
+     * @var string
+     */
+    const PATH =  'api/';
+	
+	/**
+	 * default token
+	 *
+	 * @var string
+	 */
+	static private $token = 'dever_api';
+	
+	/**
+	 * log
+	 *
+	 * @var string
+	 */
+	static private $log;
+	
+	/**
+	 * state
+	 *
+	 * @var string
+	 */
+	static public $state = false;
+
+	/**
+     * init
+     * @param  string  $key
+     * @param  string  $path
+     * 
+     * @return string
+     */
+	static public function init($path = false)
+	{
+		if(!$path)
+		{
+			$path = DEVER_APP_PATH;
+		}
+		$file = $path . self::PATH . 'main.php';
+
+		if(is_file($file))
+		{
+			return include($file);
+		}
+
+		return array();
+	}
+
+    static public function login($uid)
+    {
+        $auth = '';
+        $data = array($uid, time());
+        if($data)
+        {
+            $auth = base64_encode(Internal::encode(implode("\t", $data), self::$token));
+        }
+
+        return $auth;
+    }
+	
+	/**
+     * check
+     * @param  string  $key
+     * 
+     * @return string
+     */
+	static public function check($key, $path = false)
+	{
+		$config = self::init($path);
+
+		if($config && isset($config[$key]))
+		{
+			self::$log = array();
+			self::$log['add_site'] = $key;
+			
+			self::$state = true;
+			# 验证当前api有效性
+			$request = Input::prefix(self::PREFIX);
+			
+			Config::$global['base']['api'] = true;
+
+			# 增加测试效果
+			/*
+			if(Input::get('dever_api_test') == 'test_yes')
+			{
+				print_r(self::get($request));die;
+			}
+			*/
+			
+			self::result($request);
+			
+			if($request)
+			{
+				foreach($request as $k => $v)
+				{
+					$k = str_replace(self::PREFIX, '', $k);
+					
+					if(!isset($config[$key]['request'][$k]))
+					{
+						Output::abert('api_param_exists', $k);
+					}
+					
+					Input::set($k, $v);
+					
+					self::$log['add_request'][0][$k] = $v;
+				}
+			}
+		}
+	}
+	
+	/**
+     * 得到数据结果
+     * 
+     * @return mixed
+     */
+	static public function out($data, $state = false)
+	{
+		if(self::$state == true || $state == true)
+		{
+			if(!$data)
+			{
+				return;
+				//Output::abert('api_param_exists', 'response');
+			}
+			
+			# 记录日志 暂时不做记录
+			if(Project::load('manage'))
+			{
+				self::$log['add_response'][0] = $data;
+				//Load::get('manage/api_log-insert', $param);
+			}
+			
+			$result['msg'] = 'success';
+			$result['status'] = 1;
+			$result['data'] = $data;
+			
+			if(Input::get('dever_api_data') == 'yes')
+			{
+				print_r($result);die;
+			}
+			Output::result($result);
+		}
+
+		Debug::out();
+	}
+	
+	/**
+     * 得到解密结果
+     * 
+     * @return mixed
+     */
+	static public function result($info)
+	{
+		$time 	= Input::get('time');
+		if(!$time)
+		{
+			return self::resultLogin();
+		}
+		# 验证时间是否超时,默认为5分钟
+		if(time() - $time > self::TIME)
+		{
+			Output::abert('api_signature_exists');
+		}
+		$nonce 	= Input::get('nonce');
+		$key 	= Input::get('signature');
+		$signature = self::signature($time, $nonce, $info);
+		
+		if(Input::get('signature') != $signature)
+		{
+			Output::abert('api_signature_exists');
+		}
+
+		return $signature;
+	}
+
+	/**
+     * 得到解密结果
+     * 
+     * @return mixed
+     */
+	static public function resultLogin()
+    {
+    	$signature 	= Input::get('signature');
+        $auth     	= array();
+        $user 		= array();
+        if($signature)
+        {
+            $auth = explode("\t", Internal::decode(base64_decode($signature), self::$token));
+        }
+
+        list($uid, $time) = (empty($auth) || count($auth) < 2) ? array(0, '') : $auth;
+
+        if(!empty($uid) && (time() - $time) < 2592000)
+        {
+            $user = array('uid' => $uid,'time'=>$time);
+            Input::set('uid', $uid);
+            return $user;
+        }
+        else
+        {
+            Output::abert('api_signature_exists');
+        }
+    }
+	
+	/**
+     * 得到签名及其数据
+     * 
+     * @return mixed
+     */
+	static public function get($info)
+	{
+		$time 	= time();
+		$nonce 	= self::nonce();
+		$signature = self::signature($time, $nonce, $info);
+		
+		$info += array
+		(
+			'time'	=> $time,
+			'nonce'	=> $nonce,
+			'signature'	=> $signature,
+			//'token' => self::token(),
+			//'status'	=> 1,
+			//'msg'		=> 'success',
+		);
+		
+		return $info;
+	}
+	
+	/**
+     * 获取signature
+     * 
+     * @return mixed
+     */
+    static public function signature($time, $nonce, $info = array())
+    {
+		$info['token'] = self::token();
+		$info['time'] = $time;
+		$info['nonce'] = $nonce;
+		ksort($info);
+
+		$signature_string = '';
+		foreach($info as $k => $v)
+		{
+			$signature_string .= $k . '=' . $v . '&';
+		}
+		$signature_string = substr($signature_string, 0, -1);
+		return sha1($signature_string);
+	}
+	
+	/**
+     * 获取token
+     * 
+     * @return mixed
+     */
+	static public function token()
+	{
+		self::$token = isset(Config::$global['base']['token']) ? Config::$global['base']['token'] : self::$token;
+		return md5(self::$token);
+	}
+	
+	/**
+     * 获取nonce
+     * 
+     * @return mixed
+     */
+	static public function nonce()
+	{
+		return substr(md5(microtime()), rand(10, 15));
+	}
+}

+ 164 - 0
vendor/dever-main/framework/src/Dever/Security/Internal.php

@@ -0,0 +1,164 @@
+<?php namespace Dever\Security;
+
+class Internal
+{
+	/**
+     * key
+     *
+     * @var string
+     */
+    static private $key = 'qwertyuiop12345asdfghjkl67890zxcvbnm';
+    
+	/**
+     * encode
+     * @param  string  $string
+     * @param  string  $key
+     * 
+     * @return string
+     */
+	static public function encode($string, $key="")
+	{
+		$ckey_length = 5;
+		
+		if(!$key) $key = md5(self::$key);
+		
+		$keya = md5(substr($key, 0, 16));
+		$keyb = md5(substr($key, 16, 16));
+		$keyc = $ckey_length ? substr(md5(microtime()), -$ckey_length) : '';//md5串后4位,每次不一样
+
+		$cryptkey = $keya.md5($keya.$keyc);//两个md5串
+		$key_length = strlen($cryptkey);//64
+
+		$string = sprintf('%010d', time()).substr(md5($string.$keyb), 0, 16).$string;
+		$string_length = strlen($string);
+
+		$result = '';
+		$box = range(0, 255);
+
+		$rndkey = array();
+		for($i = 0; $i <= 255; $i++) 
+		{
+			$rndkey[$i] = ord($cryptkey[$i % $key_length]);//生成一个255个元素的数组
+		}
+
+		for($j = $i = 0; $i < 256; $i++)
+		{
+			//将$box数组转换为无序并且个数不变的数据
+			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
+			$tmp = $box[$i];
+			$box[$i] = $box[$j];
+			$box[$j] = $tmp;
+		}
+
+		for($a = $j = $i = 0; $i < $string_length; $i++) 
+		{
+			$a = ($a + 1) % 256;
+			$j = ($j + $box[$a]) % 256;
+			$tmp = $box[$a];
+			$box[$a] = $box[$j];
+			$box[$j] = $tmp;
+			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
+		}
+		
+		return $keyc.str_replace('=', '', self::base64_encode($result));
+
+	}
+
+	/**
+     * decode
+     * @param  string  $string
+     * @param  string  $key
+     * 
+     * @return string
+     */
+	static public function decode($string, $key="")
+	{
+		$ckey_length = 5;
+		
+		if(!$key) $key = md5(self::$key);
+		
+		$keya = md5(substr($key, 0, 16));
+		$keyb = md5(substr($key, 16, 16));
+		$keyc = $ckey_length ? substr($string, 0, $ckey_length) : '';//和encrypt时的$keyc一样
+
+		$cryptkey = $keya.md5($keya.$keyc);
+		$key_length = strlen($cryptkey);
+
+		$string =  self::base64_decode(substr($string, $ckey_length)) ;
+		$string_length = strlen($string);
+
+		$result = '';
+		$box = range(0, 255);
+
+		$rndkey = array();
+		for($i = 0; $i <= 255; $i++) 
+		{
+			$rndkey[$i] = ord($cryptkey[$i % $key_length]);
+		}
+
+		for($j = $i = 0; $i < 256; $i++) 
+		{
+			//和encrypt时的$box一样
+			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
+			$tmp = $box[$i];
+			$box[$i] = $box[$j];
+			$box[$j] = $tmp;
+		}
+
+		for($a = $j = $i = 0; $i < $string_length; $i++)
+		{
+			//核心操作,解密
+			$a = ($a + 1) % 256;
+			$j = ($j + $box[$a]) % 256;
+			$tmp = $box[$a];
+			$box[$a] = $box[$j];
+			$box[$j] = $tmp;
+			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
+		}
+
+
+		if(substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) 
+		{
+			return substr($result, 26);
+		}
+		else 
+		{
+			return '';
+		}
+
+	}
+	
+	/**
+     * base64_encode
+     * @param  string  $string
+     * 
+     * @return string
+     */
+	static function base64_encode($string)
+	{
+		if(!$string)
+		{
+			return false;
+		}
+		$encodestr = base64_encode($string);
+		$encodestr = str_replace(array('+','/'),array('-','_'),$encodestr);
+		return $encodestr;
+	}
+	
+	/**
+     * base64_decode
+     * @param  string  $string
+     * 
+     * @return string
+     */
+	static function base64_decode($string)
+	{
+		if(!$string)
+		{
+			return false;
+		}
+		$string = str_replace(array('-','_'),array('+','/'),$string);
+		$decodestr = base64_decode($string);		
+		return $decodestr;
+	}
+}

+ 157 - 0
vendor/dever-main/framework/src/Dever/Security/String.php

@@ -0,0 +1,157 @@
+<?php namespace Dever\Security;
+
+class String
+{
+    static public function rule($method)
+	{
+		$method = 'rule_' . $method;
+		return self::$method();
+	}
+
+	static public function rule_mobile()
+	{
+		return '/^(1(([358][0-9])|(45)|(47)))\d{8}$/';
+	}
+
+	static public function rule_email()
+	{
+		return '/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/';
+	}
+
+	static public function rand($len, $type = 4)
+	{
+		$source = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
+
+		$config = array
+		(
+			0 => array("min" => 0,"max" => 9),	/// 全数字
+			1 => array("min" => 10,"max" => 35),	/// 全小写
+			2 => array("min" => 36,"max" => 61),	/// 全大写
+			3 => array("min" => 10,"max" => 61),	/// 大小写
+			4 => array("min" => 0,"max" => 61),	/// 数字+大小写
+		);
+		if(!isset($config[$type]))
+		{
+			$type = 4;
+		}
+
+		$rand = "";
+		for($i=0;$i<$len;$i++)
+		{
+			$rand .= $source[rand($config[$type]["min"], $config[$type]["max"])];
+		}
+
+		return $rand;
+	}
+
+	static public function xss($data)
+	{
+		if(!is_string($data))
+		{
+			return $data;
+		}
+		$data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
+		$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
+		$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
+		$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
+
+		// Remove any attribute starting with "on" or xmlns
+		$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
+
+		// Remove javascript: and vbscript: protocols
+		$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
+		$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
+		$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
+
+		// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
+		$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
+		$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
+		$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
+
+		// Remove namespaced elements (we do not need them)
+		$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
+
+		do {
+		// Remove really unwanted tags
+			$old_data = $data;
+			$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
+		}
+		while ($old_data !== $data);
+
+		// we are done...
+		return $data;
+	}
+
+	static public function idtostr($input)
+	{
+		if(!is_numeric($input) || $input < 0)
+		{
+			return false;
+		}
+
+		$input = substr("00000000".$input, -8);
+		$sandNum =  $input % 10;
+		srand($input);
+		$randstr = "".rand(1,9).common_RandStr(7,0);
+
+		$retstr1 = "";
+		$retstr2 = "";
+		for($i=0;$i<4;$i++)
+		{
+			$retstr1 .= $randstr[$i] . $input[$i];
+			$retstr2 .= $input[7-$i] . $randstr[7-$i];
+		}
+		$retstr1 = substr(common_RandStr(6)."g".dechex($retstr1),-7);
+		$retstr2 = substr(common_RandStr(6)."g".dechex($retstr2),-7);
+		srand(time()+$input);
+		$retstr = "1".$sandNum;
+		for ($i = 0; $i < 7; $i++)
+		{
+			$retstr .=$retstr1[$i].$retstr2[$i];
+		}
+		return $retstr;
+	}
+
+	static public function strtoid($str)
+	{
+		if(strlen($str) != 16)
+		{
+			return $str;
+		}
+		$type = $str1[0];
+
+		$sandNum = $str[1];
+
+		for ($i = 0; $i < 7; $i++)
+		{
+			if($str[2+$i*2] == 'g')
+			{
+				$retstr1 = "";
+			}
+			else
+			{
+				$retstr1 .= $str[2+$i*2];
+			}
+
+			if($str[3+$i*2] == 'g')
+			{
+				$retstr2 = "";
+			}
+			else
+			{
+				$retstr2 .= $str[3+$i*2];
+			}
+		}
+
+		$retstr1 = "g".substr("00000000".hexdec($retstr1),-8);
+		$retstr2 = "g".substr("00000000".hexdec($retstr2),-8);
+		$ret1 = $ret2 = "";
+		for ($i = 0; $i < 4; $i++)
+		{
+			$ret1 .= $retstr1[$i*2+2];
+			$ret2 .= $retstr2[7-$i*2];
+		}
+		$ret = $ret1 * 10000 + $ret2;
+		return $ret;
+	}
+}

+ 76 - 0
vendor/dever-main/framework/src/Dever/Server/Rpc.php

@@ -0,0 +1,76 @@
+<?php namespace Dever\Server;
+
+use Dever\Routing\Load;
+use Dever\Http\Output;
+
+class Rpc_Api
+{
+
+    public function api($method, $param = array())
+    {
+    	$data = Load::get($method, $param);
+    	$page = Output::page();
+    	if($page)
+    	{
+    		return array('data' => $data, 'page' => $page);
+    	}
+        return $data;
+    }
+
+    protected function client_can_not_see()
+    {
+
+    }
+}
+
+class Rpc
+{
+	static $client = array();
+	static public function init()
+	{
+		self::server();
+		die;
+	}
+
+	static public function server()
+	{
+		$service = new \Yar_Server(new Rpc_Api());
+		$service->handle();
+	}
+
+	static public function client($link)
+	{
+		if(empty(self::$client[$link]))
+		{
+			ini_set("yar.timeout",60000);
+			self::$client[$link] = new \Yar_Client($link);
+		}
+		
+		return self::$client[$link];
+	}
+
+	static public function api($link, $method, $param = array())
+	{
+		self::client($link);
+
+		$data = self::$client[$link]->api($method, $param);
+
+		if(isset($data['page']) && $data['page'])
+		{
+			Output::page('current', $data['page']);
+			return $data['data'];
+		}
+
+		return $data;
+	}
+
+	static public function loop($link, $method, $param = array())
+	{
+		Yar_Concurrent_Client::call($link, $method, $param, "callback");
+		Yar_Concurrent_Client::call($link, $method, $param, "callback");
+		Yar_Concurrent_Client::call($link, $method, $param, "callback");
+		Yar_Concurrent_Client::loop(); //send
+
+		return $data;
+	}
+}

+ 425 - 0
vendor/dever-main/framework/src/Dever/Server/Swoole.php

@@ -0,0 +1,425 @@
+<?php namespace Dever\Server;
+
+use Dever;
+use Dever\Routing\Load;
+use Dever\Http\Output;
+use Dever\Http\Input;
+use Dever\Config\Load as Config;
+use Dever\Debug\Process as Debug;
+//use Swoole\Server as Server;
+//use Swoole\Client as Client;
+use swoole_server as Server;
+use swoole_client as Client;
+
+class Swoole
+{
+    protected $log = '/var/log/dever/swoole_';
+    protected $client = array();
+    protected $callback;
+    protected $ip;
+    protected $port;
+    static protected $instance;
+
+    /**
+     * load file
+     * @param string $file
+     * @param string $path
+     * 
+     * @return \Dever\Template\View
+     */
+    static public function getInstance($port = 30000, $ip = '0.0.0.0')
+    {
+        $key = $ip . ':' . $port;
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self($port, $ip);
+        }
+
+        return self::$instance[$key];
+    }
+
+    /**
+     * __construct
+     * @param int $this->port
+     * @param string $this->ip
+     *
+     * @return mixed
+     */
+    public function __construct($port = 30000, $ip = '0.0.0.0')
+    {
+        $this->setPort($port);
+        $this->setIp($ip);
+    }
+
+    /**
+     * set ip
+     * @param string $this->ip
+     *
+     * @return mixed
+     */
+    private function setIp($ip)
+    {
+        $this->ip = $ip;
+    }
+
+    /**
+     * set port
+     * @param int $this->port
+     *
+     * @return mixed
+     */
+    private function setPort($port)
+    {
+        $this->port = $port;
+    }
+
+    /**
+     * create path
+     *
+     * @return mixed
+     */
+    private function path()
+    {
+        $path = DEVER_APP_PATH;
+
+        return Dever::path($path . 'process/');
+    }
+
+    /**
+     * reload server
+     * @param string $config
+     *
+     * @return mixed
+     */
+    public function reload($config = false, $callback = array())
+    {
+        $content_server = '';
+        if($config)
+        {
+            $_SERVER['DEVER_SERVER'] = $config;
+            $content_server = "\$_SERVER['DEVER_SERVER'] = '".$config."';";
+        }
+        if($this->ip && $this->port)
+        {
+            $server = $this->port;
+            $entry = defined('DEVER_ENTRY') ? DEVER_ENTRY : 'index.php';
+            $content = "<?php
+
+define('DEVER_DAEMON', true);".$content_server."
+
+include(dirname(__FILE__) . DIRECTORY_SEPARATOR . '../".$entry."');
+
+\$ip = '".$this->ip."';
+
+\$port = '".$this->port."';
+
+\$callback = ".var_export($callback, true).";
+
+Dever::tcp(\$port, \$ip)->server(\$callback);";
+                        
+            $file = $this->path() . $server . '.php';
+            
+            file_put_contents($file, $content);
+            
+            Dever::kill($file);
+                
+            return Dever::run('php ' . $file, '');
+        }
+
+        return false;
+    }
+
+    /**
+     * daemon
+     *
+     * @return mixed
+     */
+    public function daemon()
+    {
+        /*
+        $cron = 'count=`ps -fe |grep "tcp.start" | grep -v "grep" | grep "master" | wc -l`
+
+        echo $count
+        if [ $count -lt 1 ]; then
+        ps -eaf |grep "tcp.start" | grep -v "grep"| awk \'{print $2}\'|xargs kill -9
+        sleep 2
+        ulimit -c unlimited
+        php /data/webroot/server.php
+        echo "restart";
+        echo $(date +%Y-%m-%d_%H:%M:%S) >'.self::$log.'restart.log
+        fi';
+        */
+
+        $process = $this->path();
+        $path = scandir($process);
+        foreach($path as $k => $v)
+        {
+            if(strpos($v, '.php'))
+            {
+                $v = $process . $v;
+                $state = Dever::process($v);
+                if(!$state)
+                {
+                    # 需要启动
+                    Dever::run('php ' . $v);
+                }
+            }
+        }
+    }
+
+    /**
+     * start server
+     *
+     * @return mixed
+     */
+    public function server($callback = false)
+    {
+        $server = new Server($this->ip, $this->port);
+        $config = array
+        (
+            'worker_num' => 8,
+            'daemonize' => true,
+            'max_request' => 0,
+            'dispatch_mode' => 2,
+            'log_file' => $this->log . 'run.log',
+
+            # 启用task
+            //'task_worker_num' => 1,
+            //'task_max_request' => 0,
+
+            # 确定数据完整性
+            //'open_length_check' => true,
+            //'open_eof_check' => true,
+            //'open_eof_split' => true,
+            //'package_eof' => '"eof":1}',
+            
+            # 确定心跳,确定死链接 ,每30秒检测一次心跳,如果60秒内没有数据发送,则切断链接
+            //'open_tcp_keepalive' => true,
+            //'heartbeat_check_interval' => 30,
+            //'heartbeat_idle_time' => 60,
+
+            # debug开启
+            //'debug_mode'=> 1
+        );
+        if(isset(Config::$global['host']['api_server']))
+        {
+            $config = array_merge($config, Config::$global['host']['api_server']);
+        }
+
+        $this->callback = $callback;
+        if($this->callback)
+        {
+            $this->callback['ip'] = $this->ip;
+            $this->callback['port'] = $this->port;
+        }
+
+        $server->set($config);
+
+        $server->on('start', array($this, 'server_start'));
+        $server->on('connect', array($this, 'server_connect'));
+        $server->on('receive', array($this, 'server_receive'));
+        $server->on('close', array($this, 'server_close'));
+        //$server->on('task', array($this, 'server_task'));
+        //$server->on('finish', array($this, 'server_finish'));
+        $server->on('shutdown', array($this, 'server_shutdown'));
+
+        $server->start();
+    }
+
+    public function server_start($server)
+    {
+        //echo "Service:Start...";
+        if(isset($this->callback['start']))
+        {
+            Dever::load($this->callback['start'], array($server, $this->callback));
+        }
+    }
+
+    public function server_shutdown($server)
+    {
+        if(isset($this->callback['shutdown']))
+        {
+            Dever::load($this->callback['shutdown'], array($server, $this->callback));
+        }
+        //echo "Service:Shutdown...";
+    }
+
+    public function server_connect($server, $fd)
+    {
+        if(isset($this->callback['connect']))
+        {
+            Dever::load($this->callback['connect'], array($server, $fd, $this->callback));
+        }
+        //echo "Client:Connect.\n";
+    }
+
+    public function server_receive($server, $fd, $from_id, $data)
+    {
+        $data = json_decode($data, true);
+        # 直接转发给客户端
+        if($data['method'] == 'send' && isset($data['param']['tcp_id']) && isset($data['param']['send']))
+        {
+            if(is_array($data['param']['send']))
+            {
+                $data['param']['send']['tcp_id'] = $data['param']['tcp_id'];
+                $data['param']['send'] = json_encode($data['param']['send']);
+            }
+            $server->send($data['param']['tcp_id'], $data['param']['send']);
+            unset($data['param']['tcp_id']);
+        }
+        else
+        {
+            if(isset($this->callback['receive']))
+            {
+                $state = Dever::load($this->callback['receive'], array($server, $fd, $data, $this->callback));
+
+                if(!$state)
+                {
+                    $server->close($fd);
+                    return;
+                }
+            }
+            if(isset($data['param']['token']))
+            {
+                $data['param']['tcp_id'] = $fd;
+            }
+
+            if(isset(Config::$global['host']['api_server']['backend']))
+            {
+                list($project, $interface) = explode('/', $data['method']);
+                $send = Dever::daemon($interface . '?' . http_build_query($data['param']), $project, 'index.php');
+
+                $send = $send[0];
+            }
+            else
+            {
+                Input::set('pg', 0);
+                Input::set('pt', 0);
+            	$send = Load::get($data['method'], $data['param']);
+                if(is_array($send))
+                {
+                    $page = Output::page('current', false, false);
+                    if($page)
+                    {
+                        $send = array('data' => $send, 'page' => $page);
+                    }
+                    //$send['eof'] = 1;
+                    $send = json_encode($send);
+                }
+            }
+
+            $server->send($fd, $send);
+        }
+
+        if(isset(Config::$global['host']['api_server']['pconnect']))
+        {
+            $data['param']['tcp_id'] = 1;
+        }
+        
+        if(empty($data['param']['tcp_id']))
+        {
+            $server->close($fd);
+        }
+    }
+
+    public function server_close($server, $fd)
+    {
+        if(isset($this->callback['close']))
+        {
+            Dever::load($this->callback['close'], array($server, $fd, $this->callback));
+        }
+        //echo "Client: Close.\n";
+    }
+
+    private function client($time = 0, $callback = false)
+    {
+    	$time = $time > 0 ? $time : 500;
+        if(!$callback)
+        {
+            $client = new Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
+            $state = $client->connect($this->ip, $this->port, $time);
+            if(!$state)
+            {
+                return false;
+            }
+        }
+        else
+        {
+        	$this->callback = $callback;
+            if($this->callback)
+            {
+                $this->callback['ip'] = $this->ip;
+                $this->callback['port'] = $this->port;
+            }
+            $client = new Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
+            $client->on('connect', array($this, 'client_connect'));
+            $client->on('receive', array($this, 'client_receive'));
+            $client->on('error', array($this, 'client_error'));
+            $client->on('close', array($this, 'client_close'));
+            $client->connect($this->ip, $this->port, $time);
+        }
+
+        return $client;
+    }
+
+    public function client_connect($client)
+    {
+        if(isset($this->callback['connect']))
+        {
+            Dever::load($this->callback['connect'], array($client, $this->callback));
+        }
+    }
+
+    public function client_receive($client, $data)
+    {
+        if(isset($this->callback['receive']))
+        {
+            return Dever::load($this->callback['receive'], array($client, $data, $this->callback));
+        }
+        return false;
+    }
+
+    public function client_error($client)
+    {
+        if(isset($this->callback['error']))
+        {
+            Dever::load($this->callback['error'], array($client, $this->callback));
+        }
+    }
+
+    public function client_close($client)
+    {
+        if(isset($this->callback['close']))
+        {
+            Dever::load($this->callback['close'], array($client, $this->callback));
+        }
+    }
+
+    public function api($method, $param = array(), $time = 0, $size = 65535, $flag = true)
+    {
+        $client = $this->client($time);
+
+        if(!$client)
+        {
+            return false;
+        }
+
+        $send = array('method' => $method, 'param' => $param);
+        $client->send(json_encode($send));
+        $data = $client->recv($size, $flag);
+        if($data && is_string($data) && strpos('{', $data) !== false)
+        {
+            $data = json_decode($data, true);
+        }
+        
+        $client->close();
+        
+        if(isset($data['page']) && $data['page'])
+        {
+            Output::page('current', $data['page']);
+            return $data['data'];
+        }
+
+        return $data;
+    }
+}

+ 207 - 0
vendor/dever-main/framework/src/Dever/Session/Save.php

@@ -0,0 +1,207 @@
+<?php namespace Dever\Session;
+
+use Dever\Security\Internal as Security;
+use Dever\Config\Load as Config;
+
+@header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
+@session_start();
+ini_set('session.cookie_domain', Config::$global['host']['cookie']);
+class Save
+{
+    /**
+     * key
+     *
+     * @var string
+     */
+    private $key = '';
+    
+    /**
+     * prefix
+     *
+     * @var string
+     */
+    private $prefix = 'dever_';
+    
+    /**
+     * project
+     *
+     * @var string
+     */
+    private $project = '';
+
+    /**
+     * method
+     *
+     * @var string
+     */
+    private $method = 'session';
+
+    /**
+     * __construct
+     * @param string $key
+     * @param string $method
+     * 
+     * @return mixed
+     */
+    public function __construct($key = false, $method = 'session')
+    {
+		$this->key 		= $key ? $key : $this->key;
+		
+		$this->method 	= $method ? $method : $this->method;
+		
+		$this->method 	= ucwords($this->method);
+		
+		$this->project 	= defined('DEVER_PROJECT') ? DEVER_PROJECT : 'default';
+		
+		$this->key($this->key);
+		
+		return $this;
+	}
+
+    /**
+     * add
+     * @param string $key
+     * @param mixed $value
+     * 
+     * @return mixed
+     */
+    public function add($key, $value, $time = 3600)
+    {
+        if(is_array($key))
+        {
+            $key = md5(serialize($key));
+        }
+        
+		$key = $this->project . '_' . $key;
+		
+        $value = Security::encode(base64_encode(serialize($value)), $this->key);
+        
+        $method = '_set' . $this->method;
+        
+        $this->$method($key, $value, $time);
+        
+        return $value;
+    }
+
+    /**
+     * get
+     * @param string $key
+     * @param mixed $type
+     * 
+     * @return mixed
+     */
+    public function get($key, $type = false)
+    {
+        if(is_array($key))
+        {
+            $key = md5(serialize($key));
+        }
+		$key = $this->project . '_' . $key;
+		
+        $method = '_get' . $this->method;
+        
+        $value = $this->$method($key);
+        
+        $type == false && $value = Security::decode($value, $this->key);
+        
+		$value = unserialize(base64_decode($value));
+		
+        return $value;
+    }
+
+    /**
+     * un
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    public function un($key)
+    {
+		$key = $this->project . '_' . $key;
+		
+        $method = '_unset' . $this->method;
+        
+        return $this->$method($key);
+    }
+
+    /**
+     * key
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    private function key($key)
+    {
+        $this->key = $this->prefix . '_' . $this->method . '_' . $key;
+    }
+
+    /**
+     * _setCookie
+     * @param string $key
+     * @param string $value
+     * 
+     * @return mixed
+     */
+    private function _setCookie($key, $value, $time = 3600)
+    {
+        return setCookie($this->prefix . $key, $value, time() + $time,  "/", Config::$global['host']['cookie']);
+    }
+
+    /**
+     * _getCookie
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    private function _getCookie($key)
+    {
+        return isset($_COOKIE[$this->prefix . $key]) ? $_COOKIE[$this->prefix . $key] : false;
+    }
+
+    /**
+     * _unsetCookie
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    private function _unsetCookie($key)
+    {
+        return setCookie($this->prefix . $key, false, time() - 3600,  "/", Config::$global['host']['cookie']);
+    }
+
+    /**
+     * _setSession
+     * @param string $key
+     * @param string $value
+     * 
+     * @return mixed
+     */
+    private function _setSession($key, $value, $time = 3600)
+    {
+        return $_SESSION[$this->prefix . $key] = $value;
+    }
+
+    /**
+     * _getSession
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    private function _getSession($key)
+    {
+        return (isset($_SESSION[$this->prefix . $key]) && $_SESSION[$this->prefix . $key]) ? $_SESSION[$this->prefix . $key] : false;
+    }
+
+    /**
+     * _unsetSession
+     * @param string $key
+     * 
+     * @return mixed
+     */
+    private function _unsetSession($key)
+    {
+        unset($_SESSION[$this->prefix . $key]);
+        
+        return true;
+    }
+}

+ 1222 - 0
vendor/dever-main/framework/src/Dever/Template/Compile.php

@@ -0,0 +1,1222 @@
+<?php namespace Dever\Template;
+
+use Dever\File\Path;
+use Dever\Debug\Process as Debug;
+use Dever\Config\Load as Config;
+use Dever\Http\Input;
+
+class Compile
+{
+    /**
+     * left
+     *
+     * @var const string
+     */
+    const LEFT = '<?php ';
+
+    /**
+     * right
+     *
+     * @var const string
+     */
+    const RIGHT = ' ?>';
+    
+    /**
+     * copyright
+     *
+     * @var const string
+     */
+    const COPYRIGHT = '<!--power by dever-->';
+
+    /**
+     * file
+     *
+     * @var string
+     */
+    protected $file;
+    
+    /**
+     * path
+     *
+     * @var string
+     */
+    protected $path;
+
+    /**
+     * template
+     *
+     * @var string
+     */
+    protected $template;
+
+    /**
+     * content
+     *
+     * @var array
+     */
+    protected $content;
+
+    /**
+     * update
+     *
+     * @var bull
+     */
+    protected $update = false;
+
+    /**
+     * data
+     *
+     * @var array
+     */
+    protected $data = NULL;
+
+    /**
+     * index
+     *
+     * @var int
+     */
+    protected $index = 0;
+
+    /**
+     * load file
+     * @param string $file
+     * @param string $path
+     * @param string $service
+     * @param string $project
+     *
+     * @return mixed
+     */
+    public function __construct($file, $template, $service, $project = false, $path = '', $data = array())
+    {
+        $this->index = 0;
+
+        $this->path = $path;
+
+        if($data) $this->data = $data;
+
+        $this->project($project);
+        
+        $this->file = $this->path($path . $file) . '.cmp.php';
+
+        if(isset(Config::$global['base']['publish']) && Config::$global['base']['publish'])
+        {
+            $this->update = false;
+        }
+        else
+        {
+            Debug::log($this->file, 'template');
+
+            $this->read($file, $template, $service);
+        }
+    }
+
+    /**
+     * read file
+     * @param string $file
+     * @param string $path
+     * @param string $service
+     * @param bool $local
+     *
+     * @return mixed
+     */
+    public function read($file, $path, $service, $local = false)
+    {
+        if(strpos($file, 'http://'))
+        {
+            $content = file_get_contents($file);
+
+            # 增加抓取功能 本地化
+            if($local == true)
+            {
+                $content = $this->local($content);
+            }
+
+            $this->template = $content;
+        }
+        else
+        {
+            $this->template = $path . $file . '.html';
+
+            if(is_file($this->template))
+            {
+                $is_service = is_file($service);
+
+                $time = is_file($this->file) ? filemtime($this->file) : 0;
+
+                $this->update = defined('DEVER_COMPILE');
+
+                if(filemtime($this->template) > $time || ($is_service && filemtime($service) > $time))
+                {
+                    # 可以更新
+                    $this->update = true;
+                }
+                
+                if(!$this->update && isset(Config::$global['base']['template-cache']) && Input::get(Config::$global['base']['template-cache']))
+                {
+                    $this->update = true;
+                }
+
+                if($time == 0 || $this->update == true)
+                {
+                    $content = $this->readContent($path);
+                }
+
+                if(!empty($content) && !$is_service)
+                {
+                    return $this->create($this->content($content));
+                }
+            }
+            else
+            {
+                # 当文件不存在时
+                $this->update = false;
+            }
+        }
+    }
+
+    /**
+     * readContent 获取当前模板的内容
+     *
+     * @return string
+     */
+    public function readContent($path)
+    {
+        # 这里直接用content传过去效率高
+        $content = file_get_contents($this->template);
+
+        if(strpos($content, '@include:') !== false)
+        {
+            $temp = explode('@include:', $content);
+            $file = end($temp);
+            $this->template = $path . $file . '.html';
+
+            $content = file_get_contents($this->template);
+        }
+        # 远程读取
+        elseif(strpos($content, '@url:') !== false)
+        {
+            //$config = $content;
+            $content = str_replace("\n", '', $content);
+            $temp = explode('@url:', $content);
+            $this->template = end($temp);
+            //$this->template = end(explode('@url:', $config));
+
+            $content = file_get_contents($this->template);
+            
+            # 增加资源处理功能 @res:replace 将资源中的路径替换为带有域名的路径 @res:local 本地化
+            if(strpos($temp[0], '@res:') !== false)
+            {
+                $temp = explode('@res:', $temp[0]);
+                $content = $this->res(end($temp), $content, $this->template, $path);
+            }
+        }
+
+        $this->template = $content;
+
+        return $content;
+    }
+
+    /**
+     * res 资源处理 此处待优化
+     *
+     * @return string
+     */
+    private function res($type, $content, $url, $path)
+    {
+        //return $content;
+        
+        $encode = mb_detect_encoding($content, array('GB2312','GBK','UTF-8'));
+        if($encode == 'GB2312' || $encode == 'GBK' || $encode == 'EUC-CN' || $encode == 'CP936')
+        {
+            $content = iconv('GBK', 'UTF-8', $content);
+        }
+
+        # 过滤换行
+        $content = str_replace(PHP_EOL, '', $content); 
+        
+        if($type == 'local')
+        {
+            # 规则
+            $rule = '<link(.*?)href="(.*?)"';
+
+            preg_match_all('/' . $rule . '/i', $content, $result);
+
+            $rule = '<script src="(.*?)"(.*?)<\/script>';
+
+            preg_match_all('/' . $rule . '/i', $content, $result);
+        }
+        elseif(strpos($type, 'include:') !== false)
+        {
+            $temp = explode('include:', $type);
+            $file = end($temp);
+
+            $include = str_replace("\n", '', file_get_contents($path . $file . '.html'));
+
+            parse_str($include, $param);
+            
+            foreach($param as $k => $v)
+            {
+                $content = $this->replace($k, $v, $content);
+            }
+        }
+        else
+        {
+            parse_str($type, $param);
+            
+            foreach($param as $k => $v)
+            {
+                $content = $this->replace($k, $v, $content);
+            }
+        }
+
+        return $content;
+    }
+
+    /**
+     * get file
+     *
+     * @return string
+     */
+    public function file()
+    {
+        return $this->file;
+    }
+
+    /**
+     * get template or content
+     *
+     * @return string
+     */
+    public function template()
+    {
+        return $this->template;
+    }
+
+    /**
+     * project
+     *
+     * @return string
+     */
+    public function project($project = false)
+    {
+        $this->project = $project ? $project : DEVER_APP_NAME;
+
+        return $this->project;
+    }
+
+    /**
+     * path create path
+     * @param string $file
+     * @param string $project
+     *
+     * @return string
+     */
+    public function path($file, $path = 'compile')
+    {
+        $path .= DIRECTORY_SEPARATOR . DEVER_PROJECT;
+
+        if(isset(Config::$global['base']['data']))
+        {
+            $data = Config::$global['base']['data'];
+        }
+        else
+        {
+            $data = DEVER_PATH . 'data' . DIRECTORY_SEPARATOR;
+        }
+        return Path::create($data . $path . DIRECTORY_SEPARATOR, $this->project . DIRECTORY_SEPARATOR . $file);
+    }
+
+    /**
+     * get
+     *
+     * @return mixed
+     */
+    public function get()
+    {
+        if($this->update == false && is_file($this->file))
+        {
+            ob_start();
+
+            if(isset($this->data) && $this->data && is_array($this->data))
+            {
+                parse_str(http_build_query($this->data));
+            }
+
+            require $this->file;
+
+            $content = ob_get_contents();
+
+            if(isset(Config::$global['host']['domain']))
+            {
+                $this->domain($content);
+            }
+
+            ob_end_clean();
+
+            return $content;
+        }
+        elseif($this->update == false)
+        {
+            return '';
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * replace domain
+     * @param  string $content
+     */
+    private function domain(&$content)
+    {
+        $rule = Config::$global['host']['domain']['rule'];
+        $replace = Config::$global['host']['domain']['replace'];
+        $rule = $rule();
+        if($rule[0] != $rule[1])
+        {
+            foreach($replace as $k => $v)
+            {
+                $source = $rule[0] . str_replace('*', '([a-zA-Z0-9_]+)', $v);
+                $desc = $rule[1] . str_replace('*', '$1', $v);
+                $source = str_replace('/', '\/', $source);
+                $content = preg_replace('/'.$source.'/i', $desc, $content);
+            }
+        }
+    }
+
+    /**
+     * load view
+     *
+     * @param  string $service
+     * @return \Dever\Template\View
+     */
+    public function load($file, $path = '')
+    {
+        $desc = '<!--{'.$path.'/'.$file.'}-->';
+
+        $view = View::getInstance($file);
+
+        if($path)
+        {
+            $view->path($path);
+        }
+        else
+        {
+            $view->path($this->path);
+        }
+
+        $view->runing();
+
+        $file = $view->file();
+
+        if($file)
+        {
+            if(strpos($file, '//') !== false)
+            {
+                $file = str_replace('//', '/', $file);
+            }
+            if(isset(Config::$global['base']['data']))
+            {
+                $require = 'Dever::$global["base"]["data"]';
+                $path = Config::$global['base']['data'];
+            }
+            else
+            {
+                $require = 'DEVER_PATH . "data" . DIRECTORY_SEPARATOR';
+                $path = DEVER_PATH . 'data' . DIRECTORY_SEPARATOR;
+            }
+            return $desc . $this->script('require '.$require.' . \'' . str_replace($path, '', $file) . '\'') . $desc;
+        }
+    }
+
+    /**
+     * create
+     * @param string $content
+     *
+     * @return string
+     */
+    public function create($content)
+    {
+        $this->update = false;
+
+        if($this->content)
+        {
+            $content = implode("\n", $this->content) . "\n" . $content;
+        }
+
+        $this->write($this->assets($content));
+
+        return $this->get();
+    }
+
+    /**
+     * write
+     *
+     * @return mixed
+     */
+    public function write($content)
+    {
+        $content = preg_replace('/<!--(.*?)-->/s', '', $content);
+
+        if(isset(Config::$global['host']['merge']) && Config::$global['host']['merge'] && strpos($content, Config::$global['host']['workspace']) !== false)
+        {
+            $this->merge
+            (
+                array('<link(.*?)href=[\'|"](.*?)[\'|"](.*?)>', '<script([a-zA-Z\/"\'=\\s]+)src=[\'|"](.*?)[\'|"](.*?)<\/script>'),
+                $content
+            );
+        }
+
+        //$this->file = str_replace('/', DIRECTORY_SEPARATOR, $this->file);
+        
+        if(strpos($content, self::COPYRIGHT) === false && strpos($content, '<html') !== false)
+        {
+            $content = str_replace('<html', self::COPYRIGHT . '<html', $content);
+        }
+        
+        file_put_contents($this->file, $content);
+
+        @chmod($this->file, 0755);
+
+        system('chmod -R ' . $this->file . ' 777');
+    }
+    
+    /**
+     * assets
+     * @param string $content
+     *
+     * @return string
+     */
+    public function assets($content)
+    {
+        if(isset(Config::$global['base']['replace']) && is_array(Config::$global['base']['replace']))
+        {
+            foreach(Config::$global['base']['replace'] as $k => $v)
+            {
+                if(isset(Config::$global['host'][$k]))
+                {
+                    if(empty(Config::$global['host']['merge']) && isset(Config::$global['base']['assets_domain']) && Config::$global['base']['assets_domain'])
+                    {
+                        $content = $this->replace($v, $this->script('echo Dever::$global["host"]["'.$k.'"]'), $content);
+                    }
+                    else
+                    {
+                        $content = $this->replace($v, Config::$global['host'][$k], $content);
+                    }
+                }
+            }
+        }
+
+        return $content;
+    }
+
+
+    /**
+     * merge
+     *
+     * @return string
+     */
+    private function merge($rule, &$content)
+    {
+        foreach($rule as $k => $v)
+        {
+            $v = '/' . $v . '/i';
+            preg_match_all($v, $content, $result);
+
+            //print_r($result);
+
+            if(isset($result[2]) && $result[2])
+            {
+                if($k == 1)
+                {
+                    $ext = 'js';
+                    $fext = "\r\n;";
+                }
+                else
+                {
+                    $ext = 'css';
+                    $fext = '';
+                }
+
+                $file = md5($this->file) . '.' . $ext;
+                
+                $host = Config::$global['host']['merge'] . $this->project . DIRECTORY_SEPARATOR . $file . '?v' . DEVER_TIME;
+
+                if(isset(Config::$global['base']['assets_domain']) && Config::$global['base']['assets_domain'])
+                {
+                    $host = $this->replace(Config::$global['host']['merge'], $this->script('echo Dever::$global["host"]["merge"]'), $host);
+                }
+                
+                
+                $file = $this->path($file, 'assets');
+                
+                $assets = '';
+                foreach($result[2] as $fk => $fv)
+                {
+                    if($fv)
+                    {
+                        //$fv = str_replace(Config::$global['host']['assets'], Config::$global['base']['assets'], $fv);
+
+                        //$fv = str_replace(Config::$global['host']['workspace'], DEVER_PATH, $fv);
+
+                        $fv = str_replace(Config::$global['host']['workspace'], Config::$global['base']['workspace'], $fv);
+                        
+                        $fv = str_replace('/', DIRECTORY_SEPARATOR, $fv);
+                        
+                        $assets .= $this->copy($fv, $file, $ext) . $fext;
+                        
+                        if(strpos($content, '{{file}}') === false)
+                        {
+                            $content = str_replace($result[0][$fk], '{{file}}', $content);
+                        }
+                        else
+                        {
+                            $content = str_replace($result[0][$fk], '', $content);
+                        }
+                    }
+                }
+                
+                if($assets)
+                {
+                    $method = 'zip_' . $ext;
+                    //$assets = $this->assets($assets);
+                    file_put_contents($file, $this->$method($assets));
+                }
+
+                $file = $k == 1 ? '<script type="text/javascript" src="'.$host.'"></script>' : '<link rel="stylesheet" type="text/css" href="'.$host.'" />';
+                
+                //$content = $this->zip_css($content);
+                
+                $content = str_replace('{{file}}', $file, $content);
+            }
+        }
+    }
+
+    private function copy($file, $copy, $type = 'css')
+    {
+        $content = file_get_contents($file);
+
+        if($type == 'css')
+        {
+            $rule = '/url\((.*?)\)/i';
+            preg_match_all($rule, $content, $result);
+
+            $path = array();
+            if(isset($result[1]))
+            {
+                foreach($result[1] as $k => $v)
+                {
+                    $temp = $this->getPathByFile($v);
+                    $path[$temp] = $temp;
+
+                    $content = str_replace('../', '', $content);
+                }
+            }
+
+            $boot = $this->getPathByFile($file);
+            $copy = $this->getPathByFile($copy);
+
+            if($path)
+            {
+                foreach($path as $k => $v)
+                {
+                    $this->copyDir($boot . $v, $copy, $v);
+                }
+            }
+        }
+
+        return $content;
+    }
+
+    private function copyDir($src, $dst, $path)
+    {
+        if(function_exists('system'))
+        {
+            system('cp -R ' . $src . ' ' . $dst);
+        }
+        else
+        {
+            $path = str_replace(array('/', '..'), '', $path);
+            $dst = $dst . $path;
+
+            if(!is_dir($dst))
+            {
+                mkdir($dst);
+            }
+
+            $dir = opendir($src);
+            
+            while(false !== ($file = readdir($dir)))
+            {
+                if(($file != '.') && ($file != '..'))
+                {
+                    if(is_dir($src . '/' . $file))
+                    {
+                        $this->copyDir($src . '/' . $file, $dst . '/' . $file);
+                    }
+                    else
+                    {
+                        copy($src . '/' . $file, $dst . '/' . $file);
+                    }
+                }
+            }
+            closedir($dir);
+        }
+    }
+
+    private function getPathByFile($file)
+    {
+        $temp = explode('/', $file);
+        $count = count($temp)-1;
+        $file = str_replace($temp[$count], '', $file);
+        return $file;
+    }
+    
+    /**
+     * zip_css
+     * @param string $string
+     *
+     * @return string
+     */
+    private function zip_css($string)
+    {
+        return str_replace(array("\t", "\r\n", "\r", "\n"), '', $string);
+    }
+    
+    /**
+     * zip_js
+     * @param string $string
+     *
+     * @return string
+     */
+    private function zip_js($string)
+    {
+        return $string;
+        $h1 = 'http://';
+        $s1 = '【:??】';
+        $h2 = 'https://';
+        $s2 = '【s:??】';
+        $string = preg_replace('#function include([^}]*)}#isU','',$string);//include函数体
+        $string = preg_replace('#\/\*.*\*\/#isU','',$string);//块注释
+        $string = str_replace($h1,$s1,$string);
+        $string = str_replace($h2,$s2,$string);
+        $string = preg_replace('#\/\/[^\n]*#','',$string);//行注释
+        $string = str_replace($s1,$h1,$string);
+        $string = str_replace($s2,$h2,$string);
+        $string = preg_replace('#\s?(=|>=|\?|:|==|\+|\|\||\+=|>|<|\/|\-|,|\()\s?#','$1',$string);//字符前后多余空格
+        $string = $this->zip_css($string);
+        $string = trim($string," ");
+        
+        return $string;
+    }
+
+    /**
+     * script
+     * @param string $string
+     *
+     * @return string
+     */
+    public function script($string)
+    {
+        return self::LEFT . $string . self::RIGHT;
+    }
+
+
+    /**
+     * equal
+     * @param string $variable
+     * @param string $value
+     * @param string $key
+     *
+     * @return string
+     */
+    public function equal($variable, $value, $key = '')
+    {
+        if(strpos($key, '$') !== false)
+        {
+            $variable .= '['.$key.']';
+        }
+        elseif(strpos($key, 'Dever') !== false)
+        {
+            $variable .= '[\''.$key.'\']';
+        }
+        elseif($key)
+        {
+            $variable .= '[\''.$key.'\']';
+        }
+
+        if(is_array($value))
+        {
+            $value = var_export($value, true);
+        }
+        elseif(is_string($value) && strpos($value, '"') !== false && strpos($value, 'Dever::') === false)
+        {
+            $value = '\'' . $value . '\'';
+        }
+        return $this->script('$' . $variable . '=' . $value);
+    }
+
+    /**
+     * data
+     * @param string $data
+     *
+     * @return mixed
+     */
+    public function data($data)
+    {
+        if(is_object($data))
+        {
+            return $data();
+            /*
+            $this->set('$test', $data);
+            return '<{$test}>';
+            */
+        }
+        
+        $type = $this->strip($data);
+
+        # include page
+        if(strpos($type, '@') !== false)
+        {
+            return explode('@', $type);
+        }
+        # include database|model
+        elseif(strpos($type, 'http://') === false && strpos($type, '/') !== false && (strpos($type, '.') !== false || strpos($type, '-') !== false || strpos($type, '!') !== false))
+        {
+            $key = $type;
+            if(strpos($type, '|') !== false)
+            {
+                if(strpos($type, '!') !== false)
+                {
+                    $type = str_replace('!', '$', $type . '');
+                }
+                $temp = explode('|', $type);
+                $type = $temp[0];
+                parse_str($temp[1], $param);
+               // print_r($param);die;
+            }
+
+            $callback = 'Dever\\Routing\\Load::get(\'' . $type . '\')';
+
+            if(isset($param))
+            {
+                $param = var_export($param, true);
+                $callback = str_replace(')', ', '.$param.')', $callback);
+                if(strpos($callback, '$') !== false)
+                {
+                    $callback = preg_replace('/\'\$(.*?)\'/', '\$$1', $callback);
+                }
+                if(strpos($callback, 'Dever::') !== false)
+                {
+                    $callback = preg_replace('/\'\Dever::(.*?)\'/', "Dever::$1", $callback);
+                }
+            }
+
+            $this->push($key, $this->equal('data', $callback, $key));
+
+            return true;
+        }
+
+        return $data;
+    }
+
+    /**
+     * out echo variable
+     * @param string $variable
+     *
+     * @return string
+     */
+    public function out($variable)
+    {
+        return $this->script('echo $' . $variable);
+    }
+
+    /**
+     * each
+     * @param string $replace
+     * @param string $data
+     * @param string $content
+     *
+     * @return string
+     */
+    public function each($replace, $data, $content)
+    {
+        if($replace)
+        {
+            $strip = $this->strip($replace);
+            if($strip && strpos($replace, $strip) !== false)
+            {
+                $replace = $strip;
+            }
+        }
+
+        # 增加数组和非数组的判断,如果这里效率不高,以后可以优化,去掉第一行和最后三行即可
+        return $this->script('if(is_array($data[\''.$data.'\'])):')
+        .$this->equal('t', 'count($data[\''.$data.'\'])-1')
+        .$this->equal('i', 0)
+        .$this->script('foreach($data[\''.$data.'\'] as $k => $v):')
+        //.$this->replace($replace, $this->out('v'), $content)
+        .$content
+        .$this->equal('i', '$i+1')
+        .$this->script('endforeach;')
+        .$this->script('else:')
+        .$this->replace($replace, $this->out('data[\''.$data.'\']'), $content)
+        .$this->script('endif;');
+    }
+
+    private function callback($matches)
+    {
+        //print_r($matches);die;
+        
+        $key = '';
+
+        if($this->count > 0)
+        {
+            $key = $this->count;
+        }
+
+        $result = 'if(isset('.$matches[1].') && is_array('.$matches[1].')): foreach('.$matches[1].' as $k'.$key.' => $v'.$key.'):';
+
+        $this->count++;
+
+        return $result;
+    }
+
+    /**
+     * content
+     * @param string $content
+     *
+     * @return string
+     */
+    public function content($content, $data = false)
+    {
+        $echo = ' echo ';
+
+        $content = $this->rule($content);
+
+        $this->count = 0;
+
+        //$content  = preg_replace('/<{\$(.*?)=(.*?)}>/i', self::LEFT.'\$$1=$2' . self::RIGHT, $content);
+        $content  = preg_replace('/<{\$([a-zA-Z0-9_\'\"\[\]\s]+)=([a-zA-Z0-9_\'\"\[\]\s]+)}>/i', self::LEFT.'\$$1=$2' . self::RIGHT, $content);
+
+        if(strpos($content, 'loop('))
+        {
+            $content  = preg_replace_callback('/loop\((.*?)\):/i', array($this, 'callback'), $content);
+            $content = $this->replace('endloop', 'endforeach;endif;', $content);
+        }
+
+        $content = $this->replace('<{', self::LEFT . $echo, $this->replace('}>', self::RIGHT, $content));
+
+        $array = array('function', 'foreach', 'endforeach', 'if', 'endif', 'else', 'for', 'endfor', 'highlight_string', 'echo', 'print_r', 'is_array');
+
+        foreach($array as $k => $v)
+        {
+            if(is_numeric($k))
+            {
+                $k = $v;
+            }
+            if(strpos($content, self::LEFT . $echo . $k) !== false)
+            {
+                $content = $this->replace(self::LEFT . $echo . $k, self::LEFT . $v, $content);
+            }
+        }
+
+        if(strpos($content, '{self}') !== false)
+        {
+            $content  = $this->replace('{self}', '$data[\'' . $data . '\']', $content);
+        }
+
+        return $content;
+    }
+
+    /**
+     * logic
+     * @param string $logic
+     * @param string $string
+     *
+     * @return string
+     */
+    public function logic($logic, $string, $index = 1)
+    {
+        $this->index = $index;
+        # 这里暂时这样判断,以后再处理多种逻辑情况的
+        if(strpos($logic, '|') !== false)
+        {
+            list($handle, $logic) = explode('|', $logic);
+
+            if($logic == 'foreach')
+            {
+                $string = '<{if(isset('.$handle.') && '.$handle.' && is_array('.$handle.')):foreach('.$handle.' as $k'.$this->index.' => $v'.$this->index.'):if($v'.$this->index.'):}>' . $string . '<{endif;endforeach;endif;}>';
+            }
+            elseif($logic == 'if')
+            {
+                $string = '<{if(isset('.$handle.') && '.$handle.'):}>' . $string . '<{endif;}>';
+            }
+            else
+            {
+                $string = '<{'.$handle.'}>' . $string . '<{'.$logic.'}>';
+            }
+        }
+        else
+        {
+            $string = '<{if(isset('.$logic.') && '.$logic.' && is_array('.$logic.')):foreach('.$logic.' as $k'.$this->index.' => $v'.$this->index.'):if($v'.$this->index.'):}>' . $string . '<{endif;endforeach;endif;}>';
+        }
+        
+        return $this->content($string);
+    }
+
+    /**
+     * replace
+     * @param string $replace
+     * @param string $value
+     * @param string $content
+     *
+     * @return string
+     */
+    public function replace($replace, $value, $content)
+    {
+        if(!$replace)
+        {
+            return $value;
+        }
+
+        if(is_string($replace) && strpos($content, $replace) !== false)
+        {
+            $content = str_replace($replace, $value, $content);
+        }
+
+        return $content;
+    }
+
+    /**
+     * push
+     * @param string $value
+     *
+     * @return string
+     */
+    public function push($key, $value)
+    {
+        $this->content[$key] = $value;
+    }
+
+
+    /**
+     * set
+     * @param string $value
+     *
+     * @return string
+     */
+    public function set($key, $value = false)
+    {
+        if(!$value)
+        {
+            return $this->push($key, $this->script($this->rule($key)));
+        }
+
+        if(is_string($value))
+        {
+            if(strpos($value, 'Dever') === false)
+            {
+                $value = var_export($value, true);
+            }
+
+            $value = $this->rule($value);
+        }
+        elseif(is_object($value))
+        {
+            $value = $value();
+        }
+        
+        $this->push($key, $this->script($this->rule($key) . '=' . $value . ''));
+    }
+
+    /**
+     * tag
+     * @param string $key
+     * @param string $data
+     *
+     * @return string
+     */
+    public function tag($key, $data = false)
+    {
+        if($data)
+        {
+            $result = $data[$key];
+        }
+        else
+        {
+            $result = $key;
+        }
+        return $result;
+    }
+
+    /**
+     * handle
+     * @param string $data
+     * @param string $content
+     * @param string $expression
+     *
+     * @return string
+     */
+    public function handle($data, $content, $expression = '')
+    {
+        $result = '';
+
+        if(is_array($data))
+        {
+            $tags = $this->strip($content);
+            foreach($data as $k => $v)
+            {
+                $result .= $this->replace($tags, $v, $content);
+            }
+        }
+        else
+        {
+            $index = false;
+
+            if(is_string($data) && strpos($data, '#') > 0 && strpos($data, '"') === false)
+            {
+                list($data, $index) = explode('#', $data);
+            }
+
+            $method = $this->data($data);
+
+            if($method === true)
+            {
+                $result = $this->complex($data, $content, $index, $expression);
+            }
+            elseif(is_array($method))
+            {
+                $result = $this->load($method[1], $method[0]);
+            }
+            elseif($method && (is_string($method) || is_numeric($method)))
+            {
+                $method = $this->content($method);
+
+                $result = $this->replace($content, $method, $content);
+
+                if($result == $content)
+                {
+                    //$result = $this->replace($this->strip($content), $method, $content);
+                }
+            }
+            elseif(!$result && (is_string($data) || is_numeric($data)))
+            {
+                $data = $this->content($data);
+
+                $result = $this->replace($this->strip($content), $data, $content);
+            }
+            else
+            {
+                $result = $content;
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * complex
+     * @param string $data
+     * @param string $content
+     * @param string $index
+     * @param string $expression
+     *
+     * @return string
+     */
+    public function complex($data, $content, $index = false, $expression = '')
+    {
+        if($index)
+        {
+            $strip = $this->strip($content);
+            $result = $this->out('data[\''.$data.'\'][\''.$index.'\']');
+            if($strip == $content)
+            {
+                $result = $this->replace($strip, $result, $content);
+            }
+        }
+        else
+        {
+            if($expression)
+            {
+                $content = $this->replace($expression, $this->out('v'), $content);
+            }
+            $result = $this->each($content, $data, $this->content($content));
+        }
+        
+
+        return $result;
+    }
+
+    /**
+     * rule
+     * @param string $content
+     *
+     * @return string
+     */
+    public function rule($content)
+    {
+        if(strpos($content, 'request.') !== false)
+        {
+            $content = preg_replace('/request\.([a-zA-Z0-9]+)/', 'Dever::input(\'$1\')', $content);
+        }
+
+        if(strpos($content, '$') !== false && strpos($content, '.') !== false)
+        {
+            $rule = '\$([a-zA-Z0-9]+)\.([a-zA-Z0-9._]+)';
+
+            $content = preg_replace_callback('/' . $rule . '/i', array($this, 'rule_val'), $content);
+        }
+
+        if(strpos($content, '"+') !== false)
+        {
+            $content = str_replace(array('"+','+"'), array('".', '."'), $content);
+        }
+
+        if(strpos($content, '++') !== false)
+        {
+            $content = str_replace('++', '.', $content);
+        }
+
+        if(strpos($content, '<{$') !== false)
+        {
+            //$content = str_replace('<{$', '<{echo $', $content);
+        }
+
+        return $content;
+    }
+
+    /**
+     * rule_val
+     * @param array $result
+     *
+     * @return string
+     */
+    public function rule_val($result)
+    {
+        if(isset($result[2]) && $result[2])
+        {
+            $result[2] = '$' . $result[1] . '' . preg_replace('/\.([a-zA-Z0-9_]+)/', '[\'$1\']', '.' . $result[2]);
+
+            return $result[2];
+        }
+        return $result[0];
+    }
+
+    /**
+     * strip
+     * @param string $content
+     *
+     * @return string
+     */
+    public function strip($content)
+    {
+        if(is_string($content))
+        {
+            return strip_tags($content);
+        }
+        return $content;
+    }
+}

+ 10 - 0
vendor/dever-main/framework/src/Dever/Template/Parse.php

@@ -0,0 +1,10 @@
+<?php namespace Dever\Template;
+
+interface Parse
+{
+	public function __construct(Compile $compile);
+
+	public function make($param);
+
+	public function get();
+}

+ 574 - 0
vendor/dever-main/framework/src/Dever/Template/Parse/Dom.php

@@ -0,0 +1,574 @@
+<?php namespace Dever\Template\Parse;
+
+use Dever\Template\Parse;
+use Dever\Template\Compile;
+use Dever\Http\Output;
+use Sunra\PhpSimple\HtmlDomParser;
+use Dever\Debug\Process as Debug;
+use Dever\Config\Lang;
+use Dever\Config\Load as Config;
+
+class Dom implements Parse
+{
+    /**
+     * current
+     *
+     * @var object
+     */
+    protected $current;
+
+    /**
+     * data
+     *
+     * @var string
+     */
+    protected $data;
+
+    /**
+     * expression
+     *
+     * @var string
+     */
+    protected $expression;
+
+    /**
+     * attr
+     *
+     * @var string
+     */
+    protected $attr = 'outertext';
+
+    /**
+     * compile
+     *
+     * @var \Dever\Template\Compile
+     */
+    protected $compile;
+
+    /**
+     * dom
+     *
+     * @var \Sunra\PhpSimple\HtmlDomParser
+     */
+    protected $dom;
+
+    /**
+     * temp dom
+     *
+     * @var \Sunra\PhpSimple\HtmlDomParser
+     */
+    protected $temp;
+
+    /**
+     * __construct
+     *
+     * @return mixed
+     */
+    public function __construct(Compile $compile)
+    {
+        $this->compile = $compile;
+        
+        $this->load($this->compile->template());
+    }
+
+    /**
+     * load file or string
+     * @param string $file
+     *
+     * @return mixed
+     */
+    public function load($value)
+    {
+        if(is_file($value))
+        {
+            $this->dom = HtmlDomParser::file_get_html($value);
+        }
+        else
+        {
+            $this->dom = HtmlDomParser::str_get_html($value);
+        }
+        
+
+        $this->filter();
+
+        //$this->layout();
+
+        $this->import();
+    }
+
+
+
+    /**
+     * make
+     * @param array $param
+     *
+     * @return mixed
+     */
+    public function make($param)
+    {
+        $this->current($param[0]);
+
+        $this->data = $param[1];
+
+        if($this->current) $this->expression = $this->current->innertext;
+
+        if(isset($param[2]) && is_array($param[2]))
+        {
+			$this->child($param[2]);
+		}
+		elseif(isset($param[2]) && $param[2] == 'none' && $this->current && is_string($this->data))
+		{
+			$value = $this->data;
+			if(strpos($this->data, 'Dever::') === false)
+			{
+				$value = '<{Dever::load("'.$this->data.'")}>';
+			}
+            $value = str_replace(array('<{', '}>'), array('<{if(!(', ')):}>'), $value);
+
+			$this->current->style = $this->compile->content($value . 'display:none;<{endif;}>');
+		}
+
+        elseif(isset($param[2]) && $param[2] == 'remove' && $this->current && is_string($this->data))
+        {
+            $value = $this->data;
+            if(strpos($this->data, 'Dever::') === false)
+            {
+                $value = '<{Dever::load("'.$this->data.'")}>';
+            }
+            $content = str_replace(array('<{', '}>'), array('<{if((', ')):}>'), $value);
+
+            $this->current->outertext = $this->compile->content($content . $value . '<{endif;}>');
+        }
+
+        $this->handle();
+    }
+
+    /**
+     * get
+     *
+     * @return string
+     */
+    public function get()
+    {
+        $this->layout();
+        return $this->dom->save();
+    }
+
+    /**
+     * child
+     * @param array $child
+     *
+     * @return array
+     */
+    public function child($child)
+    {
+		$this->attr = 'outertext';
+		
+        if($this->current && $child)
+        {
+            $this->expression = '';
+
+            foreach($child as $k => $v)
+            {
+                if($k == 'self')
+                {
+                    $this->attribute($v, $this->current);
+                }
+                elseif($k == 'parent')
+                {
+                    $parent = $this->current->parent();
+                    if(isset($v['number']) && $v['number'] >= 2)
+                    {
+                        for($i = 2; $i <= $v['number']; $i++)
+                        {
+                            $parent = $parent->parent();
+                        }
+                    }
+
+                    $this->attribute($v, $parent);
+                }
+                else
+                {
+                    if(strpos($k, '|') !== false)
+                    {
+                        $temp = explode('|', $k);
+                        list($k, $index) = $temp;
+                        if(!is_numeric($index))
+                        {
+                            $this->child_foreach($temp, $k, $v, $index, $this->current);
+
+                            continue;
+                        }
+                    }
+                    else
+                    {
+                        $index = 0;
+                        if(isset($v['key']))
+                        {
+                            $index = $v['key'];unset($v['key']);
+                        }
+                    }
+                    
+                    $this->attribute($v, $this->current->find($k, $index));
+                }
+            }
+
+            //echo $this->current->innertext;die;
+        }
+    }
+
+    private function child_foreach($temp, $k, $v, $index, $dom)
+    {
+        $temp[2] = isset($temp[2]) ? $temp[2] : 0;
+        $dom = $dom->find($k);
+
+        foreach($dom as $i => $j)
+        {
+            if($i == $temp[2])
+            {
+                $child = $j;
+            }
+            else
+            {
+                $j->outertext = '';
+            }
+        }
+
+        if(isset($child))
+        {
+            $this->attribute($v, $child);
+
+            $key = 1;
+            $temp = str_replace('$v', '', $index);
+            $temp = explode('.', $temp);
+            if($temp[0])
+            {
+                $key = $temp[0]+1;
+            }
+
+            $child->outertext = $this->compile->logic($index, $child->outertext, $key);
+        }
+    }
+
+    /**
+     * filter
+     *
+     * @return mixed
+     */
+    private function filter()
+    {
+        $dom = $this->dom->find('filter');
+
+        foreach($dom as $k => $v)
+        {
+            $dom[$k]->outertext = '';
+        }
+    }
+
+    /**
+     * layout
+     *
+     * @return mixed
+     */
+    private function layout()
+    {
+        if(isset(Config::$global['base']['layout']) && Config::$global['base']['layout'])
+        {
+            $dom = $this->dom->find(Config::$global['base']['layout']);
+            if(isset($dom[0]) && $dom[0]->outertext)
+            {
+                foreach($dom as $k => $v)
+                {
+                    $v->innertext = $this->compile->content('<{endif;}>' . $v->innertext . '<{if(isset($_SERVER["HTTP_X_PJAX"])):}><{else:}>');
+                }
+                
+
+                $html = $this->dom->find('html');
+                $html[0]->outertext = $this->compile->content('<{if(isset($_SERVER["HTTP_X_PJAX"])):}><{else:}>' . $html[0]->outertext . '<{endif;}>');
+            }
+
+            /*
+            $dom = $this->dom->find('.dever-layout');
+
+            if(isset($dom[0]) && $dom[0]->outertext)
+            {
+                foreach($dom as $k => $v)
+                {
+                    $v->innertext = $this->compile->content('<{endif;}>' . $v->innertext . '<{if(isset($_SERVER["HTTP_X_PJAX"])):}><{else:}>');
+                }
+            }
+            */
+        }
+    }
+
+    /**
+     * import
+     *
+     * @return mixed
+     */
+    private function import()
+    {
+        $dom = $this->dom->find('.include');
+
+        foreach($dom as $k => $v)
+        {
+            if(isset($v->path)) $v->file = $v->path . $v->file;
+            $v->outertext = $this->compile->load($v->file, $v->system);
+        }
+    }
+
+    /**
+     * attribute
+     * @param array|string $value
+     * @param object $dom
+     * @param array $data
+     *
+     * @return mixed
+     */
+    private function attribute($value, $dom, $data = false)
+    {
+        if(is_array($value))
+        {
+            foreach($value as $k => $v)
+            {
+                if($k == 'html')
+                {
+                    $data = $v;
+                }
+                else
+                {
+                    $index = 0;
+                    if(strpos($k, '|') !== false)
+                    {
+                        $temp = explode('|', $k);
+                        list($k, $index) = $temp;
+                        if(!is_numeric($index))
+                        {
+                            $this->child_foreach($temp, $k, $v, $index, $dom);
+
+                            continue;
+                        }
+                    }
+                    $this->plugin($dom, $k, $v, $index);
+                }
+            }
+
+            if($this->temp) $this->temp = null;
+        }
+        else
+        {
+            $data = $value;
+        }
+        
+        //if($data) $dom->outertext = $this->compile->handle($data, $dom->outertext);
+        if($data) $dom->innertext = $this->compile->content($data);
+    }
+
+    /**
+     * plugin
+     * @param object $dom
+     * @param string $attribute
+     * @param string $value
+     * @param int $index
+     *
+     * @return mixed
+     */
+    private function plugin($dom, $attribute, $value, $index = 0)
+    {
+        $key = '{data}';
+
+        if(is_array($value))
+        {
+            $child = $dom->find($attribute, $index);
+
+            if(!$child)
+            {
+                if(!$this->temp)
+                {
+                    # 这里因为dom类对append支持的不好,所以只能重新读取一次
+                    if($index > 0)
+                    {
+                        # 当有一个节点时,后续的所有节点均使用第一个节点为模板
+                        $this->temp = HtmlDomParser::str_get_html($dom->innertext);
+                    }
+                    else
+                    {
+                        # 清空原有父节点的全部内容
+                        $dom->innertext = '';
+                        # 当没有节点时,直接创建
+                        $this->temp = HtmlDomParser::str_get_html("<$attribute></$attribute>");
+                    }
+                }
+                
+                $child = $this->temp->find($attribute, 0);
+            }
+			/*
+            foreach($value as $k => $v)
+            {
+                if($k != $key)
+                {
+                    $this->plugin($child, $k, $v);
+                }
+            }
+            */
+
+			$this->attribute($value, $child);
+			
+            if(isset($value[$key]))
+            {
+                $dom->innertext = $this->compile->logic($value[$key], $child->outertext);
+            }
+
+            if($this->temp)
+            {
+                $dom->innertext .= $this->temp->innertext;
+            }
+            
+            return;
+        }
+
+        elseif($attribute == $key)
+        {
+            return;
+        }
+        if($attribute == 'html')
+        {
+            $attribute = 'innertext';
+        }
+        # modal
+        elseif($attribute == 'modal')
+        {
+            $dom->{'data-am-modal'} = '{target: \'#DEVER_modal\', closeViaDimmer: 0}';
+            $dom->{'href'} = '#DEVER_modal';
+            $dom->{'data-toggle'} = 'modal';
+
+            $attribute = 'onclick';
+
+            if(strpos($value, '|') !== false)
+            {
+                $temp = explode('|', $value);
+                $dom->{'data-modal-title'} = $temp[0];
+                $dom->{'data-modal-content'} = $temp[1];
+            }
+            else
+            {
+                $dom->{'data-modal-title'} = '提醒您';
+                $dom->{'data-modal-content'} = $value;
+            }
+            $value = '$(\'#DEVER_modal_title\').html($(this).attr(\'data-modal-title\'));$(\'#DEVER_modal_body\').html($(this).attr(\'data-modal-content\'))';
+        }
+        
+        $value = $this->compile->content($value, $this->data);
+
+        if(strpos($attribute, '++') !== false)
+        {
+            $attribute = str_replace('++', '', $attribute);
+
+            if(!strstr($dom->$attribute, $value))
+            {
+                $dom->$attribute = $dom->$attribute . $value;
+            }
+        }
+        elseif(strpos($attribute, '--') !== false)
+        {
+            $attribute = str_replace('--', '', $attribute);
+
+            if(strpos($dom->$attribute, $value) !== false)
+            {
+                $dom->$attribute = str_replace($value, '', $dom->$attribute);
+            }
+        }
+        else
+        {
+            $dom->$attribute = $value;
+        }
+    }
+
+    /**
+     * parse
+     * @param string $parse
+     *
+     * @return mixed
+     */
+    private function parse(& $parse)
+    {
+        if(strpos($parse, '@') !== false)
+        {
+            $temp = explode('@', $parse);
+            $parse = $temp[0];
+            $array = array
+            (
+                'html' => 'innertext',
+            );
+            $this->attr = isset($array[$temp[1]]) ? $array[$temp[1]] : $temp[1];
+        }
+    }
+
+    /**
+     * current
+     * @param array $parse
+     *
+     * @return mixed
+     */
+    private function current($parse)
+    {
+        //$this->attr = 'outertext';
+        
+        $this->attr = 'innertext';
+
+        if(is_array($parse))
+        {
+            $this->parse($parse[0]);
+
+            $this->current = $this->dom->find($parse[0], $parse[1]);
+        }
+        else
+        {
+            $this->parse($parse);
+
+            $dom = $this->dom->find($parse);
+
+            if($dom)
+            {
+                foreach($dom as $k => $v)
+                {
+                    if($k == 0)
+                    {
+                        $this->current = $v;
+                    }
+                    else
+                    {
+                        $dom[$k]->outertext = '';
+                    }
+                }
+            }
+            else
+            {
+                //Output::abert('dom_exists', $parse);
+                Debug::log(Lang::get('dom_exists', $parse));
+            }
+        }
+
+        if(!$this->current)
+        {
+            //Output::abert('dom_exists', $parse);
+            Debug::log(Lang::get('dom_exists', $parse));
+        }
+
+        return $this;
+    }
+
+    /**
+     * handle
+     *
+     * @return array
+     */
+    private function handle()
+    {
+		if($this->current)
+		{
+			//echo $this->current->outertext;die;
+			$this->current->{$this->attr} = $this->compile->handle($this->data, $this->current->{$this->attr}, $this->expression);
+		}
+    }
+}

+ 676 - 0
vendor/dever-main/framework/src/Dever/Template/View.php

@@ -0,0 +1,676 @@
+<?php namespace Dever\Template;
+
+use Dever;
+use Dever\Http\Input;
+use Dever\Http\Output;
+use Dever\Session\Save;
+use Dever\Config\Load as Config;
+use Dever\Config\Project;
+
+class View
+{
+	/**
+	 * templatePath
+	 *
+	 * @var string
+	 */
+	const TEMPLATE = 'html';
+
+	/**
+	 * servicePath
+	 *
+	 * @var string
+	 */
+	const SERVICE =  'template';
+	
+
+	/**
+	 * template
+	 *
+	 * @var string
+	 */
+	protected $template;
+
+	/**
+	 * template
+	 *
+	 * @var string
+	 */
+	protected $service;
+
+	/**
+	 * method
+	 *
+	 * @var string
+	 */
+	protected $method;
+
+	/**
+	 * content
+	 *
+	 * @var string
+	 */
+	protected $content;
+
+	/**
+	 * path
+	 *
+	 * @var string
+	 */
+	protected $path;
+
+	/**
+	 * parse (default value is dom)
+	 *
+	 * @var string
+	 */
+	protected $parse = 'Dom';
+
+	/**
+	 * file
+	 *
+	 * @var string
+	 */
+	protected $file;
+
+	/**
+	 * data
+	 *
+	 * @var array
+	 */
+	protected $data = NULL;
+
+	/**
+	 * pjax
+	 *
+	 * @var bool
+	 */
+	protected $pjax = NULL;
+
+	/**
+	 * project
+	 *
+	 * @var string
+	 */
+	protected $project;
+
+	/**
+	 * project
+	 *
+	 * @var string
+	 */
+	protected $porject_path;
+
+	/**
+	 * assets
+	 *
+	 * @var string
+	 */
+	protected $assets;
+
+	/**
+	 * compile
+	 *
+	 * @var \Dever\Template\Compile
+	 */
+	protected $compile;
+
+	/**
+     * instance
+     *
+     * @var string
+     */
+    static protected $instance;
+
+    /**
+     * load file
+     * @param string $file
+     * @param string $path
+     * 
+     * @return \Dever\Template\View
+     */
+    static public function getInstance($file, $path = '', $project = false)
+    {
+    	$key = $path . DIRECTORY_SEPARATOR . $file;
+        if(empty(self::$instance[$key]))
+        {
+            self::$instance[$key] = new self($file, $path);
+
+            self::$instance[$key]->project($project);
+        }
+
+        return self::$instance[$key];
+    }
+	
+	/**
+	 * __construct
+	 * @param string $file
+	 * @param string $path
+	 *
+	 * @return mixed
+	 */
+	public function __construct($file, $path = '')
+	{
+		$this->file = $file;
+
+		$this->path($path);
+
+		$this->content = '';
+	}
+
+	/**
+	 * project
+	 * @param string $project
+	 * @param array $data
+	 * 
+	 * @return mixed
+	 */
+	public function project($project, $data = array())
+	{
+		$this->assets = Config::$global['base']['assets'];
+		$this->service = DEVER_APP_PATH;
+		if($data) $this->data = $data;
+
+		$this->project = $project;
+
+		if($this->project)
+		{
+			$project = Project::load($this->project);
+			$this->assets = str_replace(DEVER_APP_PATH, $project['path'], $this->assets);
+			$this->service = $project['path'];
+		}
+
+		$this->service .=  self::SERVICE .  DIRECTORY_SEPARATOR;
+	}
+
+	/**
+	 * page
+	 * @param string $service
+	 * 
+	 * @return \Dever\Template\View
+	 */
+	public function page($file, $path = '')
+	{
+		echo $this->load($file, $path);
+	}
+
+	/**
+	 * load service
+	 * @param string $service
+	 * 
+	 * @return \Dever\Template\View
+	 */
+	public function load($file, $path = '', $project = false)
+	{
+		$view = View::getInstance($file, $path, $project);
+
+		return $view->runing();
+	}
+
+	/**
+	 * load service
+	 * @param string $service
+	 * 
+	 * @return \Dever\Template\View
+	 */
+	static public function get($file, $path = '', $project = false)
+	{
+		$class = new self($file, $path);
+
+        $class->project($project);
+
+        return $class->runing();
+
+        /*
+		$view = View::getInstance($file, $path, $project);
+
+		return $view->runing();
+		*/
+	}
+
+	/**
+	 * html 主流模板引擎的方式
+	 * @param $file 文件名
+	 * @param $data 数据
+	 *
+	 * @return mixed
+	 */
+	static public function html($file = false, $data = array(), $project = false)
+	{
+		$class = new self($file, '');
+
+		$class->parse = false;
+
+		$class->project($project, $data);
+
+        return $class->runing();
+	}
+
+	/**
+	 * path
+	 * @param string $path
+	 * 
+	 * @return \Dever\Template\View
+	 */
+	public function path($path = false)
+	{
+		if(isset(Config::$global['base']['template']))
+		{
+			$save = new Save();
+			$template = Input::get(Config::$global['base']['template']);
+			if($template)
+			{
+				if($template == 'none')
+				{
+					$save->un(Config::$global['base']['template']);
+				}
+				else
+				{
+					$save->add(Config::$global['base']['template'], $template);
+				}
+			}
+
+			$template = $save->get(Config::$global['base']['template']);
+		}
+		
+		if(isset($template) && $template)
+		{
+			$this->path = $template . DIRECTORY_SEPARATOR;
+		}
+		elseif($path)
+		{
+			if($path == 'manage')
+			{
+				Config::$global['base']['service'] = 'manage';
+			}
+			$this->path = $path . DIRECTORY_SEPARATOR;
+		}
+		elseif(isset(Config::$global['base']['template']))
+		{
+			if(is_array(Config::$global['base']['template']))
+			{
+				$this->path = Dever::mobile() ? Config::$global['base']['template'][1] : Config::$global['base']['template'][0];
+			}
+			else
+			{
+				$this->path = Config::$global['base']['template'];
+			}
+			$this->path .= DIRECTORY_SEPARATOR;
+		}
+		else
+		{
+			$temp = explode(DIRECTORY_SEPARATOR, DEVER_APP_PATH);
+			$this->path  = $temp[count($temp)-2] . DIRECTORY_SEPARATOR;
+		}
+
+		return $this;
+	}
+
+	/**
+	 * parse
+	 * @param string $parse
+	 * 
+	 * @return \Dever\Template\View
+	 */
+	public function parse($parse)
+	{
+		$parse = 'Dever\\Template\\Parse\\' . ucwords($parse);
+
+		if(class_exists($parse))
+		{
+			$this->parse = new $parse($this->compile);
+		}
+
+		return $this;
+	}
+
+	/**
+	 * runing
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function runing()
+	{
+		$key = \Dever\Routing\Uri::url();
+		$this->content = $this->cache($key);
+		if($this->content)
+		{
+			return $this->content;
+		}
+
+		$this->template()->compile();
+		$this->cache($key, $this->content);
+
+		return $this->content;
+	}
+
+	/**
+	 * file
+	 *
+	 * @return string
+	 */
+	public function file()
+	{
+		if(empty($this->compile))
+		{
+			return '';
+		}
+		return $this->compile->file();
+	}
+
+	/**
+	 * compile
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function compile()
+	{
+		$this->layout();
+
+		$this->compile = new Compile($this->file, $this->template, $this->service, $this->project, $this->path, $this->data);
+
+		$this->content = $this->compile->get();
+
+		if($this->content || $this->content !== false)
+		{
+			return $this->content;
+		}
+
+		if(!$this->parse)
+		{
+			return $this->display();
+		}
+
+		return $this->service();
+	}
+
+	/**
+	 * layout
+	 *
+	 * @return mixed
+	 */
+	public function layout()
+	{
+		if(isset(Config::$global['base']['layout']) && empty($this->pjax))
+		{
+			if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'])
+			{
+				$this->pjax = true;
+			}
+			else
+			{
+				$this->pjax = false;
+			}
+		}
+	}
+
+	/**
+	 * service
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function service()
+	{
+		if(!is_file($this->service))
+		{
+			return $this->display();
+		}
+		$view = $this;
+
+		require $this->service;
+
+		return $this->content;
+	}
+
+	/**
+	 * template
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function template($state = 1)
+	{
+		//$path = str_replace(DEVER_APP_PATH, '', $this->assets);
+		//$path = $path == $this->assets ? str_replace(DEVER_PATH, '', $this->assets) : $path;
+		if($this->path && strpos($this->assets, DIRECTORY_SEPARATOR . $this->path) !== false)
+		{
+			$this->path = '';
+		}
+
+		$html = isset(Config::$global['base']['html']) ? Config::$global['base']['html'] . DIRECTORY_SEPARATOR : self::TEMPLATE . DIRECTORY_SEPARATOR; 
+
+		$this->template = $this->assets  . $this->path . $html;
+
+		if($state == 1 && !is_file($this->template . $this->file . '.html') && isset(Config::$global['base']['template']) && is_array(Config::$global['base']['template']) && isset(Config::$global['base']['template'][0]))
+		{
+			# 当前文件不存在,则跳转
+			$this->path(Config::$global['base']['template'][0] . DIRECTORY_SEPARATOR);
+			
+			return $this->template(2);
+		}
+		
+		//echo Config::$global['host']['css'];die;
+
+		/*
+		if($this->path && (DEVER_APP_LIB . DIRECTORY_SEPARATOR == $this->path || DEVER_APP_NAME . DIRECTORY_SEPARATOR == $this->path))
+		{
+			$this->path = '';
+		}
+		*/
+
+		$this->sername = (isset(Config::$global['base']['service']) && $this->path) ? Config::$global['base']['service'] . DIRECTORY_SEPARATOR : $this->path;
+
+		$this->service 	= $this->service . $this->sername . $this->file . '.php';
+
+		//echo $this->service . "\r\n";
+
+		$this->replace();
+		
+		return $this;
+	}
+
+	private function replace()
+	{
+		if($this->path && empty(Config::$global['host']['replace']))
+		{
+			if(isset(Config::$global['base']['replace']) && is_array(Config::$global['base']['replace']))
+			{
+				foreach(Config::$global['base']['replace'] as $k => $v)
+				{
+					$this->replaceOne($k);
+				}
+			}
+
+	        Config::$global['host']['replace'] = true;
+		}
+	}
+
+	private function replaceOne($k)
+	{
+		if($k == 'public')
+		{
+			return;
+		}
+		$key = 'assets/';
+
+		if(isset(Config::$global['base']['template']) && is_array(Config::$global['base']['template']))
+		{
+			foreach(Config::$global['base']['template'] as $v)
+			{
+				if(isset(Config::$global['host'][$k]) && strpos(Config::$global['host'][$k], $key . $v) !== false)
+				{
+					return;
+				}
+			}
+		}
+
+		if(isset(Config::$global['host'][$k]))
+		{
+			Config::$global['host'][$k] = str_replace($key, $key . $this->path, Config::$global['host'][$k]);
+		}
+	}
+
+	/**
+	 * fetch
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function fetch()
+	{
+		$this->method[] = func_get_args();
+
+		return $this;
+	}
+
+	/**
+	 * check
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function check()
+	{
+		$this->method[] = func_get_args();
+
+		return $this;
+	}
+
+	/**
+	 * set 设置变量
+	 * @param $key 变量名
+	 * @param $value 变量的值
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function set($key, $value = false)
+	{
+		$this->compile->set($key, $value);
+
+		return $this;
+	}
+
+	/**
+	 * hook
+	 * @param $key
+	 *
+	 * @return \Dever\Template\View
+	 */
+	public function hook($key, $value)
+	{
+		$this->compile->set('Dever::$global[\'hook\'][\'' . $key. '\']', $value);
+
+		$value = '<{function(){echo 1;}}>';
+		$this->fetch($key, $value);
+
+		return $this;
+	}
+
+	/**
+	 * display
+	 * @param $file 文件名
+	 * @param $local 是否本地化 默认不抓取文件到本地
+	 *
+	 * @return mixed
+	 */
+	public function display($file = false, $local = false)
+	{
+		if($file)
+		{
+			$this->compile->read($file, $this->template, $this->service, $local);
+		}
+
+		if($this->method)
+		{
+			if(is_string($this->parse))
+			{
+				$this->parse($this->parse);
+			}
+
+			if(is_object($this->parse))
+			{
+				$node = array();
+
+				if(isset(Config::$global['base']['data']))
+		        {
+		            $path = Config::$global['base']['data'];
+		        }
+		        else
+		        {
+		            $path = DEVER_PATH . 'data/';
+		        }
+				$file = $path . 'node/' . DEVER_APP_NAME . '_' . trim($this->sername, DIRECTORY_SEPARATOR) . '.php';
+				if(is_file($file))
+				{
+					$node = include($file);
+				}
+				
+				# 为了更好的兼容大部分php配置,取消这里的匿名函数...
+				foreach($this->method as $k => $v)
+				{
+					$this->parse->make($v);
+					# 节点记录
+					//$this->node($node, $v);
+				}
+
+				if($node)
+				{
+					file_put_contents($file, '<?php return ' . var_export($node, true) . ';');
+				}
+				
+				/*
+				$callback = function($param, $key)
+				{
+					$this->parse->make($param);
+				};
+
+				array_walk($this->method, $callback);
+				*/
+
+				$this->content = $this->compile->create($this->parse->get());
+			}
+		}
+		else
+		{
+			$this->content = $this->compile->create($this->content);
+		}
+
+		return $this->content;
+	}
+	
+	private function node(&$node, $param = array())
+	{
+		$config = array('none', 'null', 'remove');
+		if((isset($param[2]) && is_string($param[2]) && !array_search($param[2], $config)) || (isset($param[3]) && is_string($param[3])))
+		{
+			if(is_array($param[0]))
+			{
+				$param[0] = implode(',', $param[0]);
+			}
+			
+			$node[$this->file][$param[0]] = $param;
+		}
+	}
+
+	/**
+	 * result 获取当前视图模板的基本信息
+	 *
+	 * @return array
+	 */
+	public function result()
+	{
+		$result['service'] = $this->service;
+		$result['template'] = $this->template . $this->file . '.html';
+		$result['cmp'] = $this->compile->file();
+
+		//$content = file_get_contents($result['template']);
+
+		//$rule = '<script class="include"(.*?)path="(.*?)"(.*?)file="(.*?)"(.*?)><\/script>';
+
+        //preg_match_all(DIRECTORY_SEPARATOR . $rule . '/i', $content, $result);
+		
+		return $result;
+	}
+
+	private function cache($key, $data = false)
+    {
+        return Dever::cache($key, $data, 0, 'html');
+    }
+}

+ 343 - 0
vendor/dever-main/framework/src/Dever/Upload/Upload.php

@@ -0,0 +1,343 @@
+<?php namespace Dever\Plad;
+
+class Upload
+{
+	/**
+	 * base path
+	 *
+	 * @var string
+	 */
+	const path = 'data';
+	
+    /**
+     * config
+     *
+     * @var array
+     */
+    private $config = array();
+
+    /**
+     * data
+     *
+     * @var array
+     */
+    private $data = array();
+
+    /**
+     * __construct
+     * 
+     * @return mixed
+     */
+    public function __construct()
+    {}
+
+    /**
+     * save
+     * 
+     * @return mixed
+     */
+    public function save($config)
+    {
+        $this->config  = $config;
+        $this->make();
+        return $this->copy();
+    }
+
+    /**
+     * data
+     * 
+     * @return array
+     */
+    public function data()
+    {
+        return $this->data;
+    }
+
+    /**
+     * create file name
+     * 
+     * @return int
+     */
+    private function file()
+    {
+        //return md5(microtime()+rand()*100);
+        
+        $ext = '.jpg';
+        
+        if($this->data['tmp']['type'] == 'image/gif')
+        {
+			$ext = '.gif';
+		}
+		if(empty($this->config['filename']))
+		{
+			$filename = md5($this->data['tmp']['name']);
+			$this->data['filename'] = $filename . $ext;
+		}
+		else
+		{
+			$this->data['filename'] = $this->config['filename'];
+		}
+    }
+    
+    /**
+     * create path
+     * 
+     * @return mixed
+     */
+    private function create($path)
+    {
+		if(is_array($path))
+		{
+			foreach($path as $v)
+			{
+				$this->create($v);
+			}
+		}
+		else
+		{
+			if(isset($this->config['id']) && $this->config['id'] > 0)
+			{
+				$id = ceil($this->config['id']/1000);
+				
+				$filepath = \Helper::path(DEVER_PATH . self::path, $path . $id . '/');
+			}
+			else
+			{
+				$filepath = \Helper::path(DEVER_PATH . self::path, $path . date("Y") . '/' . date("m") . '/' . date("d") . '/');
+			}
+			
+			$this->data[$path . '_file'] = $filepath . $this->data['filename'];
+		}
+    }
+
+    /**
+     * make file
+     * 
+     * @return mixed
+     */
+    private function make()
+    {
+        $this->checkConfig();
+        
+        $this->file();
+        
+        $this->create(array('source', 'view'));
+        
+        $this->data['tmp']     = $this->post($this->config['name']);
+    }
+
+    /**
+     * copy file
+     * 
+     * @return mixed
+     */
+    private function copy()
+    {
+        if(isset($this->config['filesize']) && $this->config['filesize'] > 0 && $this->data['tmp']['size'] > $this->config['filesize'])
+        {
+            return $this->error('file size error -1');
+        }
+        if(isset($this->config['filelimit']) && strstr($this->config['filelimit'], '*'))
+        {
+            $imgstream = file_get_contents($this->data['tmp']['tmp_name']);
+            $im = imagecreatefromstring($imgstream);
+
+            $width = imagesx($im);
+            $height = imagesy($im);
+
+            @imagedestroy($im);
+            $attribute = explode(',', $this->config['filelimit']);
+            $array = explode('*', $attribute[0]);
+
+            if($width > $array[0])
+            {
+                return $this->error('file max width error -2');
+            }
+            if($height > $array[1])
+            {
+                return $this->error('file max height error -3');
+            }
+
+            if(isset($attribute[1]))
+            {
+                $array = explode('*', $attribute[1]);
+                if($width < $array[0])
+                {
+                    return $this->error('file min width error -4');
+                }
+                if($height < $array[1])
+                {
+                    return $this->error('file min height error -5');
+                }
+            }
+        }
+
+        if($this->data['type'] && !strstr($this->data['type'], $this->data['tmp']['type']))
+        {
+            return $this->error('upload type error -6');
+        }
+
+        if(!copy($this->data['tmp']['tmp_name'], $this->data['file']))
+        {
+            return $this->error('upload error -7');
+        }
+        else
+        {
+			# 复制一份用来给用户看的,我们保留一份吧
+			copy($this->data['file'], $this->data['view_file']);
+			//@unlink($this->data['tmp']['tmp_name']);
+            $this->data['name'] = $this->data['tmp']['name'];
+            $this->data['type'] = $this->data['tmp']['type'];
+
+            if(isset($this->config['width']) && $this->config['width'])
+            {
+                $imgstream = file_get_contents($this->data['file']);
+                $im = imagecreatefromstring($imgstream);
+
+                $this->data['width'] = imagesx($im);
+                $this->data['height'] = imagesy($im);
+
+                @imagedestroy($im);
+            }
+            $img = false;
+
+            //图片压缩
+            if(isset($this->config['compress']))
+            {
+                $img = \Helper::core('img');
+                $img->compress($this->data['file'], $this->config['compress']);
+            }
+            
+            //添加水印
+            if(isset($this->config['mark']))
+            {
+                if(!$img)
+                {
+                    $img = \Helper::core('img');
+                }
+                $img->mark($this->data['file'], $this->config['mark']);
+            }
+
+            //建立小图
+            if(isset($this->config['thumb']))
+            {
+                if(!$img)
+                {
+                    $img = \Helper::core('img');
+                }
+                $img->thumb($this->data['file'], $this->config['thumb']);
+            }
+            //建立小图
+            if(isset($this->config['crop']))
+            {
+                if(!$img)
+                {
+                    $img = \Helper::core('img');
+                }
+                $img->crop($this->data['file'], $this->config['crop']);
+            }
+
+            return $this->data;
+        }
+    }
+
+    /**
+     * @desc 检测是否设置了配置
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function checkConfig()
+    {
+        if(!$this->config)
+        {
+            $this->error('config error');
+        }
+        if(!isset($this->config['name']))
+        {
+            $this->error('name error');
+        }
+        if(!isset($this->config['filetype']))
+        {
+            $this->config['filetype'] = 'file';
+        }
+        if(isset($this->config['filepath']) && $this->config['filepath'])
+        {
+            $this->config['filepath'] .= '/';
+        }
+
+        $this->data['type'] = false;
+        switch($this->config['filetype'])
+        {
+            case 'file':
+                $this->data['type'] = 'image/png,image/x-png,image/jpg,image/jpeg,image/pjpeg,image/gif,image/bmp,application/javascript,text/css,application/octet-stream';
+                break;
+            case 'img':
+                $this->data['type'] = 'image/png,image/jpg,image/x-png,image/jpeg,image/pjpeg,image/gif,image/bmp,application/octet-stream';
+                break;
+            case 'excel':
+                $this->data['type'] = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
+                break;
+            case 'stream':
+                $this->data['type'] = 'application/octet-stream';
+                break;
+        }
+    }
+
+    /**
+     * @desc 获取post数据
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function post($name)
+    {
+		# 判断是否网络文件
+		if(strpos($name, 'http://') !== false)
+		{
+			$state = false;
+			if(strpos($name, '.jpg') !== false)
+			{
+				$state = true;
+				$data['type'] = 'image/jpeg';
+			}
+			elseif(strpos($name, '.gif') !== false)
+			{
+				$state = true;
+				$data['type'] = 'image/gif';
+				$this->_data['filename'] = str_replace('.jpg', '.gif', $this->_data['filename']);
+			}
+			else
+			{
+				$data['type'] = '';
+			}
+			
+			if($state == true)
+			{
+				$data['name'] = md5($name);
+				$data['tmp_name'] = $name;
+			}
+			
+			return $data;
+		}
+		else
+		{
+			return $this->data['post'][$name] = \Input::get($name);
+		}
+
+        return false;
+    }
+
+    /**
+     * @desc 匹配错误
+     * @param *
+     * @author leo(suwi.bin)
+     * @date 2012-03-23
+     */
+    private function error($string, $type = 1)
+    {
+        $errstr = '' ;
+        $errstr .= "Upload Error:" . $string . "\n";
+        return $errstr;
+    }
+}

+ 16 - 0
vendor/erusev/parsedown/.travis.yml

@@ -0,0 +1,16 @@
+language: php
+
+php:
+  - 7.0
+  - 5.6
+  - 5.5
+  - 5.4
+  - 5.3
+  - hhvm
+  - hhvm-nightly
+
+matrix:
+  fast_finish: true
+  allow_failures:
+    - php: 7.0
+    - php: hhvm-nightly

+ 20 - 0
vendor/erusev/parsedown/LICENSE.txt

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Emanuil Rusev, erusev.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 1528 - 0
vendor/erusev/parsedown/Parsedown.php

@@ -0,0 +1,1528 @@
+<?php
+
+#
+#
+# Parsedown
+# http://parsedown.org
+#
+# (c) Emanuil Rusev
+# http://erusev.com
+#
+# For the full license information, view the LICENSE file that was distributed
+# with this source code.
+#
+#
+
+class Parsedown
+{
+    # ~
+
+    const version = '1.6.0';
+
+    # ~
+
+    function text($text)
+    {
+        # make sure no definitions are set
+        $this->DefinitionData = array();
+
+        # standardize line breaks
+        $text = str_replace(array("\r\n", "\r"), "\n", $text);
+
+        # remove surrounding line breaks
+        $text = trim($text, "\n");
+
+        # split text into lines
+        $lines = explode("\n", $text);
+
+        # iterate through lines to identify blocks
+        $markup = $this->lines($lines);
+
+        # trim line breaks
+        $markup = trim($markup, "\n");
+
+        return $markup;
+    }
+
+    #
+    # Setters
+    #
+
+    function setBreaksEnabled($breaksEnabled)
+    {
+        $this->breaksEnabled = $breaksEnabled;
+
+        return $this;
+    }
+
+    protected $breaksEnabled;
+
+    function setMarkupEscaped($markupEscaped)
+    {
+        $this->markupEscaped = $markupEscaped;
+
+        return $this;
+    }
+
+    protected $markupEscaped;
+
+    function setUrlsLinked($urlsLinked)
+    {
+        $this->urlsLinked = $urlsLinked;
+
+        return $this;
+    }
+
+    protected $urlsLinked = true;
+
+    #
+    # Lines
+    #
+
+    protected $BlockTypes = array(
+        '#' => array('Header'),
+        '*' => array('Rule', 'List'),
+        '+' => array('List'),
+        '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
+        '0' => array('List'),
+        '1' => array('List'),
+        '2' => array('List'),
+        '3' => array('List'),
+        '4' => array('List'),
+        '5' => array('List'),
+        '6' => array('List'),
+        '7' => array('List'),
+        '8' => array('List'),
+        '9' => array('List'),
+        ':' => array('Table'),
+        '<' => array('Comment', 'Markup'),
+        '=' => array('SetextHeader'),
+        '>' => array('Quote'),
+        '[' => array('Reference'),
+        '_' => array('Rule'),
+        '`' => array('FencedCode'),
+        '|' => array('Table'),
+        '~' => array('FencedCode'),
+    );
+
+    # ~
+
+    protected $unmarkedBlockTypes = array(
+        'Code',
+    );
+
+    #
+    # Blocks
+    #
+
+    private function lines(array $lines)
+    {
+        $CurrentBlock = null;
+
+        foreach ($lines as $line)
+        {
+            if (chop($line) === '')
+            {
+                if (isset($CurrentBlock))
+                {
+                    $CurrentBlock['interrupted'] = true;
+                }
+
+                continue;
+            }
+
+            if (strpos($line, "\t") !== false)
+            {
+                $parts = explode("\t", $line);
+
+                $line = $parts[0];
+
+                unset($parts[0]);
+
+                foreach ($parts as $part)
+                {
+                    $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
+
+                    $line .= str_repeat(' ', $shortage);
+                    $line .= $part;
+                }
+            }
+
+            $indent = 0;
+
+            while (isset($line[$indent]) and $line[$indent] === ' ')
+            {
+                $indent ++;
+            }
+
+            $text = $indent > 0 ? substr($line, $indent) : $line;
+
+            # ~
+
+            $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
+
+            # ~
+
+            if (isset($CurrentBlock['continuable']))
+            {
+                $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
+
+                if (isset($Block))
+                {
+                    $CurrentBlock = $Block;
+
+                    continue;
+                }
+                else
+                {
+                    if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
+                    {
+                        $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
+                    }
+                }
+            }
+
+            # ~
+
+            $marker = $text[0];
+
+            # ~
+
+            $blockTypes = $this->unmarkedBlockTypes;
+
+            if (isset($this->BlockTypes[$marker]))
+            {
+                foreach ($this->BlockTypes[$marker] as $blockType)
+                {
+                    $blockTypes []= $blockType;
+                }
+            }
+
+            #
+            # ~
+
+            foreach ($blockTypes as $blockType)
+            {
+                $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
+
+                if (isset($Block))
+                {
+                    $Block['type'] = $blockType;
+
+                    if ( ! isset($Block['identified']))
+                    {
+                        $Blocks []= $CurrentBlock;
+
+                        $Block['identified'] = true;
+                    }
+
+                    if (method_exists($this, 'block'.$blockType.'Continue'))
+                    {
+                        $Block['continuable'] = true;
+                    }
+
+                    $CurrentBlock = $Block;
+
+                    continue 2;
+                }
+            }
+
+            # ~
+
+            if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
+            {
+                $CurrentBlock['element']['text'] .= "\n".$text;
+            }
+            else
+            {
+                $Blocks []= $CurrentBlock;
+
+                $CurrentBlock = $this->paragraph($Line);
+
+                $CurrentBlock['identified'] = true;
+            }
+        }
+
+        # ~
+
+        if (isset($CurrentBlock['continuable']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete'))
+        {
+            $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
+        }
+
+        # ~
+
+        $Blocks []= $CurrentBlock;
+
+        unset($Blocks[0]);
+
+        # ~
+
+        $markup = '';
+
+        foreach ($Blocks as $Block)
+        {
+            if (isset($Block['hidden']))
+            {
+                continue;
+            }
+
+            $markup .= "\n";
+            $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
+        }
+
+        $markup .= "\n";
+
+        # ~
+
+        return $markup;
+    }
+
+    #
+    # Code
+
+    protected function blockCode($Line, $Block = null)
+    {
+        if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
+        {
+            return;
+        }
+
+        if ($Line['indent'] >= 4)
+        {
+            $text = substr($Line['body'], 4);
+
+            $Block = array(
+                'element' => array(
+                    'name' => 'pre',
+                    'handler' => 'element',
+                    'text' => array(
+                        'name' => 'code',
+                        'text' => $text,
+                    ),
+                ),
+            );
+
+            return $Block;
+        }
+    }
+
+    protected function blockCodeContinue($Line, $Block)
+    {
+        if ($Line['indent'] >= 4)
+        {
+            if (isset($Block['interrupted']))
+            {
+                $Block['element']['text']['text'] .= "\n";
+
+                unset($Block['interrupted']);
+            }
+
+            $Block['element']['text']['text'] .= "\n";
+
+            $text = substr($Line['body'], 4);
+
+            $Block['element']['text']['text'] .= $text;
+
+            return $Block;
+        }
+    }
+
+    protected function blockCodeComplete($Block)
+    {
+        $text = $Block['element']['text']['text'];
+
+        $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+
+        $Block['element']['text']['text'] = $text;
+
+        return $Block;
+    }
+
+    #
+    # Comment
+
+    protected function blockComment($Line)
+    {
+        if ($this->markupEscaped)
+        {
+            return;
+        }
+
+        if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
+        {
+            $Block = array(
+                'markup' => $Line['body'],
+            );
+
+            if (preg_match('/-->$/', $Line['text']))
+            {
+                $Block['closed'] = true;
+            }
+
+            return $Block;
+        }
+    }
+
+    protected function blockCommentContinue($Line, array $Block)
+    {
+        if (isset($Block['closed']))
+        {
+            return;
+        }
+
+        $Block['markup'] .= "\n" . $Line['body'];
+
+        if (preg_match('/-->$/', $Line['text']))
+        {
+            $Block['closed'] = true;
+        }
+
+        return $Block;
+    }
+
+    #
+    # Fenced Code
+
+    protected function blockFencedCode($Line)
+    {
+        if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
+        {
+            $Element = array(
+                'name' => 'code',
+                'text' => '',
+            );
+
+            if (isset($matches[1]))
+            {
+                $class = 'language-'.$matches[1];
+
+                $Element['attributes'] = array(
+                    'class' => $class,
+                );
+            }
+
+            $Block = array(
+                'char' => $Line['text'][0],
+                'element' => array(
+                    'name' => 'pre',
+                    'handler' => 'element',
+                    'text' => $Element,
+                ),
+            );
+
+            return $Block;
+        }
+    }
+
+    protected function blockFencedCodeContinue($Line, $Block)
+    {
+        if (isset($Block['complete']))
+        {
+            return;
+        }
+
+        if (isset($Block['interrupted']))
+        {
+            $Block['element']['text']['text'] .= "\n";
+
+            unset($Block['interrupted']);
+        }
+
+        if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
+        {
+            $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
+
+            $Block['complete'] = true;
+
+            return $Block;
+        }
+
+        $Block['element']['text']['text'] .= "\n".$Line['body'];;
+
+        return $Block;
+    }
+
+    protected function blockFencedCodeComplete($Block)
+    {
+        $text = $Block['element']['text']['text'];
+
+        $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+
+        $Block['element']['text']['text'] = $text;
+
+        return $Block;
+    }
+
+    #
+    # Header
+
+    protected function blockHeader($Line)
+    {
+        if (isset($Line['text'][1]))
+        {
+            $level = 1;
+
+            while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
+            {
+                $level ++;
+            }
+
+            if ($level > 6)
+            {
+                return;
+            }
+
+            $text = trim($Line['text'], '# ');
+
+            $Block = array(
+                'element' => array(
+                    'name' => 'h' . min(6, $level),
+                    'text' => $text,
+                    'handler' => 'line',
+                ),
+            );
+
+            return $Block;
+        }
+    }
+
+    #
+    # List
+
+    protected function blockList($Line)
+    {
+        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
+
+        if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
+        {
+            $Block = array(
+                'indent' => $Line['indent'],
+                'pattern' => $pattern,
+                'element' => array(
+                    'name' => $name,
+                    'handler' => 'elements',
+                ),
+            );
+
+            $Block['li'] = array(
+                'name' => 'li',
+                'handler' => 'li',
+                'text' => array(
+                    $matches[2],
+                ),
+            );
+
+            $Block['element']['text'] []= & $Block['li'];
+
+            return $Block;
+        }
+    }
+
+    protected function blockListContinue($Line, array $Block)
+    {
+        if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
+        {
+            if (isset($Block['interrupted']))
+            {
+                $Block['li']['text'] []= '';
+
+                unset($Block['interrupted']);
+            }
+
+            unset($Block['li']);
+
+            $text = isset($matches[1]) ? $matches[1] : '';
+
+            $Block['li'] = array(
+                'name' => 'li',
+                'handler' => 'li',
+                'text' => array(
+                    $text,
+                ),
+            );
+
+            $Block['element']['text'] []= & $Block['li'];
+
+            return $Block;
+        }
+
+        if ($Line['text'][0] === '[' and $this->blockReference($Line))
+        {
+            return $Block;
+        }
+
+        if ( ! isset($Block['interrupted']))
+        {
+            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
+
+            $Block['li']['text'] []= $text;
+
+            return $Block;
+        }
+
+        if ($Line['indent'] > 0)
+        {
+            $Block['li']['text'] []= '';
+
+            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
+
+            $Block['li']['text'] []= $text;
+
+            unset($Block['interrupted']);
+
+            return $Block;
+        }
+    }
+
+    #
+    # Quote
+
+    protected function blockQuote($Line)
+    {
+        if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
+        {
+            $Block = array(
+                'element' => array(
+                    'name' => 'blockquote',
+                    'handler' => 'lines',
+                    'text' => (array) $matches[1],
+                ),
+            );
+
+            return $Block;
+        }
+    }
+
+    protected function blockQuoteContinue($Line, array $Block)
+    {
+        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
+        {
+            if (isset($Block['interrupted']))
+            {
+                $Block['element']['text'] []= '';
+
+                unset($Block['interrupted']);
+            }
+
+            $Block['element']['text'] []= $matches[1];
+
+            return $Block;
+        }
+
+        if ( ! isset($Block['interrupted']))
+        {
+            $Block['element']['text'] []= $Line['text'];
+
+            return $Block;
+        }
+    }
+
+    #
+    # Rule
+
+    protected function blockRule($Line)
+    {
+        if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
+        {
+            $Block = array(
+                'element' => array(
+                    'name' => 'hr'
+                ),
+            );
+
+            return $Block;
+        }
+    }
+
+    #
+    # Setext
+
+    protected function blockSetextHeader($Line, array $Block = null)
+    {
+        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
+        {
+            return;
+        }
+
+        if (chop($Line['text'], $Line['text'][0]) === '')
+        {
+            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
+
+            return $Block;
+        }
+    }
+
+    #
+    # Markup
+
+    protected function blockMarkup($Line)
+    {
+        if ($this->markupEscaped)
+        {
+            return;
+        }
+
+        if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
+        {
+            $element = strtolower($matches[1]);
+
+            if (in_array($element, $this->textLevelElements))
+            {
+                return;
+            }
+
+            $Block = array(
+                'name' => $matches[1],
+                'depth' => 0,
+                'markup' => $Line['text'],
+            );
+
+            $length = strlen($matches[0]);
+
+            $remainder = substr($Line['text'], $length);
+
+            if (trim($remainder) === '')
+            {
+                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
+                {
+                    $Block['closed'] = true;
+
+                    $Block['void'] = true;
+                }
+            }
+            else
+            {
+                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
+                {
+                    return;
+                }
+
+                if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
+                {
+                    $Block['closed'] = true;
+                }
+            }
+
+            return $Block;
+        }
+    }
+
+    protected function blockMarkupContinue($Line, array $Block)
+    {
+        if (isset($Block['closed']))
+        {
+            return;
+        }
+
+        if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
+        {
+            $Block['depth'] ++;
+        }
+
+        if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
+        {
+            if ($Block['depth'] > 0)
+            {
+                $Block['depth'] --;
+            }
+            else
+            {
+                $Block['closed'] = true;
+            }
+        }
+
+        if (isset($Block['interrupted']))
+        {
+            $Block['markup'] .= "\n";
+
+            unset($Block['interrupted']);
+        }
+
+        $Block['markup'] .= "\n".$Line['body'];
+
+        return $Block;
+    }
+
+    #
+    # Reference
+
+    protected function blockReference($Line)
+    {
+        if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
+        {
+            $id = strtolower($matches[1]);
+
+            $Data = array(
+                'url' => $matches[2],
+                'title' => null,
+            );
+
+            if (isset($matches[3]))
+            {
+                $Data['title'] = $matches[3];
+            }
+
+            $this->DefinitionData['Reference'][$id] = $Data;
+
+            $Block = array(
+                'hidden' => true,
+            );
+
+            return $Block;
+        }
+    }
+
+    #
+    # Table
+
+    protected function blockTable($Line, array $Block = null)
+    {
+        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
+        {
+            return;
+        }
+
+        if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
+        {
+            $alignments = array();
+
+            $divider = $Line['text'];
+
+            $divider = trim($divider);
+            $divider = trim($divider, '|');
+
+            $dividerCells = explode('|', $divider);
+
+            foreach ($dividerCells as $dividerCell)
+            {
+                $dividerCell = trim($dividerCell);
+
+                if ($dividerCell === '')
+                {
+                    continue;
+                }
+
+                $alignment = null;
+
+                if ($dividerCell[0] === ':')
+                {
+                    $alignment = 'left';
+                }
+
+                if (substr($dividerCell, - 1) === ':')
+                {
+                    $alignment = $alignment === 'left' ? 'center' : 'right';
+                }
+
+                $alignments []= $alignment;
+            }
+
+            # ~
+
+            $HeaderElements = array();
+
+            $header = $Block['element']['text'];
+
+            $header = trim($header);
+            $header = trim($header, '|');
+
+            $headerCells = explode('|', $header);
+
+            foreach ($headerCells as $index => $headerCell)
+            {
+                $headerCell = trim($headerCell);
+
+                $HeaderElement = array(
+                    'name' => 'th',
+                    'text' => $headerCell,
+                    'handler' => 'line',
+                );
+
+                if (isset($alignments[$index]))
+                {
+                    $alignment = $alignments[$index];
+
+                    $HeaderElement['attributes'] = array(
+                        'style' => 'text-align: '.$alignment.';',
+                    );
+                }
+
+                $HeaderElements []= $HeaderElement;
+            }
+
+            # ~
+
+            $Block = array(
+                'alignments' => $alignments,
+                'identified' => true,
+                'element' => array(
+                    'name' => 'table',
+                    'handler' => 'elements',
+                ),
+            );
+
+            $Block['element']['text'] []= array(
+                'name' => 'thead',
+                'handler' => 'elements',
+            );
+
+            $Block['element']['text'] []= array(
+                'name' => 'tbody',
+                'handler' => 'elements',
+                'text' => array(),
+            );
+
+            $Block['element']['text'][0]['text'] []= array(
+                'name' => 'tr',
+                'handler' => 'elements',
+                'text' => $HeaderElements,
+            );
+
+            return $Block;
+        }
+    }
+
+    protected function blockTableContinue($Line, array $Block)
+    {
+        if (isset($Block['interrupted']))
+        {
+            return;
+        }
+
+        if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
+        {
+            $Elements = array();
+
+            $row = $Line['text'];
+
+            $row = trim($row);
+            $row = trim($row, '|');
+
+            preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
+
+            foreach ($matches[0] as $index => $cell)
+            {
+                $cell = trim($cell);
+
+                $Element = array(
+                    'name' => 'td',
+                    'handler' => 'line',
+                    'text' => $cell,
+                );
+
+                if (isset($Block['alignments'][$index]))
+                {
+                    $Element['attributes'] = array(
+                        'style' => 'text-align: '.$Block['alignments'][$index].';',
+                    );
+                }
+
+                $Elements []= $Element;
+            }
+
+            $Element = array(
+                'name' => 'tr',
+                'handler' => 'elements',
+                'text' => $Elements,
+            );
+
+            $Block['element']['text'][1]['text'] []= $Element;
+
+            return $Block;
+        }
+    }
+
+    #
+    # ~
+    #
+
+    protected function paragraph($Line)
+    {
+        $Block = array(
+            'element' => array(
+                'name' => 'p',
+                'text' => $Line['text'],
+                'handler' => 'line',
+            ),
+        );
+
+        return $Block;
+    }
+
+    #
+    # Inline Elements
+    #
+
+    protected $InlineTypes = array(
+        '"' => array('SpecialCharacter'),
+        '!' => array('Image'),
+        '&' => array('SpecialCharacter'),
+        '*' => array('Emphasis'),
+        ':' => array('Url'),
+        '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
+        '>' => array('SpecialCharacter'),
+        '[' => array('Link'),
+        '_' => array('Emphasis'),
+        '`' => array('Code'),
+        '~' => array('Strikethrough'),
+        '\\' => array('EscapeSequence'),
+    );
+
+    # ~
+
+    protected $inlineMarkerList = '!"*_&[:<>`~\\';
+
+    #
+    # ~
+    #
+
+    public function line($text)
+    {
+        $markup = '';
+
+        # $excerpt is based on the first occurrence of a marker
+
+        while ($excerpt = strpbrk($text, $this->inlineMarkerList))
+        {
+            $marker = $excerpt[0];
+
+            $markerPosition = strpos($text, $marker);
+
+            $Excerpt = array('text' => $excerpt, 'context' => $text);
+
+            foreach ($this->InlineTypes[$marker] as $inlineType)
+            {
+                $Inline = $this->{'inline'.$inlineType}($Excerpt);
+
+                if ( ! isset($Inline))
+                {
+                    continue;
+                }
+
+                # makes sure that the inline belongs to "our" marker
+
+                if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
+                {
+                    continue;
+                }
+
+                # sets a default inline position
+
+                if ( ! isset($Inline['position']))
+                {
+                    $Inline['position'] = $markerPosition;
+                }
+
+                # the text that comes before the inline
+                $unmarkedText = substr($text, 0, $Inline['position']);
+
+                # compile the unmarked text
+                $markup .= $this->unmarkedText($unmarkedText);
+
+                # compile the inline
+                $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
+
+                # remove the examined text
+                $text = substr($text, $Inline['position'] + $Inline['extent']);
+
+                continue 2;
+            }
+
+            # the marker does not belong to an inline
+
+            $unmarkedText = substr($text, 0, $markerPosition + 1);
+
+            $markup .= $this->unmarkedText($unmarkedText);
+
+            $text = substr($text, $markerPosition + 1);
+        }
+
+        $markup .= $this->unmarkedText($text);
+
+        return $markup;
+    }
+
+    #
+    # ~
+    #
+
+    protected function inlineCode($Excerpt)
+    {
+        $marker = $Excerpt['text'][0];
+
+        if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
+        {
+            $text = $matches[2];
+            $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+            $text = preg_replace("/[ ]*\n/", ' ', $text);
+
+            return array(
+                'extent' => strlen($matches[0]),
+                'element' => array(
+                    'name' => 'code',
+                    'text' => $text,
+                ),
+            );
+        }
+    }
+
+    protected function inlineEmailTag($Excerpt)
+    {
+        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
+        {
+            $url = $matches[1];
+
+            if ( ! isset($matches[2]))
+            {
+                $url = 'mailto:' . $url;
+            }
+
+            return array(
+                'extent' => strlen($matches[0]),
+                'element' => array(
+                    'name' => 'a',
+                    'text' => $matches[1],
+                    'attributes' => array(
+                        'href' => $url,
+                    ),
+                ),
+            );
+        }
+    }
+
+    protected function inlineEmphasis($Excerpt)
+    {
+        if ( ! isset($Excerpt['text'][1]))
+        {
+            return;
+        }
+
+        $marker = $Excerpt['text'][0];
+
+        if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
+        {
+            $emphasis = 'strong';
+        }
+        elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
+        {
+            $emphasis = 'em';
+        }
+        else
+        {
+            return;
+        }
+
+        return array(
+            'extent' => strlen($matches[0]),
+            'element' => array(
+                'name' => $emphasis,
+                'handler' => 'line',
+                'text' => $matches[1],
+            ),
+        );
+    }
+
+    protected function inlineEscapeSequence($Excerpt)
+    {
+        if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
+        {
+            return array(
+                'markup' => $Excerpt['text'][1],
+                'extent' => 2,
+            );
+        }
+    }
+
+    protected function inlineImage($Excerpt)
+    {
+        if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
+        {
+            return;
+        }
+
+        $Excerpt['text']= substr($Excerpt['text'], 1);
+
+        $Link = $this->inlineLink($Excerpt);
+
+        if ($Link === null)
+        {
+            return;
+        }
+
+        $Inline = array(
+            'extent' => $Link['extent'] + 1,
+            'element' => array(
+                'name' => 'img',
+                'attributes' => array(
+                    'src' => $Link['element']['attributes']['href'],
+                    'alt' => $Link['element']['text'],
+                ),
+            ),
+        );
+
+        $Inline['element']['attributes'] += $Link['element']['attributes'];
+
+        unset($Inline['element']['attributes']['href']);
+
+        return $Inline;
+    }
+
+    protected function inlineLink($Excerpt)
+    {
+        $Element = array(
+            'name' => 'a',
+            'handler' => 'line',
+            'text' => null,
+            'attributes' => array(
+                'href' => null,
+                'title' => null,
+            ),
+        );
+
+        $extent = 0;
+
+        $remainder = $Excerpt['text'];
+
+        if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
+        {
+            $Element['text'] = $matches[1];
+
+            $extent += strlen($matches[0]);
+
+            $remainder = substr($remainder, $extent);
+        }
+        else
+        {
+            return;
+        }
+
+        if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
+        {
+            $Element['attributes']['href'] = $matches[1];
+
+            if (isset($matches[2]))
+            {
+                $Element['attributes']['title'] = substr($matches[2], 1, - 1);
+            }
+
+            $extent += strlen($matches[0]);
+        }
+        else
+        {
+            if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
+            {
+                $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
+                $definition = strtolower($definition);
+
+                $extent += strlen($matches[0]);
+            }
+            else
+            {
+                $definition = strtolower($Element['text']);
+            }
+
+            if ( ! isset($this->DefinitionData['Reference'][$definition]))
+            {
+                return;
+            }
+
+            $Definition = $this->DefinitionData['Reference'][$definition];
+
+            $Element['attributes']['href'] = $Definition['url'];
+            $Element['attributes']['title'] = $Definition['title'];
+        }
+
+        $Element['attributes']['href'] = str_replace(array('&', '<'), array('&amp;', '&lt;'), $Element['attributes']['href']);
+
+        return array(
+            'extent' => $extent,
+            'element' => $Element,
+        );
+    }
+
+    protected function inlineMarkup($Excerpt)
+    {
+        if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
+        {
+            return;
+        }
+
+        if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
+        {
+            return array(
+                'markup' => $matches[0],
+                'extent' => strlen($matches[0]),
+            );
+        }
+
+        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
+        {
+            return array(
+                'markup' => $matches[0],
+                'extent' => strlen($matches[0]),
+            );
+        }
+
+        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
+        {
+            return array(
+                'markup' => $matches[0],
+                'extent' => strlen($matches[0]),
+            );
+        }
+    }
+
+    protected function inlineSpecialCharacter($Excerpt)
+    {
+        if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
+        {
+            return array(
+                'markup' => '&amp;',
+                'extent' => 1,
+            );
+        }
+
+        $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
+
+        if (isset($SpecialCharacter[$Excerpt['text'][0]]))
+        {
+            return array(
+                'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
+                'extent' => 1,
+            );
+        }
+    }
+
+    protected function inlineStrikethrough($Excerpt)
+    {
+        if ( ! isset($Excerpt['text'][1]))
+        {
+            return;
+        }
+
+        if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
+        {
+            return array(
+                'extent' => strlen($matches[0]),
+                'element' => array(
+                    'name' => 'del',
+                    'text' => $matches[1],
+                    'handler' => 'line',
+                ),
+            );
+        }
+    }
+
+    protected function inlineUrl($Excerpt)
+    {
+        if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
+        {
+            return;
+        }
+
+        if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
+        {
+            $Inline = array(
+                'extent' => strlen($matches[0][0]),
+                'position' => $matches[0][1],
+                'element' => array(
+                    'name' => 'a',
+                    'text' => $matches[0][0],
+                    'attributes' => array(
+                        'href' => $matches[0][0],
+                    ),
+                ),
+            );
+
+            return $Inline;
+        }
+    }
+
+    protected function inlineUrlTag($Excerpt)
+    {
+        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
+        {
+            $url = str_replace(array('&', '<'), array('&amp;', '&lt;'), $matches[1]);
+
+            return array(
+                'extent' => strlen($matches[0]),
+                'element' => array(
+                    'name' => 'a',
+                    'text' => $url,
+                    'attributes' => array(
+                        'href' => $url,
+                    ),
+                ),
+            );
+        }
+    }
+
+    # ~
+
+    protected function unmarkedText($text)
+    {
+        if ($this->breaksEnabled)
+        {
+            $text = preg_replace('/[ ]*\n/', "<br />\n", $text);
+        }
+        else
+        {
+            $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
+            $text = str_replace(" \n", "\n", $text);
+        }
+
+        return $text;
+    }
+
+    #
+    # Handlers
+    #
+
+    protected function element(array $Element)
+    {
+        $markup = '<'.$Element['name'];
+
+        if (isset($Element['attributes']))
+        {
+            foreach ($Element['attributes'] as $name => $value)
+            {
+                if ($value === null)
+                {
+                    continue;
+                }
+
+                $markup .= ' '.$name.'="'.$value.'"';
+            }
+        }
+
+        if (isset($Element['text']))
+        {
+            $markup .= '>';
+
+            if (isset($Element['handler']))
+            {
+                $markup .= $this->{$Element['handler']}($Element['text']);
+            }
+            else
+            {
+                $markup .= $Element['text'];
+            }
+
+            $markup .= '</'.$Element['name'].'>';
+        }
+        else
+        {
+            $markup .= ' />';
+        }
+
+        return $markup;
+    }
+
+    protected function elements(array $Elements)
+    {
+        $markup = '';
+
+        foreach ($Elements as $Element)
+        {
+            $markup .= "\n" . $this->element($Element);
+        }
+
+        $markup .= "\n";
+
+        return $markup;
+    }
+
+    # ~
+
+    protected function li($lines)
+    {
+        $markup = $this->lines($lines);
+
+        $trimmedMarkup = trim($markup);
+
+        if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
+        {
+            $markup = $trimmedMarkup;
+            $markup = substr($markup, 3);
+
+            $position = strpos($markup, "</p>");
+
+            $markup = substr_replace($markup, '', $position, 4);
+        }
+
+        return $markup;
+    }
+
+    #
+    # Deprecated Methods
+    #
+
+    function parse($text)
+    {
+        $markup = $this->text($text);
+
+        return $markup;
+    }
+
+    #
+    # Static Methods
+    #
+
+    static function instance($name = 'default')
+    {
+        if (isset(self::$instances[$name]))
+        {
+            return self::$instances[$name];
+        }
+
+        $instance = new static();
+
+        self::$instances[$name] = $instance;
+
+        return $instance;
+    }
+
+    private static $instances = array();
+
+    #
+    # Fields
+    #
+
+    protected $DefinitionData;
+
+    #
+    # Read-Only
+
+    protected $specialCharacters = array(
+        '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
+    );
+
+    protected $StrongRegex = array(
+        '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
+        '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
+    );
+
+    protected $EmRegex = array(
+        '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
+        '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
+    );
+
+    protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
+
+    protected $voidElements = array(
+        'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
+    );
+
+    protected $textLevelElements = array(
+        'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
+        'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
+        'i', 'rp', 'del', 'code',          'strike', 'marquee',
+        'q', 'rt', 'ins', 'font',          'strong',
+        's', 'tt', 'sub', 'mark',
+        'u', 'xm', 'sup', 'nobr',
+                   'var', 'ruby',
+                   'wbr', 'span',
+                          'time',
+    );
+}

+ 57 - 0
vendor/erusev/parsedown/README.md

@@ -0,0 +1,57 @@
+## Parsedown
+
+[![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown)
+<!--[![Total Downloads](http://img.shields.io/packagist/dt/erusev/parsedown.svg?style=flat-square)](https://packagist.org/packages/erusev/parsedown)-->
+
+Better Markdown Parser in PHP
+
+[Demo](http://parsedown.org/demo) |
+[Benchmarks](http://parsedown.org/speed) |
+[Tests](http://parsedown.org/tests/) |
+[Documentation](https://github.com/erusev/parsedown/wiki/)
+
+### Features
+
+* Super Fast
+* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
+* Extensible
+* Tested in 5.3 to 5.6
+* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
+
+### Installation
+
+Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
+
+### Example
+
+``` php
+$Parsedown = new Parsedown();
+
+echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
+```
+
+More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
+
+### Questions
+
+**How does Parsedown work?**
+
+It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line start with a `-` then it perhaps belong to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).
+
+We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.
+
+**Is it compliant with CommonMark?**
+
+It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.
+
+**Who uses it?**
+
+[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/),  [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://www.versioneye.com/php/erusev:parsedown/references).
+
+**How can I help?**
+
+Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
+
+---
+
+You might also like [Caret](http://caret.io) - our Markdown editor for the desktop.

+ 18 - 0
vendor/erusev/parsedown/composer.json

@@ -0,0 +1,18 @@
+{
+    "name": "erusev/parsedown",
+    "description": "Parser for Markdown.",
+    "keywords": ["markdown", "parser"],
+    "homepage": "http://parsedown.org",
+    "type": "library",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Emanuil Rusev",
+            "email": "hello@erusev.com",
+            "homepage": "http://erusev.com"
+        }
+    ],
+    "autoload": {
+        "psr-0": {"Parsedown": ""}
+    }
+}

+ 8 - 0
vendor/erusev/parsedown/phpunit.xml.dist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="test/bootstrap.php" colors="true">
+	<testsuites>
+		<testsuite>
+			<file>test/ParsedownTest.php</file>
+		</testsuite>
+	</testsuites>
+</phpunit>

+ 74 - 0
vendor/erusev/parsedown/test/CommonMarkTest.php

@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * Test Parsedown against the CommonMark spec.
+ *
+ * Some code based on the original JavaScript test runner by jgm.
+ *
+ * @link http://commonmark.org/ CommonMark
+ * @link http://git.io/8WtRvQ JavaScript test runner
+ */
+class CommonMarkTest extends PHPUnit_Framework_TestCase
+{
+    const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
+
+    /**
+     * @dataProvider data
+     * @param $section
+     * @param $markdown
+     * @param $expectedHtml
+     */
+    function test_($section, $markdown, $expectedHtml)
+    {
+        $Parsedown = new Parsedown();
+        $Parsedown->setUrlsLinked(false);
+
+        $actualHtml = $Parsedown->text($markdown);
+        $actualHtml = $this->normalizeMarkup($actualHtml);
+
+        $this->assertEquals($expectedHtml, $actualHtml);
+    }
+
+    function data()
+    {
+        $spec = file_get_contents(self::SPEC_URL);
+        $spec = strstr($spec, '<!-- END TESTS -->', true);
+
+        $tests = array();
+        $currentSection = '';
+
+        preg_replace_callback(
+            '/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/m',
+            function($matches) use ( & $tests, & $currentSection, & $testCount) {
+                if (isset($matches[3]) and $matches[3]) {
+                    $currentSection = $matches[3];
+                } else {
+                    $testCount++;
+                    $markdown = $matches[1];
+                    $markdown = preg_replace('/→/', "\t", $markdown);
+                    $expectedHtml = $matches[2];
+                    $expectedHtml = $this->normalizeMarkup($expectedHtml);
+                    $tests []= array(
+                        $currentSection, # section
+                        $markdown, # markdown
+                        $expectedHtml, # html
+                    );
+                }
+            },
+            $spec
+        );
+
+        return $tests;
+    }
+
+    private function normalizeMarkup($markup)
+    {
+        $markup = preg_replace("/\n+/", "\n", $markup);
+        $markup = preg_replace('/^\s+/m', '', $markup);
+        $markup = preg_replace('/^((?:<[\w]+>)+)\n/m', '$1', $markup);
+        $markup = preg_replace('/\n((?:<\/[\w]+>)+)$/m', '$1', $markup);
+        $markup = trim($markup);
+
+        return $markup;
+    }
+}

+ 159 - 0
vendor/erusev/parsedown/test/ParsedownTest.php

@@ -0,0 +1,159 @@
+<?php
+
+class ParsedownTest extends PHPUnit_Framework_TestCase
+{
+    final function __construct($name = null, array $data = array(), $dataName = '')
+    {
+        $this->dirs = $this->initDirs();
+        $this->Parsedown = $this->initParsedown();
+
+        parent::__construct($name, $data, $dataName);
+    }
+
+    private $dirs, $Parsedown;
+
+    /**
+     * @return array
+     */
+    protected function initDirs()
+    {
+        $dirs []= dirname(__FILE__).'/data/';
+
+        return $dirs;
+    }
+
+    /**
+     * @return Parsedown
+     */
+    protected function initParsedown()
+    {
+        $Parsedown = new Parsedown();
+
+        return $Parsedown;
+    }
+
+    /**
+     * @dataProvider data
+     * @param $test
+     * @param $dir
+     */
+    function test_($test, $dir)
+    {
+        $markdown = file_get_contents($dir . $test . '.md');
+
+        $expectedMarkup = file_get_contents($dir . $test . '.html');
+
+        $expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
+        $expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
+
+        $actualMarkup = $this->Parsedown->text($markdown);
+
+        $this->assertEquals($expectedMarkup, $actualMarkup);
+    }
+
+    function data()
+    {
+        $data = array();
+
+        foreach ($this->dirs as $dir)
+        {
+            $Folder = new DirectoryIterator($dir);
+
+            foreach ($Folder as $File)
+            {
+                /** @var $File DirectoryIterator */
+
+                if ( ! $File->isFile())
+                {
+                    continue;
+                }
+
+                $filename = $File->getFilename();
+
+                $extension = pathinfo($filename, PATHINFO_EXTENSION);
+
+                if ($extension !== 'md')
+                {
+                    continue;
+                }
+
+                $basename = $File->getBasename('.md');
+
+                if (file_exists($dir . $basename . '.html'))
+                {
+                    $data []= array($basename, $dir);
+                }
+            }
+        }
+
+        return $data;
+    }
+
+    public function test_no_markup()
+    {
+        $markdownWithHtml = <<<MARKDOWN_WITH_MARKUP
+<div>_content_</div>
+
+sparse:
+
+<div>
+<div class="inner">
+_content_
+</div>
+</div>
+
+paragraph
+
+<style type="text/css">
+    p {
+        color: red;
+    }
+</style>
+
+comment
+
+<!-- html comment -->
+MARKDOWN_WITH_MARKUP;
+
+        $expectedHtml = <<<EXPECTED_HTML
+<p>&lt;div&gt;<em>content</em>&lt;/div&gt;</p>
+<p>sparse:</p>
+<p>&lt;div&gt;
+&lt;div class=&quot;inner&quot;&gt;
+<em>content</em>
+&lt;/div&gt;
+&lt;/div&gt;</p>
+<p>paragraph</p>
+<p>&lt;style type=&quot;text/css&quot;&gt;
+p {
+color: red;
+}
+&lt;/style&gt;</p>
+<p>comment</p>
+<p>&lt;!-- html comment --&gt;</p>
+EXPECTED_HTML;
+        $parsedownWithNoMarkup = new Parsedown();
+        $parsedownWithNoMarkup->setMarkupEscaped(true);
+        $this->assertEquals($expectedHtml, $parsedownWithNoMarkup->text($markdownWithHtml));
+    }
+
+    public function testLateStaticBinding()
+    {
+        include 'test/TestParsedown.php';
+
+        $parsedown = Parsedown::instance();
+        $this->assertInstanceOf('Parsedown', $parsedown);
+
+        // After instance is already called on Parsedown
+        // subsequent calls with the same arguments return the same instance
+        $sameParsedown = TestParsedown::instance();
+        $this->assertInstanceOf('Parsedown', $sameParsedown);
+        $this->assertSame($parsedown, $sameParsedown);
+
+        $testParsedown = TestParsedown::instance('test late static binding');
+        $this->assertInstanceOf('TestParsedown', $testParsedown);
+
+        $sameInstanceAgain = TestParsedown::instance('test late static binding');
+        $this->assertSame($testParsedown, $sameInstanceAgain);
+    }
+}

+ 5 - 0
vendor/erusev/parsedown/test/TestParsedown.php

@@ -0,0 +1,5 @@
+<?php
+
+class TestParsedown extends Parsedown
+{
+}

+ 3 - 0
vendor/erusev/parsedown/test/bootstrap.php

@@ -0,0 +1,3 @@
+<?php
+
+include 'Parsedown.php';

+ 18 - 0
vendor/erusev/parsedown/test/data/aesthetic_table.html

@@ -0,0 +1,18 @@
+<table>
+<thead>
+<tr>
+<th>header 1</th>
+<th>header 2</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>cell 1.1</td>
+<td>cell 1.2</td>
+</tr>
+<tr>
+<td>cell 2.1</td>
+<td>cell 2.2</td>
+</tr>
+</tbody>
+</table>

+ 4 - 0
vendor/erusev/parsedown/test/data/aesthetic_table.md

@@ -0,0 +1,4 @@
+| header 1 | header 2 |
+| -------- | -------- |
+| cell 1.1 | cell 1.2 |
+| cell 2.1 | cell 2.2 |

+ 21 - 0
vendor/erusev/parsedown/test/data/aligned_table.html

@@ -0,0 +1,21 @@
+<table>
+<thead>
+<tr>
+<th style="text-align: left;">header 1</th>
+<th style="text-align: center;">header 2</th>
+<th style="text-align: right;">header 2</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td style="text-align: left;">cell 1.1</td>
+<td style="text-align: center;">cell 1.2</td>
+<td style="text-align: right;">cell 1.3</td>
+</tr>
+<tr>
+<td style="text-align: left;">cell 2.1</td>
+<td style="text-align: center;">cell 2.2</td>
+<td style="text-align: right;">cell 2.3</td>
+</tr>
+</tbody>
+</table>

+ 4 - 0
vendor/erusev/parsedown/test/data/aligned_table.md

@@ -0,0 +1,4 @@
+| header 1 | header 2 | header 2 |
+| :------- | :------: | -------: |
+| cell 1.1 | cell 1.2 | cell 1.3 |
+| cell 2.1 | cell 2.2 | cell 2.3 |

+ 9 - 0
vendor/erusev/parsedown/test/data/atx_heading.html

@@ -0,0 +1,9 @@
+<h1>h1</h1>
+<h2>h2</h2>
+<h3>h3</h3>
+<h4>h4</h4>
+<h5>h5</h5>
+<h6>h6</h6>
+<p>####### not a heading</p>
+<h1>closed h1</h1>
+<p>#</p>

+ 17 - 0
vendor/erusev/parsedown/test/data/atx_heading.md

@@ -0,0 +1,17 @@
+# h1
+
+## h2
+
+### h3
+
+#### h4
+
+##### h5
+
+###### h6
+
+####### not a heading
+
+# closed h1 #
+
+#

+ 1 - 0
vendor/erusev/parsedown/test/data/automatic_link.html

@@ -0,0 +1 @@
+<p><a href="http://example.com">http://example.com</a></p>

+ 1 - 0
vendor/erusev/parsedown/test/data/automatic_link.md

@@ -0,0 +1 @@
+<http://example.com>

+ 12 - 0
vendor/erusev/parsedown/test/data/block-level_html.html

@@ -0,0 +1,12 @@
+<div>_content_</div>
+<p>paragraph</p>
+<div>
+  <div class="inner">
+    _content_
+  </div>
+</div>
+<style type="text/css">
+  p {color: #789;}
+</style>
+<div>
+  <a href="/">home</a></div>

+ 16 - 0
vendor/erusev/parsedown/test/data/block-level_html.md

@@ -0,0 +1,16 @@
+<div>_content_</div>
+
+paragraph
+
+<div>
+  <div class="inner">
+    _content_
+  </div>
+</div>
+
+<style type="text/css">
+  p {color: #789;}
+</style>
+
+<div>
+  <a href="/">home</a></div>

+ 8 - 0
vendor/erusev/parsedown/test/data/code_block.html

@@ -0,0 +1,8 @@
+<pre><code>&lt;?php
+
+$message = 'Hello World!';
+echo $message;</code></pre>
+<hr />
+<pre><code>&gt; not a quote
+- not a list item
+[not a reference]: http://foo.com</code></pre>

Некоторые файлы не были показаны из-за большого количества измененных файлов