From 2d38a78581206b27f04008f9c6751a67c476cee5 Mon Sep 17 00:00:00 2001
From: usheweb <814994791@qq.com>
Date: Wed, 15 Oct 2014 00:34:31 +0800
Subject: [PATCH] init
---
appliction/Common/Config/etc.php | 21 ++
appliction/Index/Config/etc.php | 4 +
.../Index/Controller/IndexController.php | 87 +++++
data/cache/test_arr.php | 2 +
index.php | 14 +
leguan.sql | 45 +++
library/Leguan/Bootstrap/Leguan.php | 78 ++++
library/Leguan/Bootstrap/Path.php | 111 ++++++
library/Leguan/Bootstrap/Start.php | 89 +++++
library/Leguan/Cache/Adapter/File.php | 60 ++++
library/Leguan/Cache/Cache.php | 59 ++++
library/Leguan/Cache/ICache.php | 19 +
library/Leguan/Config/Config.php | 103 ++++++
library/Leguan/Config/etc.php | 53 +++
library/Leguan/Controller/Controller.php | 17 +
library/Leguan/Cookie/Cookie.php | 71 ++++
library/Leguan/Db/Db.php | 102 ++++++
library/Leguan/Db/Dsn.php | 63 ++++
library/Leguan/Debug/Debug.php | 70 ++++
library/Leguan/Helper/Helper.php | 60 ++++
library/Leguan/LeguanLoder/LeguanLoder.php | 23 ++
library/Leguan/Request/Request.php | 154 ++++++++
library/Leguan/Routing/Routing.php | 146 ++++++++
library/Leguan/Routing/etc.php | 13 +
library/Leguan/Session/Session.php | 141 ++++++++
library/Leguan/Sql/Adapter/Mysql.php | 290 +++++++++++++++
library/Leguan/Sql/Sql.php | 35 ++
library/Leguan/Url/Url.php | 317 +++++++++++++++++
library/Leguan/View/View.php | 334 ++++++++++++++++++
library/Usheweb/Chapter/Chapter.php | 172 +++++++++
library/Usheweb/Chapter/font/elephant.ttf | Bin 0 -> 44820 bytes
library/Usheweb/Upload/Mime.php | 75 ++++
library/Usheweb/Upload/Upload.php | 169 +++++++++
themes/Default/Cache/Index/Index/Index.php | 33 ++
themes/Default/Cache/Index/Index/Upload.php | 19 +
themes/Default/Index/Index/Index.php | 36 ++
themes/Default/Index/Index/Parent.php | 13 +
themes/Default/Index/Index/Test.php | 1 +
themes/Default/Index/Index/Top.php | 4 +
themes/Default/Index/Index/upload.php | 19 +
40 files changed, 3122 insertions(+)
create mode 100644 appliction/Common/Config/etc.php
create mode 100644 appliction/Index/Config/etc.php
create mode 100644 appliction/Index/Controller/IndexController.php
create mode 100644 data/cache/test_arr.php
create mode 100644 index.php
create mode 100644 leguan.sql
create mode 100644 library/Leguan/Bootstrap/Leguan.php
create mode 100644 library/Leguan/Bootstrap/Path.php
create mode 100644 library/Leguan/Bootstrap/Start.php
create mode 100644 library/Leguan/Cache/Adapter/File.php
create mode 100644 library/Leguan/Cache/Cache.php
create mode 100644 library/Leguan/Cache/ICache.php
create mode 100644 library/Leguan/Config/Config.php
create mode 100644 library/Leguan/Config/etc.php
create mode 100644 library/Leguan/Controller/Controller.php
create mode 100644 library/Leguan/Cookie/Cookie.php
create mode 100644 library/Leguan/Db/Db.php
create mode 100644 library/Leguan/Db/Dsn.php
create mode 100644 library/Leguan/Debug/Debug.php
create mode 100644 library/Leguan/Helper/Helper.php
create mode 100644 library/Leguan/LeguanLoder/LeguanLoder.php
create mode 100644 library/Leguan/Request/Request.php
create mode 100644 library/Leguan/Routing/Routing.php
create mode 100644 library/Leguan/Routing/etc.php
create mode 100644 library/Leguan/Session/Session.php
create mode 100644 library/Leguan/Sql/Adapter/Mysql.php
create mode 100644 library/Leguan/Sql/Sql.php
create mode 100644 library/Leguan/Url/Url.php
create mode 100644 library/Leguan/View/View.php
create mode 100644 library/Usheweb/Chapter/Chapter.php
create mode 100644 library/Usheweb/Chapter/font/elephant.ttf
create mode 100644 library/Usheweb/Upload/Mime.php
create mode 100644 library/Usheweb/Upload/Upload.php
create mode 100644 themes/Default/Cache/Index/Index/Index.php
create mode 100644 themes/Default/Cache/Index/Index/Upload.php
create mode 100644 themes/Default/Index/Index/Index.php
create mode 100644 themes/Default/Index/Index/Parent.php
create mode 100644 themes/Default/Index/Index/Test.php
create mode 100644 themes/Default/Index/Index/Top.php
create mode 100644 themes/Default/Index/Index/upload.php
diff --git a/appliction/Common/Config/etc.php b/appliction/Common/Config/etc.php
new file mode 100644
index 0000000..be88d4d
--- /dev/null
+++ b/appliction/Common/Config/etc.php
@@ -0,0 +1,21 @@
+ '',
+ 'dbEngine' => 'mysql',
+ 'dbName' => 'leguan',
+ 'dbHost' => '127.0.0.1',
+ 'dbPort' => '',
+ 'dbUser'=>'root',
+ 'dbPwd' =>'',
+ 'dbPrefix' => 'lg_'
+ );
\ No newline at end of file
diff --git a/appliction/Index/Config/etc.php b/appliction/Index/Config/etc.php
new file mode 100644
index 0000000..16bd58d
--- /dev/null
+++ b/appliction/Index/Config/etc.php
@@ -0,0 +1,4 @@
+ 'test');
\ No newline at end of file
diff --git a/appliction/Index/Controller/IndexController.php b/appliction/Index/Controller/IndexController.php
new file mode 100644
index 0000000..ebda117
--- /dev/null
+++ b/appliction/Index/Controller/IndexController.php
@@ -0,0 +1,87 @@
+ array('>',5,'or'),'id'=>array('in',array(1,3,5)));
+ $article = $this->Db->table($table)->where($condition)->field('id,title')->select();
+
+ $view = $this->view;
+ $view->assign('author', 'ushe');
+ $view->assign('script', '');
+ $view->assign('article', $article);
+ $view->assign('age',20);
+ $view->list = array('apple','pear','orange');
+ $view->display();
+ echo "
";
+ echo $this->Debug->execTime();
+ }
+
+ public function dbAction()
+ {
+ $values = array("title"=>"new 'title",'description' => 'test');
+ $table = 'article';
+ //$this->Debug->dump($this->Db->query('insert into `lg_article` set title = ?,description = ?;'));
+ //echo $this->Db->table($table)->values($values)->add();
+
+ $this->Debug->dump(
+ $this->Sql->table($table)->where(
+ array('click' => array('>',5,'or'),'id'=>array('in',array(1,3,5))))->field('id,title')->select()
+ );
+ }
+
+ public function chapterAction()
+ {
+ $chapter = new Chapter();
+ $chapter->show();
+ }
+
+ public function cacheAction()
+ {
+ $arr = array('a',123);
+ $this->cache->write('test_arr', $arr);
+ $this->debug->dump($this->cache->read('test_arr'));
+ }
+
+ public function readcacheAction()
+ {
+ $arr = $this->cache->read('test_arr');
+ $this->debug->dump($arr);
+ }
+
+ public function defaultAction()
+ {
+ echo 'defaultAction';
+ }
+
+ public function uploadAction()
+ {
+ $this->view->assign('upload', new \Usheweb\Upload\Upload());
+ $this->view->display();
+ }
+
+ public function doUploadAction()
+ {
+ if(!$this->request->isPost()){
+ return;
+ }
+
+ $upload = new \Usheweb\Upload\Upload();
+ $this->debug->dump($upload->run());
+ }
+}
\ No newline at end of file
diff --git a/data/cache/test_arr.php b/data/cache/test_arr.php
new file mode 100644
index 0000000..a13360a
--- /dev/null
+++ b/data/cache/test_arr.php
@@ -0,0 +1,2 @@
+_init();
+ }
+
+ /**
+ * 初始化路径信息
+ */
+ private function _init()
+ {
+ $this->_path['root'] = realpath('');
+ $this->_path['ds'] = DIRECTORY_SEPARATOR;
+ $this->_path['ps'] = PATH_SEPARATOR;
+ $this->_path['lib'] = $this->_path['root'] . $this->_path['ds'] . 'library';
+ $this->_path['app'] = $this->_path['root'] . $this->_path['ds'] . APP_NAME;
+ $this->_path['data'] = $this->_path['root'] . $this->_path['ds'] . 'data';
+ $this->_path['view'] = $this->_path['root'] . $this->_path['ds'] . 'themes';
+ $this->_path['upload'] = $this->_path['root'] . $this->_path['ds'] . 'uploads';
+
+ $this->_path['cache'] = $this->_path['data'] . $this->_path['ds'] . 'cache';
+ $this->_path['log'] = $this->_path['data'] . $this->_path['ds'] . 'log';
+
+ $this->_path['html'] = $this->_path['cache'] . $this->_path['ds'] . 'html';
+ $this->_path['data'] = $this->_path['cache'] . $this->_path['ds'] . 'data';
+
+ $this->_path['appCommon'] = $this->_path['app'] . $this->_path['ds'] . 'Common';
+ $this->_path['appConfig'] = $this->_path['appCommon'] . $this->_path['ds'] . 'Config';
+ }
+
+ public function __get($name)
+ {
+ if (isset($this->_path[$name])) {
+ return $this->_path[$name];
+ }
+
+ return null;
+ }
+
+ public function __set($name, $value)
+ {
+ $this->add($name, $value);
+ }
+
+ /**
+ * 添加路径信息
+ *
+ * @exception $name路径信息存在
+ * @param $name string
+ * @param $value string
+ * @return void
+ */
+ public function add($name, $value)
+ {
+ if (isset($this->_path[$name])) {
+ throw new \Exception("$name".'已在Path::$_path中', 1);
+ }
+
+ $this->_path[$name] = $value;
+ }
+
+ /**
+ * 删除路径信息
+ *
+ * @exception $name路径信息不存在
+ * @param $name
+ * @return string
+ */
+ public function del($name)
+ {
+ if(!isset($this->_path[$name])){
+ throw new \Exception("$name".'不在Path::$_path中', 1);
+ }
+
+ unset($this->_path[$name]);
+ }
+
+ /**
+ * 清除路径信息
+ */
+ public function clear()
+ {
+ $this->_path = array();
+ }
+
+ /**
+ * 获取路径中文件扩展名
+ */
+ public function getExtension($path)
+ {
+ return pathinfo($path, PATHINFO_EXTENSION);
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Bootstrap/Start.php b/library/Leguan/Bootstrap/Start.php
new file mode 100644
index 0000000..02ad186
--- /dev/null
+++ b/library/Leguan/Bootstrap/Start.php
@@ -0,0 +1,89 @@
+ 5.3.0 !');
+ }
+
+ //加载引导文件
+ $coreFiles = array('Path','Leguan');
+ foreach ($coreFiles as $value) {
+ require "{$value}.php";
+ }
+ $path = new Path();
+ Leguan::set('path',$path);
+
+ //设置include的路径
+ $new_include_path = array('.', $path->lib, $path->app);
+ $new_include_path = implode($path->ps, $new_include_path);
+ set_include_path($new_include_path);
+
+ //注册 类加载器
+ spl_autoload_register('self::autoLoader');
+
+ $config = Leguan::get('config');
+ defined('APP_NAME') && $config->app = APP_NAME;
+ defined('IS_DEBUG') && $config->isDebug = IS_DEBUG;
+
+ //加载应用公共配置
+ $appConfig = $path->appConfig . $path->ds . 'etc.php';
+ if(file_exists($appConfig)){
+ $config->load(require $appConfig);
+ }
+
+ $config->isDebug ? error_reporting(E_ALL) : error_reporting(0);
+ date_default_timezone_set($config->timezone);
+ header("Content-Type:text/html;charset={$config->charset}");
+
+ Leguan::get('url')->setCleanKey($config->urlCleanKey);
+ }
+
+ /**
+ * 框架入口
+ */
+ public static function run()
+ {
+ self::_init();
+ Leguan::get('routing')->run();
+ }
+
+ /**
+ * 类自动加载器
+ */
+ public static function autoLoader($className)
+ {
+ $path = leguan::get('path');
+ $className = ltrim($className, '\\');
+ $className = str_replace('\\', $path->ds, $className);
+
+ require "{$className}.php";
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Cache/Adapter/File.php b/library/Leguan/Cache/Adapter/File.php
new file mode 100644
index 0000000..8cf0606
--- /dev/null
+++ b/library/Leguan/Cache/Adapter/File.php
@@ -0,0 +1,60 @@
+cache . $path->ds . "{$name}.php";
+
+ if(file_exists($fileName)){
+ $content = require $fileName;
+ //http://www.cnblogs.com/A-Song/archive/2011/12/13/2285619.html
+ if(get_magic_quotes_gpc()){
+ $content = stripslashes($content);
+ }
+ return unserialize($content);
+ }
+
+ return null;
+ }
+
+ /**
+ * 写入緩存內容
+ *
+ * @param $name
+ * @param $value
+ * @return void
+ */
+ public function write($name, $value)
+ {
+ $path = Leguan::get('path');
+ $fileName = $path->cache . $path->ds . "{$name}.php";
+
+ $data = "cacheType;
+ $cacheType = ucwords($cacheType);
+
+ $class = "\\Leguan\\Cache\\Adapter\\{$cacheType}";
+ $this->_obj = new $class();
+ }
+
+ /**
+ * 讀取緩存內容
+ *
+ * @param $name
+ * @return array
+ */
+ public function read($name)
+ {
+ if(!isset($this->_data[$name])){
+ $this->_data[$name] = $this->_obj->read($name);
+ }
+
+ return $this->_data[$name];
+ }
+
+ /**
+ * 写入緩存內容
+ *
+ * @param $name
+ * @param $value
+ * @return void
+ */
+ public function write($name, $value)
+ {
+ $this->_data[$name] = $value;
+ $this->_obj->write($name, $value);
+ }
+ }
\ No newline at end of file
diff --git a/library/Leguan/Cache/ICache.php b/library/Leguan/Cache/ICache.php
new file mode 100644
index 0000000..3e662d8
--- /dev/null
+++ b/library/Leguan/Cache/ICache.php
@@ -0,0 +1,19 @@
+_init();
+ }
+
+ /**
+ * 配置信息初始化
+ */
+ private function _init()
+ {
+ $this->_config = require 'etc.php';
+ }
+
+ public function __get($name)
+ {
+ return $this->get($name);
+ }
+
+ public function __set($name, $value)
+ {
+ $this->set($name, $value);
+ }
+
+ /**
+ * 加载一组配置
+ *
+ * @param array $config 新的配置数组
+ * @return void
+ */
+ public function load($config)
+ {
+ $this->_config = array_merge($this->_config,$config);
+ }
+
+ /**
+ * 获取系统配置
+ *
+ * @param string $name 配置的name
+ * @return mixed
+ */
+ public function get($name)
+ {
+ if(!isset($this->_config[$name])){
+ return null;
+ }
+
+ return $this->_config[$name];
+ }
+
+ /**
+ * 设置系统配置
+ *
+ * @param string $name 配置的name
+ * @param mixed $value 配置的值
+ * @return void
+ */
+ public function set($name,$value)
+ {
+ $this->_config[$name] = $value;
+ }
+
+ /**
+ * 删除一个配置
+ *
+ * @param $name string
+ * @return void
+ */
+ public function del($name)
+ {
+ if(!isset($this->_config[$name])){
+ return null;
+ }
+
+ unset($this->_config[$name]);
+ }
+
+ /**
+ * 清除配置
+ */
+ public function clear()
+ {
+ $this->_config = array();
+ }
+ }
\ No newline at end of file
diff --git a/library/Leguan/Config/etc.php b/library/Leguan/Config/etc.php
new file mode 100644
index 0000000..d8facd5
--- /dev/null
+++ b/library/Leguan/Config/etc.php
@@ -0,0 +1,53 @@
+ 'Asia/Shanghai',
+ //默认字符集
+ 'charset' => 'utf-8',
+ //开发者模式
+ 'isDebug' => false,
+ //路由类型 0 普通、1 patInfo、2 url重写、3 clean
+ 'urlType' => 1,
+ //url clean模式下的key
+ 'urlCleanKey' => 'l',
+ //表、字段转义 - mysql
+ 'dbEscapeMysql' => array('`', '`'),
+ //表、字段转义 - mssql
+ 'dbEscapeMssql' => array('[', ']'),
+ //表、字段转义 - sqllite
+ 'dbEscapeSqllite' => array('"', '"'),
+ //是否开启session
+ 'sessionStart' => true,
+ //默认模块
+ 'defaultModule' => 'Index',
+ //默认控制器
+ 'defaultController' => 'Index',
+ //默认方法
+ 'defaultAction' => 'Index',
+ //默认模板主题
+ 'theme' => 'Default',
+ //模板扩展名
+ 'viewExtension' => '.php',
+ //模板分割符
+ 'viewLimiter' => array(''),
+ //模板输出转义函数
+ 'viewEscape' => 'htmlspecialchars',
+ //url扩展
+ 'urlExtension' => '.html',
+ //url分割符
+ 'urlLimiter' => '/',
+ //缓存类型
+ 'cacheType' => 'file',
+ //上传文件扩展名
+ 'fileExtension' => array('txt', 'html', 'htm', 'jpg', 'png', 'gif', 'bmp', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar'),
+ //上传文件最大尺寸 1024 * 1024 * 10 = 10M
+ 'fileMaxSize' => 1024 * 1024 * 10
+ );
\ No newline at end of file
diff --git a/library/Leguan/Controller/Controller.php b/library/Leguan/Controller/Controller.php
new file mode 100644
index 0000000..df18fc4
--- /dev/null
+++ b/library/Leguan/Controller/Controller.php
@@ -0,0 +1,17 @@
+get($name);
+ }
+
+ public function __set($name, $value)
+ {
+ $this->set($name, $value);
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Db/Db.php b/library/Leguan/Db/Db.php
new file mode 100644
index 0000000..eff401a
--- /dev/null
+++ b/library/Leguan/Db/Db.php
@@ -0,0 +1,102 @@
+_init();
+ }
+
+ /**
+ * 初始化数据库连接信息
+ */
+ protected function _init()
+ {
+ $config = Leguan::get('config');
+
+ if(empty(self::$_db)){
+
+ self::$_dbCharset = $config->charset != null ?
+ $config->charset : self::$_dbCharset;
+ self::$_dbCharset = str_replace('-', '', self::$_dbCharset);
+ self::$_dbPrefix = $config->dbPrefix;
+
+ if(empty($config->dbDsn)){
+ $dsn = new Dsn($config->dbEngine,
+ $config->dbHost,
+ $config->dbName,
+ $config->dbPort);
+ $config->dbDsn = $dsn->getDsn();
+ }
+
+ try {
+ self::$_db = new \PDO($config->dbDsn, $config->dbUser, $config->dbPwd);
+ //禁用prepared statements的仿真效果
+ self::$_db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
+ self::$_db->exec("set names '".self::$_dbCharset."'");
+ } catch (PDOException $e) {
+ echo 'Connection failed: ' . $e->getMessage();
+ }
+ }
+ }
+
+ /**
+ * 执行一条sql查询语句
+ *
+ * @param $statement string 带预处理的sql语句
+ * @param $input array 预处理数据
+ * @return mixed
+ */
+ public function query($statement,$input = array())
+ {
+ $statement = str_replace("@_", self::$_dbPrefix, $statement);
+ $this->_stmt = self::$_db->prepare($statement);
+ $result = $this->_stmt->execute($input);
+
+ if($result === false){
+ return false;
+ }
+
+ return $this->_fetchAll();
+ }
+
+ /**
+ * 获取最后插入记录的自增长id
+ */
+ public function getLastInsertId()
+ {
+ return self::$_db->lastInsertId();
+ }
+
+ /**
+ * 获取结果集
+ *
+ * @param $style
+ */
+ private function _fetchAll($style = \PDO::FETCH_ASSOC)
+ {
+ return $this->_stmt->fetchAll($style);
+ }
+
+}
\ No newline at end of file
diff --git a/library/Leguan/Db/Dsn.php b/library/Leguan/Db/Dsn.php
new file mode 100644
index 0000000..ff7d97e
--- /dev/null
+++ b/library/Leguan/Db/Dsn.php
@@ -0,0 +1,63 @@
+_dbEngine = $engine;
+ $this->_dbPort = $port;
+ $this->_dbName = $dbName;
+ $this->_host = $host;
+ }
+
+ /**
+ * 获取当前数据库引擎对应的dsn
+ *
+ * @return string
+ */
+ public function getDsn()
+ {
+ $engine = $this->_dbEngine;
+
+ if (empty($this->_dbPort)) {
+ return $this->$engine();
+ } else {
+ return $this->$engine($this->_dbPort);
+ }
+ }
+
+ public function mysql($port = 3306)
+ {
+ return $this->_common($port);
+ }
+
+ public function cubrid($port = 33000)
+ {
+ return $this->_common($port);
+ }
+
+ /**
+ * 通用dsn构造器
+ */
+ private function _common($port)
+ {
+ return "{$this->_dbEngine}:dbname={$this->_dbName};host={$this->_host};port={$port}";
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Debug/Debug.php b/library/Leguan/Debug/Debug.php
new file mode 100644
index 0000000..6ff289e
--- /dev/null
+++ b/library/Leguan/Debug/Debug.php
@@ -0,0 +1,70 @@
+";
+ var_dump($expression);
+ echo "";
+ }
+
+ /**
+ * 字符串输出到 textarea 中
+ */
+ public function dumpText($string, $col = 150, $row = 50)
+ {
+ echo "";
+ }
+
+ /**
+ * 开始记录代码执行时间
+ *
+ * @param $name string
+ * @return void
+ */
+ public function start($name)
+ {
+ $this->_time[$name] = microtime(true);
+ }
+
+ /**
+ * 获取代码执行时间
+ *
+ * @param $name string
+ * @return float
+ */
+ public function stop($name)
+ {
+ $this->_time[$name] = microtime(true) - $this->_time[$name];
+
+ return $this->_time[$name];
+ }
+
+ /**
+ * 获取app执行时间
+ *
+ * @return float
+ */
+ public function execTime()
+ {
+ return microtime(true) - APP_START_TIME;
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Helper/Helper.php b/library/Leguan/Helper/Helper.php
new file mode 100644
index 0000000..11cdeea
--- /dev/null
+++ b/library/Leguan/Helper/Helper.php
@@ -0,0 +1,60 @@
+_data['HTTP_X_REQUESTED_WITH'])
+ && strtolower($this->_data['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ? true : false;
+ }
+
+ /**
+ * 是否为手机客户端
+ */
+ public function isMobile()
+ {
+ //判断手机发送的客户端标志
+ if(isset($this->_data['HTTP_USER_AGENT'])) {
+ $userAgent = strtolower($this->_data['HTTP_USER_AGENT']);
+ $clientkeywords = array(
+ 'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-'
+ ,'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu',
+ 'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini',
+ 'operamobi', 'opera mobi', 'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile'
+ );
+ // 从HTTP_USER_AGENT中查找手机浏览器的关键字
+ if(preg_match("/(".implode('|',$clientkeywords).")/i",$userAgent)
+ && strpos($userAgent,'ipad') === false){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 获取客户端IP地址
+ *
+ * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
+ * @param boolean $adv 是否进行高级模式获取(有可能被伪装)
+ * @return mixed
+ */
+ public function getClientIp($type = 0,$adv=false)
+ {
+ $type = $type ? 1 : 0;
+ static $ip = NULL;
+ if ($ip !== NULL) return $ip[$type];
+ if($adv){
+ if (isset($this->_data['HTTP_X_FORWARDED_FOR'])) {
+ $arr = explode(',', $this->_data['HTTP_X_FORWARDED_FOR']);
+ $pos = array_search('unknown',$arr);
+ if(false !== $pos) unset($arr[$pos]);
+ $ip = trim($arr[0]);
+ }elseif (isset($this->_data['HTTP_CLIENT_IP'])) {
+ $ip = $this->_data['HTTP_CLIENT_IP'];
+ }elseif (isset($this->_data['REMOTE_ADDR'])) {
+ $ip = $this->_data['REMOTE_ADDR'];
+ }
+ }elseif (isset($this->_data['REMOTE_ADDR'])) {
+ $ip = $this->_data['REMOTE_ADDR'];
+ }
+ // IP地址合法验证
+ $long = sprintf("%u",ip2long($ip));
+ $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
+ return $ip[$type];
+ }
+
+ /**
+ * 获取当前域名
+ */
+ public function getDomain($hasBaseUrl = true)
+ {
+ $httpType = $this->getHttpType();
+ $domain = "{$httpType}{$_SERVER['SERVER_NAME']}";
+
+ if ($_SERVER["SERVER_PORT"] != 80) {
+ $domain = "{$domain}:{$_SERVER["SERVER_PORT"]}";
+ }
+
+ if ($hasBaseUrl) {
+ $baseUrl = dirname($_SERVER['SCRIPT_NAME']);
+ $baseUrl = str_replace('\\','/', $baseUrl);
+ $baseUrl = ltrim($baseUrl, '/');
+ $domain = "{$domain}/{$baseUrl}";
+ }
+
+ return $domain;
+ }
+
+ /**
+ * 获取http类型
+ */
+ public function getHttpType()
+ {
+ return $this->isSsl() ? "https://" : "http://";
+ }
+
+ /**
+ * 判断是否SSL协议
+ * @return boolean
+ */
+ function isSsl()
+ {
+ if (isset($_SERVER['HTTPS']) &&
+ ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
+ return true;
+ } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) {
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Routing/Routing.php b/library/Leguan/Routing/Routing.php
new file mode 100644
index 0000000..74d58e6
--- /dev/null
+++ b/library/Leguan/Routing/Routing.php
@@ -0,0 +1,146 @@
+_init();
+ }
+
+ /**
+ * 初始化路由配置
+ */
+ private function _init()
+ {
+ $this->_routing = require 'etc.php';
+ }
+
+ public function run()
+ {
+ $config = Leguan::get('config');
+ $urlType = $config->urlType;
+ $url = Leguan::get('url');
+ $urlType = $url->getUrlType($urlType);
+
+ if($urlType === null){
+ throw new \Exception('配置中的urlType不在Url::urlType中', 1);
+ }
+
+ //重写路由
+ if($urlType != 'normal'){
+ $this->$urlType();
+ }
+ //解析url
+ $url->$urlType();
+
+ $path = Leguan::get('path');
+ //加载模块配置
+ $moduleConfig = array($path->appPath, $url->m, 'Config', 'etc.php');
+ $moduleConfig = implode($path->ds, $moduleConfig);
+ if(file_exists($moduleConfig)){
+ $config->load(require $moduleConfig);
+ }
+
+ //开启session
+ if($config->sessionStart){
+ $session = new \Leguan\Session\Session();
+ Leguan::set('session',$session);
+ $session->start();
+ }
+
+ //加载控制器
+ $controllerName = "\\{$url->m}\\Controller\\{$url->c}Controller";
+
+ $controller = new $controllerName();
+ $actionName = "{$url->a}Action";
+
+ $defaultAction = 'defaultAction';
+ if (is_callable(array($controller, $actionName))) {
+ $controller->$actionName();
+ } elseif (is_callable(array($controller, $defaultAction))) {
+ $controller->$defaultAction();
+ } else {
+ $this->defaultAction($controllerName, $actionName);
+ }
+
+ }
+
+ /**
+ * 未知路由处理函数
+ */
+ public function defaultAction($controllerName, $actionName){
+ exit("类{$controllerName} {$actionName}方法不存在或不是public");
+ }
+
+ /**
+ * 重写路由 - pathInfo
+ */
+ public function pathInfo()
+ {
+ if(!isset($_SERVER['PATH_INFO'])){
+ $_SERVER['PATH_INFO'] = '';
+ }
+
+ $_SERVER['PATH_INFO'] = $this->_getUrl($_SERVER['PATH_INFO']);
+ }
+
+ /**
+ * 重写路由 - rewrite
+ */
+ public function rewrite()
+ {
+ $this->clean();
+ }
+
+ /**
+ * 重写路由 - clean
+ */
+ public function clean()
+ {
+ $cleanKey = Leguan::get('url')->getCleanKey();
+
+ if(isset($_GET[$cleanKey])){
+ $_GET[$cleanKey] = $this->_getUrl($_GET[$cleanKey]);
+ }
+ }
+
+ /**
+ * 获取重写后的url
+ *
+ * @param $url string
+ * @return string
+ */
+ private function _getUrl($url = '')
+ {
+ if(empty($url)){
+ return '';
+ }
+
+ foreach ($this->_routing as $value) {
+ $from = preg_replace("/(\\$\d)/", '([a-zA-Z_0-9\/])', $value['from']);
+ if(preg_match("|{$from}|i", $url)){
+ return preg_replace("|{$from}|i", "{$value['to']}", $url);
+ }
+ }
+
+ return $url;
+ }
+
+}
\ No newline at end of file
diff --git a/library/Leguan/Routing/etc.php b/library/Leguan/Routing/etc.php
new file mode 100644
index 0000000..356116e
--- /dev/null
+++ b/library/Leguan/Routing/etc.php
@@ -0,0 +1,13 @@
+'test/$1','to'=>'Index/Index/Index/$1'),
+ array('from'=>'demo/$1','to'=>'Index/Index/Index/$1')
+ );
\ No newline at end of file
diff --git a/library/Leguan/Session/Session.php b/library/Leguan/Session/Session.php
new file mode 100644
index 0000000..1675bca
--- /dev/null
+++ b/library/Leguan/Session/Session.php
@@ -0,0 +1,141 @@
+get($name);
+ }
+
+ public function __set($name, $value)
+ {
+ $this->set($name, $value);
+ }
+ }
\ No newline at end of file
diff --git a/library/Leguan/Sql/Adapter/Mysql.php b/library/Leguan/Sql/Adapter/Mysql.php
new file mode 100644
index 0000000..2adeb83
--- /dev/null
+++ b/library/Leguan/Sql/Adapter/Mysql.php
@@ -0,0 +1,290 @@
+dbEngine);
+ $escape = "dbEscape{$dbEngine}";
+
+ if($config->$escape !== null){
+ //设置表、字段转义字符
+ $this->_escape = $config->$escape;
+ }
+
+ $this->_db = Leguan::get('db');
+ }
+
+ protected function _init()
+ {
+ $this->_where = array();
+ $this->_field = array();
+ $this->_values = array();
+ $this->_input = array();
+ $this->_table = '';
+ }
+
+ /**
+ * 加添where条件数组
+ *
+ * @param $condition array
+ * @return void
+ */
+ public function where($condition)
+ {
+ $this->_where = array_merge($this->_where, $condition);
+
+ return $this;
+ }
+
+ /**
+ * 添加查询的字段信息
+ *
+ * @param $fields
+ * @return void
+ */
+ public function field($fields)
+ {
+ $this->_field = $fields;
+
+ return $this;
+ }
+
+ /**
+ * 添加新增的数据
+ *
+ * @param $values
+ * @return void
+ */
+ public function values($values)
+ {
+ $this->_values = array_merge($this->_values, $values);
+
+ return $this;
+ }
+
+ /**
+ * 设置操作的表名
+ *
+ * @param $table
+ * @return void
+ */
+ public function table($table)
+ {
+ $this->_table = $table;
+
+ return $this;
+ }
+
+ /**
+ * 获取添加数据的sql
+ */
+ public function add($isQuery = true)
+ {
+ $sql = "insert into ". $this->_save() . ";";
+
+ if ($isQuery) {
+ return $this->_db->query($sql, $this->_input);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 限制操作数
+ */
+ public function limit($limit)
+ {
+ $this->_limit = $limit;
+ }
+
+ /**
+ * 获取新增和修改 公共部分sql
+ */
+ private function _save()
+ {
+ if(empty($this->_values)){
+ return '';
+ }
+
+ $values = '';
+ foreach ($this->_values as $key => $value) {
+ array_push($this->_input, $value);
+ $values .= "{$this->_escape[0]}". $this->filter($key) ."{$this->_escape[1]} = ?,";
+ }
+ $values = rtrim($values,',');
+
+ return "{$this->_escape[0]}@_{$this->_table}{$this->_escape[1]} set {$values}";
+ }
+
+ /**
+ * 获取删除数据的sql
+ */
+ public function del($isQuery = true)
+ {
+ //防止意外删除全部数据
+ if(empty($this->_where)){
+ return '';
+ }
+
+ return $this->delAll($isQuery);
+ }
+
+ /**
+ * 删除全部数据
+ */
+ public function delAll($isQuery = true)
+ {
+ $sql = "delete @_{$this->_table} where ".$this->_where().";";
+
+ if ($isQuery) {
+ return $this->_db->query($sql, $this->_input);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 获取修改数据的sql
+ */
+ public function update($isQuery = true)
+ {
+ //防止意外修改全部数据
+ if(empty($this->_where)){
+ return '';
+ }
+
+ return $this->updateAll($isQuery);
+ }
+
+ /**
+ * 修改全部数据
+ */
+ public function updateAll($isQuery = true)
+ {
+ $sql = "update " . $this->_save() . " where " . $this->_where() .";";
+
+ if ($isQuery) {
+ return $this->_db->query($sql, $this->_input);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 获取查询数据的sql
+ */
+ public function select($isQuery = true)
+ {
+ $fields = '';
+ if (empty($this->_field)) {
+ $fields = '*';
+ } elseif (is_array($this->_field)) {
+ foreach ($this->_field as $value) {
+ $fields .= "{$this->_escape[0]}{$value}{$this->_escape[1]},";
+ }
+
+ $fields = rtrim($fields, ',');
+ } else {
+ $fields = $this->_field;
+ }
+
+ $sql = "select {$fields} from @_{$this->_table} where ".$this->_where();
+ if (!empty($this->_limit)) {
+ $sql .= " limit {$this->_limit}";
+ }
+ $sql = "{$sql};";
+
+ if ($isQuery) {
+ return $this->_db->query($sql, $this->_input);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 获取where条件字符串
+ *
+ * @return string
+ */
+ private function _where()
+ {
+ if(empty($this->_where)){
+ return '1=1';
+ }
+
+ $where = '';
+ //array('age' => array('>','20','or')) == or age > 20
+ foreach ($this->_where as $key => $value) {
+ $condition = isset($value[2]) ? strtolower($value[2]) : 'and';
+ $operator = is_array($value) ? $value[0] : '=';
+ $placeholder = '?';
+
+ //in (?,?,?)
+ if ($operator == 'in') {
+ $placeholder = '(';
+ foreach ($value[1] as $in) {
+ $placeholder .= "?,";
+ array_push($this->_input, $in);
+ }
+ $placeholder = rtrim($placeholder,',');
+ $placeholder .= ')';
+ } else {
+ if (is_array($value)) {
+ array_push($this->_input, $value[1]);
+ } else {
+ array_push($this->_input, $value);
+ }
+ }
+
+ $where .= " {$condition} {$this->_escape[0]}". $this->filter($key) ."{$this->_escape[1]} {$operator} {$placeholder}";
+ }
+
+ $where = ltrim($where, ' and ');
+ $where = ltrim($where, ' or ');
+
+ return $where;
+ }
+
+ /**
+ * key过滤
+ */
+ public function filter($key)
+ {
+ if(preg_match("|^[0-9a-zA-Z_]*$|", $key)){
+ return $key;
+ }
+
+ return '';
+ }
+ }
\ No newline at end of file
diff --git a/library/Leguan/Sql/Sql.php b/library/Leguan/Sql/Sql.php
new file mode 100644
index 0000000..cf983a1
--- /dev/null
+++ b/library/Leguan/Sql/Sql.php
@@ -0,0 +1,35 @@
+dbEngine;
+ $dbEngine = ucwords($dbEngine);
+
+ $class = "\\Leguan\\Sql\\Adapter\\{$dbEngine}";
+ $this->_obj = new $class();
+ }
+
+ public function __call($name, $arguments)
+ {
+ return $this->_obj->$name(implode(',', $arguments));
+ }
+}
\ No newline at end of file
diff --git a/library/Leguan/Url/Url.php b/library/Leguan/Url/Url.php
new file mode 100644
index 0000000..6dc4ef7
--- /dev/null
+++ b/library/Leguan/Url/Url.php
@@ -0,0 +1,317 @@
+get($name);
+ }
+
+
+ public function __set($name, $value)
+ {
+ $this->set($name, $value);
+ }
+
+ /**
+ * 修改clean key
+ *
+ * @param $key string
+ * @return void
+ */
+ public function setCleanKey($key)
+ {
+ $this->_cleanKey = $key;
+ }
+
+ /**
+ * 获取url clean key
+ *
+ * @return string
+ */
+ public function getCleanKey()
+ {
+ return $this->_cleanKey;
+ }
+
+ /**
+ * 获取url
+ *
+ * @return array
+ */
+ public function getUrlArr()
+ {
+ return $this->_url;
+ }
+
+ /**
+ * 获取url类型
+ *
+ * @param $type int
+ * @return mixed
+ */
+ public function getUrlType($type)
+ {
+ if(isset($this->_urlType[$type])){
+ return $this->_urlType[$type];
+ }
+
+ return null;
+ }
+
+ /**
+ * 设置路径键值信息
+ *
+ * @param $name string
+ * @param $value string
+ * @return void
+ */
+ public function set($name, $value)
+ {
+ $this->_url[$name] = $value;
+ }
+
+ /**
+ * 获取路径中的键值信息
+ *
+ * @param $name string
+ * @return string
+ */
+ public function get($name)
+ {
+ if(isset($this->_url[$name])){
+ return $this->_url[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * url解析 - normal
+ */
+ public function normal()
+ {
+ $config = Leguan::get('config');
+ !isset($_GET['m']) && $_GET['m'] = $config->defaultModule;
+ !isset($_GET['c']) && $_GET['c'] = $config->defaultController;
+ !isset($_GET['a']) && $_GET['a'] = $config->defaultAction;
+
+ foreach ($_GET as $key => $value) {
+ $this->_url[$key] = $value;
+ }
+
+ $this->_ucwords();
+ }
+
+ /**
+ * url解析 - pathinfo
+ */
+ public function pathInfo()
+ {
+ if(!isset($_SERVER['PATH_INFO'])){
+ $_SERVER['PATH_INFO'] = '';
+ }
+
+ $this->parseUrl($_SERVER['PATH_INFO']);
+ }
+
+ /**
+ * url解析 - rewrite
+ */
+ public function rewrite()
+ {
+ $this->clean();
+ }
+
+ /**
+ * url解析 - clean
+ */
+ public function clean()
+ {
+ if(!isset($_GET[$this->_cleanKey])){
+ $_GET[$this->_cleanKey] = '';
+ }
+
+ $this->parseUrl($_GET[$this->_cleanKey]);
+ }
+
+ /**
+ * url解析
+ *
+ * @param $path string
+ */
+ public function parseUrl($path = '')
+ {
+ $pathArr = $this->_getPathArr($path);
+
+ $this->_url['m'] = $pathArr[0];
+ $this->_url['c'] = $pathArr[1];
+ $this->_url['a'] = $pathArr[2];
+ $this->_ucwords();
+ //去除$pathArr前3个成员
+ array_splice($pathArr,0,3);
+
+ $pathKeys = array();
+ $pathValues = array();
+ foreach ($pathArr as $key => $value) {
+ if($key % 2 == 0){
+ array_push($pathKeys, $value);
+ }else{
+ array_push($pathValues, $value);
+ }
+ }
+
+ if($pathKeys || $pathValues){
+ $pathCombine = array_combine($pathKeys, $pathValues);
+ //把url转换成数组保存
+ $this->_url = array_merge($this->_url,$pathCombine);
+ }
+ }
+
+ /**
+ * 获取path补全m a c后的默认值后的array
+ */
+ private function _getPathArr($path)
+ {
+ $config = Leguan::get('config');
+ $urlExtension = $config->urlExtension;
+ $urlLimiter = $config->urlLimiter;
+
+ $path = trim($path);
+ $path = trim($path,'/');
+ $path = trim($path,$urlLimiter);
+ $path = rtrim($path,$urlExtension);
+ if (empty($path)) {
+ $pathArr = array();
+ } else {
+ $pathArr = explode($urlLimiter, $path);
+ }
+
+ //给url补全缺省m c a
+ empty($pathArr[0]) && array_push($pathArr, $config->defaultModule);
+ empty($pathArr[1]) && array_push($pathArr, $config->defaultController);
+ empty($pathArr[2]) && array_push($pathArr, $config->defaultAction);
+
+ return $pathArr;
+ }
+
+ /**
+ * m c a 大小写处理
+ */
+ private function _ucwords()
+ {
+ $this->_url['m'] = ucwords(strtolower($this->_url['m']));
+ $this->_url['c'] = ucwords(strtolower($this->_url['c']));
+ $this->_url['a'] = strtolower($this->_url['a']);
+ }
+
+ /**
+ * 获取url
+ *
+ * @param $path string
+ * @return string
+ */
+ public function getUrl($path, $hasDomain = false)
+ {
+ $config = Leguan::get('config');
+ $urlType = $this->getUrlType($config->urlType);
+ $urlType = ucwords($urlType);
+ $action = "_get{$urlType}Url";
+ $url = '';
+
+ if ($hasDomain) {
+ $request = Leguan::get('request');
+ $url = $request->getDomain();
+ }
+
+ $url = $url . $this->$action($path);
+
+ return $url;
+ }
+
+ private function _getNormalUrl($path)
+ {
+ $pathArr = $this->_getPathArr($path);
+ $urlArr['m'] = $pathArr[0];
+ $urlArr['c'] = $pathArr[1];
+ $urlArr['a'] = $pathArr[2];
+ array_splice($pathArr,0,3);
+
+ $pathKeys = array();
+ $pathValues = array();
+ foreach ($pathArr as $key => $value) {
+ if($key % 2 == 0){
+ array_push($pathKeys, $value);
+ }else{
+ array_push($pathValues, $value);
+ }
+ }
+
+ if($pathKeys || $pathValues){
+ $pathCombine = array_combine($pathKeys, $pathValues);
+ $urlArr = array_merge($urlArr,$pathCombine);
+ }
+
+ $url = '?';
+ foreach ($urlArr as $key => $value) {
+ $url .= "{$key}={$value}&";
+ }
+
+ return "/index.php".rtrim($url,'&');
+ }
+
+ private function _getPathInfoUrl($path)
+ {
+ return "/index.php".$this->_getPathUrl($path);
+ }
+
+ private function _getRewriteUrl($path)
+ {
+ return $this->_getPathUrl($path);
+ }
+
+ private function _getCleanUrl($path)
+ {
+ return "/index.php?{$this->_cleanKey}=".$this->_getPathUrl($path);
+ }
+
+ private function _getPathUrl($path)
+ {
+ $pathArr = $this->_getPathArr($path);
+ $urlArr = array();
+ array_unshift($urlArr, array_pop($pathArr));
+ array_unshift($urlArr, array_pop($pathArr));
+ array_unshift($urlArr, array_pop($pathArr));
+
+ foreach ($pathArr as $key => $value) {
+ array_push($urlArr, $key);
+ array_push($urlArr, $value);
+ }
+
+ $config = Leguan::get('config');
+
+ return "/".implode('/', $urlArr).$config->urlExtension;
+ }
+
+}
\ No newline at end of file
diff --git a/library/Leguan/View/View.php b/library/Leguan/View/View.php
new file mode 100644
index 0000000..fb28b79
--- /dev/null
+++ b/library/Leguan/View/View.php
@@ -0,0 +1,334 @@
+config;
+ $viewLimiter = $config->viewLimiter;
+
+ $this->_lLimiter = $viewLimiter[0];
+ $this->_rLimiter = $viewLimiter[1];
+ $this->_escape = $config->viewEscape;
+ }
+
+ /**
+ * 加载模板
+ */
+ public function display($path = '')
+ {
+ $config = $this->config;
+ $cache = $this->_cache($path);
+ // $this->debug->dumpText($this->getContent($path));
+ // exit;
+
+ if($config->isDebug || !file_exists($cache)){
+ $cacheDir = dirname($cache);
+
+ if(!file_exists($cacheDir) &&
+ !mkdir($cacheDir, 0, true)){
+ die('创建目录失败 {$cacheDir}');
+ }
+
+ file_put_contents($cache, $this->getContent($path));
+ }
+
+ extract($this->_data);
+ require $cache;
+ }
+
+ /**
+ * 模板渲染输出
+ *
+ * @param $path string
+ */
+ public function getContent($path = '')
+ {
+ $view = $this->_view($path);
+
+ if(!file_exists($view)){
+ return "{$view}不存在";
+ }
+
+ $content = file_get_contents($view);
+ return $this->_compile($content);
+ }
+
+ /**
+ * 获取view路径
+ */
+ private function _view($path)
+ {
+ return $this->_filename($path);
+ }
+
+ /**
+ * 获取view 缓存路径
+ */
+ private function _cache($path)
+ {
+ return $this->_filename($path, true);
+ }
+
+ /**
+ * 获取模板路径
+ *
+ * @param $path string
+ * @param $isCache bool
+ * @return string
+ */
+ private function _filename($path = '',$isCache = false)
+ {
+ $path = ltrim($path,'/');
+
+ if (empty($path)) {
+ $path = array();
+ } elseif(strpos($path, '/') === false) {
+ $path = array($path);
+ } else {
+ $path = explode('/', $path);
+ }
+
+ $url = $this->url;
+ count($path) == 0 && array_unshift($path, $url->a);
+ count($path) == 1 && array_unshift($path, $url->c);
+ count($path) == 2 && array_unshift($path, $url->m);
+
+ $a = ucwords(array_pop($path));
+ $c = ucwords(array_pop($path));
+ $m = ucwords(array_pop($path));
+
+ $path = $this->path;
+ $config = $this->config;
+
+ if ($isCache) {
+ $filename = array($path->view, $config->theme, 'Cache', $m, $c, $a . $config->viewExtension);
+ } else {
+ $filename = array($path->view, $config->theme, $m, $c, $a . $config->viewExtension);
+ }
+
+ $filename = implode($path->ds, $filename);
+
+ return $filename;
+ }
+
+ /**
+ * 获取js css 文件目录
+ */
+ public function skin()
+ {
+ $path = $this->path;
+ $config = $this->config;
+
+ return $path->view. $path->ds . $config->theme . $path->ds . 'Skin';
+ }
+
+ /**
+ * 给模板分配变量
+ */
+ public function assign($name, $value)
+ {
+ $this->_data[$name] = $value;
+ }
+
+ public function __set($name, $value)
+ {
+ $this->assign($name, $value);
+ }
+
+ /**
+ * 解析模板内容
+ */
+ private function _compile($content)
+ {
+ $content = $this->_extends($content);
+ $content = $this->_removeArea($content);
+
+ $content = $this->_securityOutput($content);
+ $content = $this->_normalOutput($content);
+ $content = $this->_include($content);
+ $content = $this->_foreach($content);
+ $content = $this->_while($content);
+ $content = $this->_if($content);
+
+ $content = $this->_dump($content);
+
+ $content = $this->_php($content);
+ return $content;
+ }
+
+ /**
+ * 模板解析 - 模板继承
+ */
+ private function _extends($content)
+ {
+ //获取继承的目标path
+ $matches = array();
+ $pattern = "/{$this->_lLimiter}extends (.*?){$this->_rLimiter}/";
+ preg_match($pattern, $content, $matches);
+ if(!isset($matches[1])){
+ return $content;
+ }
+
+ $parentView = $this->_view($matches[1]);
+ if(!file_exists($parentView)){
+ return "{$parentView}不存在";
+ }
+
+ $parentContent = file_get_contents($parentView);
+ //找出子模板中的 area
+ $pattern = "|{$this->_lLimiter}area (.*?){$this->_rLimiter}(.*?){$this->_lLimiter}/area{$this->_rLimiter}|s";
+ preg_match_all($pattern, $content, $matches);
+ if(!isset($matches[1])){
+ return $parentContent;
+ }
+
+ //把子模板中的area替换掉在父模板中对应的area
+ foreach ($matches[1] as $key => $value) {
+ $pattern = "|{$this->_lLimiter}area {$value}{$this->_rLimiter}(.*?){$this->_lLimiter}/area{$this->_rLimiter}|s";
+ $replacement = "{$this->_lLimiter}area {$value}{$this->_rLimiter}
+ {$matches[2][$key]}
+ {$this->_lLimiter}/area{$this->_rLimiter}";
+ $parentContent = preg_replace($pattern, $replacement, $parentContent);
+ }
+
+ //如果还有上级继承 就递归
+ $pattern = "/{$this->_lLimiter}extends (.*?){$this->_rLimiter}/";
+ if(preg_match($pattern, $parentContent)){
+ return $this->_extends($parentContent);
+ }
+ return $parentContent;
+ }
+
+ /**
+ * 模板解析 - 移除area包裹
+ */
+ private function _removeArea($content)
+ {
+ $pattern = "|{$this->_lLimiter}area (.*?){$this->_rLimiter}(.*?){$this->_lLimiter}/area{$this->_rLimiter}|s";
+ return preg_replace_callback($pattern, function($matches){
+ return $matches[2];
+ }, $content);
+ }
+
+ /**
+ * 模板解析 - 安全输出
+ * {=$script} ==
+ */
+ private function _securityOutput($content)
+ {
+ $pattern = "/{$this->_lLimiter}=(.*?){$this->_rLimiter}/";
+ $replacement = "_escape}($1); ?>";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 模板解析 - 正常输出
+ * {!$script} ==
+ */
+ private function _normalOutput($content)
+ {
+ $pattern = "/{$this->_lLimiter}!(.*?){$this->_rLimiter}/";
+ $replacement = "";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 模板解析 - 加载模板
+ */
+ private function _include($content)
+ {
+ $pattern = "/{$this->_lLimiter}include (.*?){$this->_rLimiter}/";
+ $_this = $this;
+ $content = preg_replace_callback($pattern, function($matches) use($_this){
+ return $_this->getContent($matches[1]);
+ }, $content);
+
+ return $content;
+ }
+
+ /**
+ * 模板解析 - foreach
+ */
+ private function _foreach($content)
+ {
+ $pattern = "/{$this->_lLimiter}(foreach.*?){$this->_rLimiter}/";
+ $replacement = "";
+ $content = preg_replace($pattern, $replacement, $content);
+ $pattern = "|{$this->_lLimiter}/foreach{$this->_rLimiter}|";
+ $replacement = "";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 模板解析 - while
+ */
+ private function _while($content)
+ {
+ $pattern = "/{$this->_lLimiter}(while.*?){$this->_rLimiter}/";
+ $replacement = "";
+ $content = preg_replace($pattern, $replacement, $content);
+ $pattern = "|{$this->_lLimiter}/while{$this->_rLimiter}|";
+ $replacement = "";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 模板解析 - if
+ */
+ private function _if($content)
+ {
+ $pattern = "/{$this->_lLimiter}(if.*?){$this->_rLimiter}/";
+ $replacement = "";
+ $content = preg_replace($pattern, $replacement, $content);
+ $pattern = "|{$this->_lLimiter}else{$this->_rLimiter}|";
+ $replacement = "";
+ $content = preg_replace($pattern, $replacement, $content);
+ $pattern = "/{$this->_lLimiter}(elseif|else if)(.*?){$this->_rLimiter}/";
+ $replacement = "";
+ $content = preg_replace($pattern, $replacement, $content);
+ $pattern = "|{$this->_lLimiter}/if{$this->_rLimiter}|";
+ $replacement = "";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 模板解析 - php
+ */
+ private function _php($content)
+ {
+ $pattern = "/{$this->_lLimiter}(.*?){$this->_rLimiter}/";
+ $replacement = "";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+ /**
+ * 变量调试
+ */
+ private function _dump($content)
+ {
+ $pattern = "/{$this->_lLimiter}dump\((.*?)\){$this->_rLimiter}/";
+ $replacement = "debug->dump($1); ?>";
+ return preg_replace($pattern, $replacement, $content);
+ }
+
+}
diff --git a/library/Usheweb/Chapter/Chapter.php b/library/Usheweb/Chapter/Chapter.php
new file mode 100644
index 0000000..85658ea
--- /dev/null
+++ b/library/Usheweb/Chapter/Chapter.php
@@ -0,0 +1,172 @@
+_width = $width;
+ $this->_height = $height;
+ $this->_len = $len;
+ $this->_fontSize = $fontSize;
+
+ $this->setFont('elephant.ttf');
+ }
+
+ /**
+ * 设置图片宽度
+ *
+ * @param $width int
+ * @return void
+ */
+ public function setWidth($width)
+ {
+ $this->_width = $width;
+ }
+
+ /**
+ * 设置图片高度
+ *
+ * @param $height int
+ * @return void
+ */
+ public function setHeight($height)
+ {
+ $this->_height = $height;
+ }
+
+ /**
+ * 设置验证码字符数
+ *
+ * @param $len int
+ * @return void
+ */
+ public function setLen($len)
+ {
+ $this->_len = $len;
+ }
+
+ /**
+ * 设置字体尺寸
+ *
+ * @param $fontSize int
+ * @return void
+ */
+ public function setFontSize($fontSize)
+ {
+ $this->_fontSize = $fontSize;
+ }
+
+ /**
+ * 设置字体
+ *
+ * @param $font string
+ * @return void
+ */
+ public function setFont($font)
+ {
+ $this->_font = $font;
+ }
+
+ /**
+ * 显示验证码
+ */
+ public function show()
+ {
+ $this->_createBg();
+ $this->_createCode();
+ $this->_createLine();
+ $this->_createFont();
+ $this->_outPut();
+ }
+
+ /**
+ * 获取验证码
+ */
+ public function getChapter()
+ {
+ return strtolower($this->_code);
+ }
+
+ //生成随机码
+ private function _createCode()
+ {
+ $_len = strlen($this->_charset)-1;
+ for ($i=0;$i<$this->_len;$i++) {
+ $this->_code .= $this->_charset[mt_rand(0,$_len)];
+ }
+ }
+
+ //生成背景
+ private function _createBg()
+ {
+ $this->_img = imagecreatetruecolor($this->_width, $this->_height);
+ $color = imagecolorallocate($this->_img, mt_rand(157,255), mt_rand(157,255), mt_rand(157,255));
+ imagefilledrectangle($this->_img,0,$this->_height,$this->_width,0,$color);
+ }
+
+ //生成文字
+ private function _createFont()
+ {
+ $_x = $this->_width / $this->_len;
+ for ($i=0;$i<$this->_len;$i++) {
+ $this->_fontcolor = imagecolorallocate($this->_img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
+
+ //判断是否支持 FreeType
+ $gdInfo = gd_info();
+ if(isset($gdInfo['FreeType Support'])
+ && $gdInfo['FreeType Support'] === true){
+ $font = array(dirname(__FILE__), 'font', $this->_font);
+ $font = implode(DIRECTORY_SEPARATOR, $font);
+
+ imagettftext($this->_img,$this->_fontsize,mt_rand(-30,30),$_x*$i+mt_rand(1,5),$this->_height / 1.4,$this->_fontcolor,$font,$this->_code[$i]);
+ }else{
+ imagechar($this->_img, mt_rand(3,30), $_x*$i+mt_rand(5,15), mt_rand(0,$this->_height/2), $this->_code[$i], $this->_fontcolor);
+ }
+ }
+ }
+
+ //生成线条、雪花
+ private function _createLine()
+ {
+ for ($i=0;$i<6;$i++) {
+ $color = imagecolorallocate($this->_img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
+ imageline($this->_img,mt_rand(0,$this->_width),mt_rand(0,$this->_height),mt_rand(0,$this->_width),mt_rand(0,$this->_height),$color);
+ }
+ for ($i=0;$i<100;$i++) {
+ $color = imagecolorallocate($this->_img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255));
+ imagestring($this->_img,mt_rand(1,5),mt_rand(0,$this->_width),mt_rand(0,$this->_height),'*',$color);
+ }
+ }
+
+ //输出
+ private function _outPut()
+ {
+ header('Content-type:image/png');
+ imagepng($this->_img);
+ imagedestroy($this->_img);
+ }
+}
\ No newline at end of file
diff --git a/library/Usheweb/Chapter/font/elephant.ttf b/library/Usheweb/Chapter/font/elephant.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2763d31491f0f2b9b74374ec26aa7f74f680bc13
GIT binary patch
literal 44820
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
sE+?yeAzUe0r41y@9;6E$(59JV<
zo~Fm~
z*M#)1;Bt$ybGf<9g)(veIZtPDoJZtuwiEeVj5Y=&-fLn|6XJPPZ5^kPmQ|=DIZ>~q=n|Y=L!Mg*w
zj|A`dH|kCB&PP#Wn0uD%OYrO+YLMPR+c*wwL$t|hzMx*U
z2Gs31>H~GfUx4%?_5xlcI~_;gc%1AUm*6kznC{Q5lm-#kAl1oVLH)t5wkRXoDu?Cw
z1i!)S!e8dQXkXmM@=lZwY4dO4M}2UcVkda~9(3|lw-$dl!#xhS4`um0{$30>UML&d
zbD7+OZv*+`d@2#7w;}f~@_oCqgMJ}BOHOVR_!9B8TfT{dD%*?jJ9B`UdvLfww}!&i*j)0Olr)oxo$5`>`K&3Y>$SmLVo9
za@8!Jx`Fp0J*!BUV^{$HNg75-6OF+C9h_^k=3c-&n{lLg`=ogu?0RH#D4GuXB{|TgGgXN(S
z@pOdiz~kTyhfh%n
zxHQc5fOJa`dst9LfZsuw66DGa|9#+IiO53MR>*(ss6AC
z!L@8FUBKUhpUwE*
z9|c~67Sf#i3F@dBE6f(43AN1OzXjZdT4>HahIb<(Eyh&d-y+gtOyQcu9R#A$$2+x=z#t5~Er)`3h?Vu!a=Q=-S?4S-{3-Ed5If4E>ND0(w
z7=A74D}gVl9r#}elYrE=TlhPGe}x8o0zBLYd;u*g0S?%J$IvzsxgUcY3DTeqFy&t0
z5#)qpco_HsYL+Q2)S3GOa?&Ys#TbGA2=dUGdlRiL2}%R-E%2QE2Z4u?E~5>21TnL}
z5y(9!BTg}36p8>j{$%bs^y?g^33w7^VSGYR4pIvA7T|M;Aq9E^@GZp2^r)Z&fxp08
z{Ip461o%^=o(z6r4kz##Aiq|${{+JRh0UAb=}=Nu+M-MQa@(ha&zU{GL|(sVcag*3j~1PvgD
zF5vU%qXrN%3H%QF+W~xooq`euzJQj=VPb+37nD`PKM(i;da8lkhp3~0+_%vOay-qz
zBgpvx`tuPQME+L;Pa@8Fz!Bg_h?D&Z;FG8k_Ma{A5Ok}!e&>U-T41NZ5#UD%lL37g
z_z}XeKMZ^lrN|(MhXk$?^b~LsF>siezy$C~l#%IUf-(a92<ke|1tWuQPgP$_}|FesED7#91xTd;Cu9l
z@UIe22WSQ22?F0jjjTXFb2j`Z;adT&4%15blR$1KE0OvNAh$rKBm^ZauuD+l!f&Hh
zBA=`9ZV>(>h=(aFg#QrmBrOGgfIP3ty$y>R?2iEd06we&m+lml5g@mdRk=T+>>PuQ
z#zZ`0xtBp71AP$4?~dhOM}GL}2$0hqL%IXNw-FnM83w+I)-wjqEESa1K>lXW##>8)
zAA(C~gYt;LjKC3rcLF~||G64*t^%G!%&Wo4Fp%F}ji)1m9s#~in2De+7ND*?$Q6ef
z6Hk-C!{FX(j7PPC(hfWh&a6g>T7V~zb511-d;@u7$}sRxC3qN2_qt4Lk@Oi|;*eNJU;3QIEJX=uWK<-sId>Hs7
z_|E=GCOobozK_3Ag2K}Yn
zR=o9+c#AP9{8`}tL9SlPt;32{{Wp$3v)$WR%3gt0{8d=7e+)U)c8EsagxNdnr0Xw%
z`w{K}cnwQj{5IYO_XOO#5Q&$;eUWey8V>Ijk6}FwzcoT+gXFx#i_IelN9|Z1+b<(3
z)4`?S?tuF#jB6qeC*E-l6IE;_awEL^S45RZi9E-MybhvjjCtUGN7RaZwRXW>
zLlnPJl0cO%VSq~H4iQTker)v5P6+9N;Llxq71@kpCej;cwhmB79!sZKO|a&XN&HF18)}{CmI5ehN5sQ
z;Slc-@-*~3+?zzhcs7jk3?q$Ulx_G9xF_I#OXzOl{BQ$s;ML;W;l2s?GTggFOUmF<
zaI4`^)+KkteIE{KE?olm9inAOYs5k{ItKSeq7{f|<*h_xeMDz3B3gqu)+~oZe$L&6
zrh~Y~@!mMnAOD!>eEhxu^tFh4E#h8_JWm*i)*+wkw-aqZxQ+J_ZJH$7+y;mEw}8IY
zO|%W~Y%hhondl77l#B=zKWPcAzXfk?u~EWtR``O`?kr5M82!+dy=w1`ZW}=~6i4
z;nG8J?+{(?BD%sxbQS1VfhSk}ndoYybv5F;8fCu*JiP{axd!~c<|;TmyXGfwCx~|A
zz1?`W8_#y**={`BjrVrry=&LO;rDg*aLeHyfkU3IA1Auu9Jr_8J|w!)3zsIkDMWNL
z;<_1e-FyYnEr{<{uR
zF1bGM*O5<7=lup+B##TfiSq+{BpluZ-q_?Pgx}2hk$;l+GyRD07m4u4^M0nkC;WUn
zfkk0Gd`V;Dc$8A%XPYObkU=xuF6eyzQqu7KXhq6E-p}Ee2!EBJt9h#u;kPi|;1Kky
z@_r6~EBlK?{*|xf{Y*b7{34&qxAT6cKlh+7mQ1$#`p?_3Yhs5l<
z8+PsV?U>j(vE!17wUNOs6WceOw{_RjiS-w6Id4bdXW{SY#EzXv!553fq6J!WKI|Fu
zux!`Ht?QSbcX`c2zR_4D8jV0oxs7(vg>)Wm!8~{iP0)7QfL~i_7i`q+627&-9aw>$
z{`^7mVU?4_f35KKi%`1|!w&ok3CcFaGXdXnx*YMcFAK^Am}U6r)VF6sEJKdA(8Wl5
zBYazFC)Vk+-&-PbJoEJQn1=A)1<1oTyt$3mAs)^fmvXyEcP?Vz0@@CQTaU8tLOA|4
zfxn#hOMq(;^7PU!1${m8wMCTk^rxr)9u;xz%$I@r6oHF=BGzWiuV%;luk(RxXCwHt
z9xqD$#yaO*~BN_oZV{9+-_#Se>&g(
ze?P;N3cVx#<*vls?o9vQ$P=MXhQ1IsSkPBPIS7(9oct#X=CwA=MoY1KQU*!21JYd=
zRbb6jiFI2Qq=nU}l^W+_4SwWk}*MGfiSv
zIR_J(Zt8)?S(@hJG*Uli<%5_N&&SFf7cpUWz6f%OVN5TUVD`KeU+Z$LeMT{dUWwW0
z7*-9dX$_qNeYJ74kMr?OtVK&(C))f*+C-aC?-!!|Y{PeP5!(Guw5N;F`Y)x+(3-BG
zE1|)8HAbl2bS*6HT#q&2jdT-6saxn)`V8GhdoUL6#YnZEK1W}mFVdGV8h)9+g7NBW
zSOeclcR_OXzvv$NI^|_X>92e+hftzoK8$5&8}N
zmi_~y;P2@*I!dq8AL$Kxi=Zb=C+IKqHoZen)01>OT^BU?aUF!$;DIi#%izF0Riy@-
z!D1+a3V^|&GiVGL0}Zrr^0^CW;rYJFlgk26NT##KCbfY+X|i-7EnMFBBy?b(yJ@fE
zQJrpZ(l9;%4Up6SxgO1A1~*Qo_Y6Fm&8i+){Tkdbc@|uH&-kP-Ffgfue`)@=KQMr1
G_J0Aepy_`A
literal 0
HcmV?d00001
diff --git a/library/Usheweb/Upload/Mime.php b/library/Usheweb/Upload/Mime.php
new file mode 100644
index 0000000..9ec055f
--- /dev/null
+++ b/library/Usheweb/Upload/Mime.php
@@ -0,0 +1,75 @@
+ 'application/zip',
+ 'rar' => 'application/x-rar-compressed',
+ 'tar' => 'application/x-tar',
+ 'gz' => 'application/x-gzip',
+ 'jpg' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpe' => 'image/jpeg',
+ 'jpz' => 'image/jpeg',
+ 'gif' => 'image/gif',
+ 'ifm' => 'image/gif',
+ 'bmp' => 'application/x-MS-bmp',
+ 'png' => 'image/png',
+ 'mp3' => 'audio/x-mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpg4' => 'video/mp4',
+ 'rmvb' => 'audio/x-pn-realaudio',
+ 'doc' => 'application/msword',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'txt' => 'text/plain',
+ );
+ /**
+ * 获取文件扩展
+ */
+ public static function getExtension($mime)
+ {
+ $data = array_flip(self::$_data);
+ if (isset($data[$mime])) {
+ return $data[$mime];
+ }
+
+ return null;
+ }
+
+ /**
+ * 获取文件Mime
+ */
+ public static function getMime($extension)
+ {
+ $data = self::$_data;
+ if (isset($data[$extension])) {
+ return $data[$extension];
+ }
+
+ return null;
+ }
+ }
\ No newline at end of file
diff --git a/library/Usheweb/Upload/Upload.php b/library/Usheweb/Upload/Upload.php
new file mode 100644
index 0000000..70b11b8
--- /dev/null
+++ b/library/Usheweb/Upload/Upload.php
@@ -0,0 +1,169 @@
+_fileSize = $config->fileMaxSize;
+ $this->_fileExtension = $config->fileExtension;
+
+ $path = Leguan::get('path');
+ $this->_fileDir = $path->upload;
+ }
+
+ /**
+ * 设置上传文件表单name
+ *
+ * @param $name string
+ * @return void
+ */
+ public function setFormName($name)
+ {
+ $this->_formName = $name;
+ }
+
+ /**
+ * 设置上传文件大小
+ *
+ * @param $size int
+ * @return void
+ */
+ public function setFileSize($size)
+ {
+ $this->_fileSize = $size;
+ }
+
+ /**
+ * 设置上传文件所在目录
+ *
+ * @param $fileDir string
+ * @return void
+ */
+ public function setFileDir($fileDir)
+ {
+ $this->_fileDir = $fileDir;
+ }
+
+ /**
+ * 设置上传文件允许扩展名
+ *
+ * @param $fileExtention array
+ * @return void
+ */
+ public function setFileExtention($fileExtention)
+ {
+ $this->_fileExtention = $fileExtention;
+ }
+
+ public function run()
+ {
+ //新上传文件所在路径
+ $filePath = array();
+
+ if(!isset($_FILES[$this->_formName])){
+ return "上传文件失败,1.表单上传name是否为{$this->_formName} 2.文件不能大于". $this->_fileSize / 1024 / 1024 .'MB';
+ }
+
+ //多文件上传
+ if (is_array($_FILES[$this->_formName]['error'])) {
+ foreach ($_FILES[$this->_formName]['error'] as $key => $error) {
+ if (empty($_FILES[$this->_formName]['name'][$key])) {
+ continue;
+ }
+
+ if ($_FILES[$this->_formName]['error'][$key] == UPLOAD_ERR_OK) {
+
+ $file = $_FILES[$this->_formName];
+ $result = $this->_exec($file['name'][$key], $file['type'][$key], $file['tmp_name'][$key], $file['error'][$key], $file['size'][$key]);
+ if (!is_array($result)) {
+ return $result;
+ }
+
+ array_push($filePath, array_pop($result));
+ } else {
+ return '文件上传失败';
+ }
+ }
+ } else {
+ //单文件上传
+ $file = $_FILES[$this->_formName];
+ $result = $this->_exec($file['name'], $file['type'], $file['tmp_name'], $file['error'], $file['size']);
+ if(is_array($result)){
+ array_push($filePath, array_pop($result));
+ } else {
+ return $result;
+ }
+ }
+
+ return $filePath;
+ }
+
+ /**
+ * 表单处理
+ */
+ private function _exec($name, $type, $tmp_name, $error, $size)
+ {
+ if ($size > $this->_fileSize) {
+ return '上传文件失败,文件不能大于' . $this->_fileSize / 1024 / 1024 .'MB';
+ }
+
+ $extension = Leguan::get('path')->getExtension($name);
+
+ if (empty($extension)) {
+ return '文件扩展名不能为空';
+ }
+
+ if (!in_array($extension, $this->_fileExtension)) {
+ return "上传文件失败,文件类型不允许为扩展{$extension}";
+ }
+
+ $path = Leguan::get('path');
+ $dirName = date('Ym') . $path->ds . date('d');
+ $realPath = array($this->_fileDir, $dirName);
+ $realPath = implode($path->ds, $realPath);
+ //判断目录是否存在
+ if (!file_exists($realPath)) {
+ mkdir($realPath, 0, true);
+ }
+
+ $fileName = md5_file($tmp_name).".{$extension}";
+ $filePath = array();
+ array_push($filePath, $dirName . $path->ds . $fileName);
+ move_uploaded_file($tmp_name, "{$realPath}{$path->ds}{$fileName}");
+
+ return $filePath;
+ }
+
+ /**
+ * 获取表单最大文件上传尺寸隐藏字段
+ */
+ public function getFormMaxSize()
+ {
+ return "";
+ }
+
+ }
\ No newline at end of file
diff --git a/themes/Default/Cache/Index/Index/Index.php b/themes/Default/Cache/Index/Index/Index.php
new file mode 100644
index 0000000..3352b5b
--- /dev/null
+++ b/themes/Default/Cache/Index/Index/Index.php
@@ -0,0 +1,33 @@
+TOP
+
+
+
+
+ Hi , Leguan for
+
+
+
+
+ - ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/themes/Default/Cache/Index/Index/Upload.php b/themes/Default/Cache/Index/Index/Upload.php
new file mode 100644
index 0000000..bc3829c
--- /dev/null
+++ b/themes/Default/Cache/Index/Index/Upload.php
@@ -0,0 +1,19 @@
+
+
+
+
+ 文件上传测试
+
+
+
+
+
\ No newline at end of file
diff --git a/themes/Default/Index/Index/Index.php b/themes/Default/Index/Index/Index.php
new file mode 100644
index 0000000..00e48db
--- /dev/null
+++ b/themes/Default/Index/Index/Index.php
@@ -0,0 +1,36 @@
+
+
+
+
+
+ Hi , Leguan for
+
+
+
+
+ - ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+test
+
+
\ No newline at end of file
diff --git a/themes/Default/Index/Index/Parent.php b/themes/Default/Index/Index/Parent.php
new file mode 100644
index 0000000..91152b5
--- /dev/null
+++ b/themes/Default/Index/Index/Parent.php
@@ -0,0 +1,13 @@
+
+title
+
+body
+
+
+
+
+footer
\ No newline at end of file
diff --git a/themes/Default/Index/Index/Test.php b/themes/Default/Index/Index/Test.php
new file mode 100644
index 0000000..db03c10
--- /dev/null
+++ b/themes/Default/Index/Index/Test.php
@@ -0,0 +1 @@
+include test for
\ No newline at end of file
diff --git a/themes/Default/Index/Index/Top.php b/themes/Default/Index/Index/Top.php
new file mode 100644
index 0000000..e8513fd
--- /dev/null
+++ b/themes/Default/Index/Index/Top.php
@@ -0,0 +1,4 @@
+TOP
+
+body
+
\ No newline at end of file
diff --git a/themes/Default/Index/Index/upload.php b/themes/Default/Index/Index/upload.php
new file mode 100644
index 0000000..4ebc1c3
--- /dev/null
+++ b/themes/Default/Index/Index/upload.php
@@ -0,0 +1,19 @@
+
+
+
+
+ 文件上传测试
+
+
+
+
+
\ No newline at end of file