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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 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 +

+ +
    + +
  1. ()
  2. + +
+

+ + + + + +

+
    + + + +
  • + + + +
+

+ + + \ 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 @@ + + + + + 文件上传测试 + + +
+ getFormMaxSize(); ?> +
+ + +
+ + \ 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 +

+ +
    + +
  1. ()
  2. + +
+

+ + + + + +

+
    + + + +
  • + + + +
+

+ + +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

+ + +
    +
  • 1
  • +
  • 2
  • +
  • 3
  • +
+ +

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