diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/Plugin.php b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/Plugin.php
new file mode 100644
index 0000000..a64969c
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/Plugin.php
@@ -0,0 +1,455 @@
+begin = array('TpCache_Plugin', 'C');
+ Typecho_Plugin::factory('index.php')->end = array('TpCache_Plugin', 'S');
+
+ //页面编辑
+ Typecho_Plugin::factory('Widget_Contents_Post_Edit')->finishPublish = array('TpCache_Plugin', 'post_update');
+ Typecho_Plugin::factory('Widget_Contents_Page_Edit')->finishPublish = array('TpCache_Plugin', 'post_update');
+
+ //评论
+ Typecho_Plugin::factory('Widget_Feedback')->finishComment = array('TpCache_Plugin', 'comment_update');
+
+
+ return '插件安装成功,请设置需要缓存的页面';
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate()
+ {
+ try {
+ $uninstall_sql = 'DROP TABLE IF EXISTS `%prefix%cache`';
+ $db = Typecho_Db::get();
+ $prefix = $db->getPrefix();
+ $sql = str_replace('%prefix%', $prefix, $uninstall_sql);
+ $db->query($sql);
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ }
+ }
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+
+ $list = array(
+ 'index' => '首页',
+ 'archive' => '归档',
+ 'post' => '文章',
+ 'attachment' => '附件',
+ 'category' => '分类',
+ 'tag' => '标签',
+ 'author' => '作者',
+ 'search' => '搜索',
+ 'feed' => 'feed',
+ 'page' => '页面',
+ );
+ $element = new Typecho_Widget_Helper_Form_Element_Checkbox('cache_page', $list, array('index', 'post', 'search', 'page', 'author', 'tag'), '需要缓存的页面');
+ $form->addInput($element);
+
+ $list = array('关闭', '开启');
+ $element = new Typecho_Widget_Helper_Form_Element_Radio('login', $list, 1, '是否对已登录用户失效', '已经录用户不会触发缓存策略');
+ $form->addInput($element);
+
+ $list = array('关闭', '开启');
+ $element = new Typecho_Widget_Helper_Form_Element_Radio('enable_ssl', $list, '0', '是否支持SSL');
+ $form->addInput($element);
+
+ $list = array(
+ '0' => '不使用缓存',
+ 'memcached' => 'Memcached',
+ 'memcache' => 'Memcache',
+ 'redis' => 'Redis',
+ 'mysql' => 'Mysql'
+ );
+ $element = new Typecho_Widget_Helper_Form_Element_Radio('cache_driver', $list, '0', '缓存驱动');
+ $form->addInput($element);
+
+ $element = new Typecho_Widget_Helper_Form_Element_Text('expire', null, '86400', '缓存过期时间', '86400 = 60s * 60m *24h,即一天的秒数');
+ $form->addInput($element);
+
+ $element = new Typecho_Widget_Helper_Form_Element_Text('host', null, '127.0.0.1', '主机地址', '主机地址,一般为127.0.0.1');
+ $form->addInput($element);
+
+ $element = new Typecho_Widget_Helper_Form_Element_Text('port', null, '11211', '端口号', '端口号,memcache对应11211,Redis对应6379,其他类型随意填写');
+ $form->addInput($element);
+
+ $list = array('关闭', '开启');
+ $element = new Typecho_Widget_Helper_Form_Element_Radio('is_debug', $list, 0, '是否开启debug');
+ $form->addInput($element);
+
+ $list = array('关闭', '清除所有数据');
+ $element = new Typecho_Widget_Helper_Form_Element_Radio('is_clean', $list, 0, '清除所有数据');
+ $form->addInput($element);
+ }
+
+ /**
+ * 手动保存配置句柄
+ * @param $config array 插件配置
+ * @param $is_init bool 是否初始化
+ */
+ public static function configHandle($config, $is_init)
+ {
+ if ($is_init != true && $config['cache_driver'] != '0') {
+
+ $driver_name = $config['cache_driver'];
+ $class_name = "typecho_$driver_name";
+ $file_path = "driver/$class_name.class.php";
+ require_once 'driver/cache.interface.php';
+ require_once $file_path;
+ self::$cache = call_user_func(array($class_name, 'getInstance'), self::$plugin_config);
+ try {
+ if ($config['is_clean'] == '1') self::$cache->flush();
+ } catch (Exception $e) {
+ print $e->getMessage();
+ die;
+ }
+ // 删除缓存仅生效一次
+ $config['is_clean'] = '0';
+ }
+
+ Helper::configPlugin('TpCache', $config);
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form)
+ {
+ }
+
+ /**
+ * 缓存前置操作
+ */
+ public static function C()
+ {
+ $start = microtime(true);
+ // 插件初始化
+ if (self::init() == false) return false;
+ // 前置条件检查
+ if (self::pre_check() == false) return false;
+
+ //获取路径信息
+ $pathInfo = self::$request->getPathInfo();
+
+ //判断是否需要缓存
+ if (!self::needCache($pathInfo)) return false;
+
+ try {
+ $data = self::get(self::$path);
+ if ($data != false) {
+ $data = unserialize($data);
+ //如果超时
+ if ($data['c_time'] + self::$plugin_config->expire <= time()) {
+
+ if (self::$plugin_config->is_debug) echo "Expired!\n";
+ $data['c_time'] = $data['c_time'] + 20;
+ self::set(self::$path, serialize($data));
+ } else {
+ if (self::$plugin_config->is_debug) echo "Hit!\n";
+ if ($data['html']) echo $data['html'];
+ $end = microtime(true);
+ $time = number_format(($end - $start), 6);
+ if (self::$plugin_config->is_debug) echo 'This page loaded in ', $time, ' seconds';
+ die;
+ }
+ } else {
+ if (self::$plugin_config->is_debug) echo "Can't find cache!";
+ }
+
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ }
+ // 先进行一次刷新
+ ob_flush();
+
+ }
+
+ /**
+ * 前置检查
+ * @return bool
+ */
+ public static function pre_check()
+ {
+ //对登录用户失效
+ if (self::check_login()) return false;
+ //针对POST失效
+ if (self::$request->isPost()) return false;
+ //是否支持SSL
+ if (self::$plugin_config->enable_ssl == '0' && self::$request->isSecure() == true) return false;
+ return true;
+ }
+
+ /**
+ * 判断用户是否登录
+ * @return bool
+ * @throws Typecho_Widget_Exception
+ */
+ public static function check_login()
+ {
+ //http与https相互独立
+ return (self::$plugin_config->login && Typecho_Widget::widget('Widget_User')->hasLogin());
+ }
+
+ /**
+ * 根据配置判断是否需要缓存
+ * @param string 路径信息
+ * @return bool
+ */
+ public static function needCache($path)
+ {
+ //后台数据不缓存
+ $pattern = '#^' . __TYPECHO_ADMIN_DIR__ . '#i';
+ if (preg_match($pattern, $path)) return false;
+
+ //action动作不缓存
+ $pattern = '#^/action#i';
+ if (preg_match($pattern, $path)) return false;
+
+ $_routingTable = self::$sys_config->routingTable;
+
+ $exclude = array('_year', '_month', '_day', '_page');
+
+ foreach ($_routingTable[0] as $key => $route) {
+ if ($route['widget'] != 'Widget_Archive') continue;
+
+ if (preg_match($route['regx'], $path, $matches)) {
+ $key = str_replace($exclude, '', str_replace($exclude, '', $key));
+
+ if (in_array($key, self::$plugin_config->cache_page)) {
+ if (self::$plugin_config->is_debug) echo "This page needs to be cached!\n" . '
+ Bug Report ';
+ self::$path = $path;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * 缓存后置操作
+ */
+ public static function S()
+ {
+ //对登录用户失效
+ if (self::check_login()) return;
+
+ //若self::$key不为空,则使用缓存
+ if (is_null(self::$key)) return;
+
+
+ $html = ob_get_contents();
+
+ if (!empty($html)) {
+ $data = array();
+ $data['c_time'] = time();
+ $data['html'] = $html;
+ //更新缓存
+ if (self::$plugin_config->is_debug) echo "Cache updated!\n";
+ self::set(self::$key, serialize($data));
+ }
+
+ }
+
+
+ /**
+ * 编辑文章后更新缓存
+ * @param $contents
+ * @param $class
+ */
+ public static function post_update($contents, $class)
+ {
+ if ('publish' != $contents['visibility'] || $contents['created'] > time()) {
+ return;
+ }
+ //获取系统配置
+ $options = Helper::options();
+
+ if(!$options->plugin('TpCache')->cache_driver){
+ return;
+ }
+ //获取文章类型
+ $type = $contents['type'];
+ //获取路由信息
+ $routeExists = (NULL != Typecho_Router::get($type));
+
+ if (!is_null($routeExists)) {
+ $db = Typecho_Db::get();
+ $contents['cid'] = $class->cid;
+ $contents['categories'] = $db->fetchAll($db->select()->from('table.metas')
+ ->join('table.relationships', 'table.relationships.mid = table.metas.mid')
+ ->where('table.relationships.cid = ?', $contents['cid'])
+ ->where('table.metas.type = ?', 'category')
+ ->order('table.metas.order', Typecho_Db::SORT_ASC));
+ $contents['category'] = urlencode(current(Typecho_Common::arrayFlatten($contents['categories'], 'slug')));
+ $contents['slug'] = urlencode($contents['slug']);
+ $contents['date'] = new Typecho_Date($contents['created']);
+ $contents['year'] = $contents['date']->year;
+ $contents['month'] = $contents['date']->month;
+ $contents['day'] = $contents['date']->day;
+ }
+
+ //生成永久连接
+ $path_info = $routeExists ? Typecho_Router::url($type, $contents) : '#';
+
+ self::init();
+
+ if (self::needCache($path_info)) self::delete(self::$path);
+ }
+
+ /**
+ * 评论更新
+ *
+ * @access public
+ * @param array $comment 评论结构
+ * @param Typecho_Widget $post 被评论的文章
+ * @param array $result 返回的结果上下文
+ * @param string $api api地址
+ * @return void
+ */
+ public static function comment_update($comment)
+ {
+ $req = new Typecho_Request();
+ self::delete(str_replace($req->getRequestRoot(), '', $req->getReferer()));
+ }
+
+ /**
+ * 插件配置初始化
+ * @return bool
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function init()
+ {
+ if (is_null(self::$sys_config)) {
+ self::$sys_config = Helper::options();
+ }
+ if (is_null(self::$plugin_config)) {
+ self::$plugin_config = self::$sys_config->plugin('TpCache');
+ }
+
+ if (self::$plugin_config->cache_driver == '0') {
+ return false;
+ }
+
+ if (is_null(self::$cache)) {
+ $driver_name = self::$plugin_config->cache_driver;
+ $class_name = "typecho_$driver_name";
+ $file_path = "driver/$class_name.class.php";
+ require_once 'driver/cache.interface.php';
+ require_once $file_path;
+ self::$cache = call_user_func(array($class_name, 'getInstance'), self::$plugin_config);
+ }
+ if (is_null(self::$request)) {
+ self::$request = new Typecho_Request();
+ }
+
+ return true;
+ }
+
+
+ public static function set($path, $data)
+ {
+
+ if (!is_null(self::$key)) return self::$cache->set(self::$key, $data);
+ $prefix = self::$request->getUrlPrefix();
+ self::$key = md5($prefix . $path);
+
+ return self::$cache->set(self::$key, $data);
+ }
+
+ public static function add($path, $data)
+ {
+
+ }
+
+ public static function get($path)
+ {
+ if (!is_null(self::$key)) return self::$cache->get(self::$key);
+ $prefix = self::$request->getUrlPrefix();
+ self::$key = md5($prefix . $path);
+ return self::$cache->get(self::$key);
+ }
+
+ /**
+ * 删除指定路径
+ * @param string $path 待删除路径
+ * @param null $del_home 是否删除首页缓存
+ */
+ public static function delete($path, $del_home = null)
+ {
+ $prefixs = array(
+ 'http'
+ . '://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] :
+ ($_SERVER['SERVER_NAME'] . (in_array($_SERVER['SERVER_PORT'], array(80, 443))
+ ? '' : ':' . $_SERVER['SERVER_PORT']))
+ ),
+ 'https'
+ . '://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] :
+ ($_SERVER['SERVER_NAME'] . (in_array($_SERVER['SERVER_PORT'], array(80, 443))
+ ? '' : ':' . $_SERVER['SERVER_PORT']))
+ ),
+ );
+ $keys = array();
+ if (!is_array($path)) {
+ $keys[] = $path;
+ } else {
+ $keys = $path;
+ }
+
+
+ foreach ($keys as $v) {
+ foreach ($prefixs as $prefix) {
+ echo $prefix . $v;
+ @self::$cache->delete(md5($prefix . $v));
+ }
+ }
+
+ if (is_null($del_home)) {
+ foreach ($prefixs as $prefix) {
+ echo $prefix . '/';
+ @self::$cache->delete(md5($prefix . '/'));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/README.md b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/README.md
new file mode 100644
index 0000000..52ccfd1
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/README.md
@@ -0,0 +1,70 @@
+## 功能
+
+减缓网站并发压力而开发的缓存插件。
+
+## 注意
+
+1. 支持**Memcache**,**Redis**,**Mysql**三种驱动。
+1. **非js方式的**访问统计插件会失效
+1. BUG请在[缓存插件TpCache for Typecho][1]页汇报
+
+
+
+
+
+## 使用说明
+
+### 后台设置
+
+![后台设置截图][2]
+
+### 组件支持
+
+**请确保你的服务器memcache套件工作正常。**
+
+目前老高提供了php**memcache**与**memcached**的支持,请选择对应的驱动。
+
+memcached配置请参考[Linux服务器配置memcached并启用PHP支持][3]。
+
+Redis配置请参考[Linux服务器配置Redis并启用PHP支持][4]。
+
+### 缓存更新机制
+
+**目前以下操作会触发缓存更新**
+
+- 来自原生评论系统的评论
+- 后台文章或页面更新
+- 重启memcached
+- 缓存到期
+
+### 评论
+
+原生评论简单测试过,没有大问题。
+
+不过既然使用缓存了不如直接使用第三方评论系统,如多说。
+
+## 性能
+
+在老高的烂主机上随便就能跑到保守800的并发(CPU占用不到70%),什么概念呢?
+
+理论上支持每天**69120000**(60\*60\*24\*800)的PV。
+
+## 下载
+
+ TpCache
+
+ TpCache
+
+## 安装
+
+请将文件夹**重命名**为TpCache。再拷贝至`usr/plugins/下`。
+
+## 升级
+
+请先**禁用此插件**后再升级,很多莫名其妙的问题都是因为没有先禁用而直接升级导致的!
+
+
+ [1]: http://www.phpgao.com/tpcache_for_typecho.html
+ [2]: http://www.phpgao.com/usr/uploads/2015/05/3901966986.jpeg
+ [3]: http://www.phpgao.com/php-memcached-extension-installation.html
+ [4]: http://www.phpgao.com/redis_php.html
\ No newline at end of file
diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/cache.interface.php b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/cache.interface.php
new file mode 100644
index 0000000..26d8eb9
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/cache.interface.php
@@ -0,0 +1,23 @@
+host = $option->host;
+ $this->port = $option->port;
+ $this->expire = $option->expire;
+ $this->init($option);
+ }
+
+ static public function getInstance($option)
+ {
+ if (is_null(self::$_instance) || isset (self::$_instance)) {
+ self::$_instance = new self($option);
+ }
+ return self::$_instance;
+ }
+
+ public function init($option)
+ {
+ try {
+ $this->mc = new Memcache;
+ $this->mc->addServer($this->host, $this->port);
+ } catch (Exception $e) {
+ echo $e->getMessage();
+ }
+ }
+
+ public function add($key, $value, $expire = null)
+ {
+ return $this->mc->add($key, $value, false, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function delete($key)
+ {
+ return $this->mc->delete($key);
+ }
+
+ public function set($key, $value, $expire = null)
+ {
+ return $this->mc->set($key, $value, false, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function get($key)
+ {
+ return $this->mc->get($key);
+ }
+
+ public function flush()
+ {
+ return $this->mc->flush();
+ }
+}
\ No newline at end of file
diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_memcached.class.php b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_memcached.class.php
new file mode 100644
index 0000000..cb0192d
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_memcached.class.php
@@ -0,0 +1,59 @@
+host = $option->host;
+ $this->port = $option->port;
+ $this->expire = $option->expire;
+ $this->init($option);
+ }
+
+ static public function getInstance($option) {
+ if (is_null ( self::$_instance ) || isset ( self::$_instance )) {
+ self::$_instance = new self($option);
+ }
+ return self::$_instance;
+ }
+
+ public function init($option)
+ {
+ try{
+ $this->mc = new Memcached;
+ $this->mc->addServer($this->host, $this->port);
+ }catch (Exception $e){
+ echo $e->getMessage();
+ }
+ }
+
+ public function add($key, $value, $expire=null)
+ {
+ return $this->mc->add($key, $value, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function delete($key)
+ {
+ return $this->mc->delete($key);
+ }
+
+ public function set($key, $value, $expire=null)
+ {
+ return $this->mc->set($key, $value, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function get($key)
+ {
+ return $this->mc->get($key);
+ }
+
+ public function flush()
+ {
+ return $this->mc->flush();
+ }
+}
\ No newline at end of file
diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_mysql.class.php b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_mysql.class.php
new file mode 100644
index 0000000..3d2f153
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_mysql.class.php
@@ -0,0 +1,104 @@
+host = $option->host;
+ $this->port = $option->port;
+ $this->expire = $option->expire;
+ $this->init($option);
+ }
+
+ static public function getInstance($option)
+ {
+ if (is_null(self::$_instance) || isset (self::$_instance)) {
+ self::$_instance = new self($option);
+ }
+ return self::$_instance;
+ }
+
+ public function init($option)
+ {
+ $this->db = Typecho_Db::get();
+ $prefix = $this->db->getPrefix();
+ $table_name = $prefix . 'cache';
+ $sql_detect = "SHOW TABLES LIKE '%" . $table_name . "%'";
+
+ if(count($this->db->fetchAll($sql_detect)) == 0){
+ $this->install_db();
+ }else{
+ // 用访问触发缓存过期
+ $this->db->query($this->db->delete('table.cache')->where('time <= ?', (time() - $this->expire) ));
+ }
+ }
+
+ public function install_db()
+ {
+ $install_sql = '
+DROP TABLE IF EXISTS `%prefix%cache`;
+CREATE TABLE `%prefix%cache` (
+ `key` char(32) NOT NULL,
+ `data` text,
+ `time` bigint(20) DEFAULT NULL,
+ PRIMARY KEY (`key`)
+) ENGINE=MyISAM DEFAULT CHARSET=%charset%';
+
+ $prefix = $this->db->getPrefix();
+ $search = array('%prefix%', '%charset%');
+ $replace = array($prefix, str_replace('UTF-8', 'utf8', Helper::options()->charset));
+ $sql = str_replace($search, $replace, $install_sql);
+ $sqls = explode(';', $sql);
+
+ foreach ($sqls as $sql) {
+ try{
+ $this->db->query($sql);
+ }catch (Typecho_Db_Exception $e){
+ echo $e->getMessage();
+ }
+ }
+ }
+
+ public function add($key, $value, $expire = null)
+ {
+ $this->db->query($this->db->insert('table.cache')->rows(array(
+ 'key' => $key,
+ 'data' => $value,
+ 'time' => time()
+ )));
+ }
+
+ public function delete($key)
+ {
+ return $this->db->query($this->db->delete('table.cache')->where('key = ?', $key));
+ }
+
+ public function set($key, $value, $expire = null)
+ {
+ $this->delete($key);
+ $this->add($key, $value);
+ }
+
+ public function get($key)
+ {
+ $rs = $this->db->fetchRow($this->db->select('*')->from('table.cache')->where('key = ?', $key));
+ if(count($rs) == 0){
+ return false;
+ }else{
+ return $rs['data'];
+ }
+ }
+
+ public function flush()
+ {
+ return $this->db->query($this->db->delete('table.cache'));
+ }
+}
\ No newline at end of file
diff --git a/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_redis.class.php b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_redis.class.php
new file mode 100644
index 0000000..e9d70e8
--- /dev/null
+++ b/server/cn/home/www/IoTgod-www/usr/plugins/TpCache/driver/typecho_redis.class.php
@@ -0,0 +1,59 @@
+host = $option->host;
+ $this->port = $option->port;
+ $this->expire = $option->expire + 0;
+ $this->init($option);
+ }
+
+ static public function getInstance($option) {
+ if (is_null ( self::$_instance ) || isset ( self::$_instance )) {
+ self::$_instance = new self($option);
+ }
+ return self::$_instance;
+ }
+
+ public function init($option)
+ {
+ try{
+ $this->redis = new Redis();
+ $this->redis->connect($this->host, $this->port);
+ }catch (Exception $e){
+ echo $e->getMessage();
+ }
+ }
+
+ public function add($key, $value, $expire=null)
+ {
+ return $this->redis->set($key, $value, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function delete($key)
+ {
+ return $this->redis->delete($key);
+ }
+
+ public function set($key, $value, $expire=null)
+ {
+ return $this->redis->set($key, $value, is_null($expire) ? $this->expire : $expire);
+ }
+
+ public function get($key)
+ {
+ return $this->redis->get($key);
+ }
+
+ public function flush()
+ {
+ return $this->redis->flushDB();
+ }
+}
\ No newline at end of file