From ed231a036589ad2342e867eaf04268f685b4aba1 Mon Sep 17 00:00:00 2001
From: Karson
Date: Tue, 11 Apr 2017 09:34:58 +0800
Subject: [PATCH]
---
extend/.gitignore | 2 -
extend/.htaccess | 1 +
extend/fast/Auth.php | 288 ++++
extend/fast/Date.php | 287 ++++
extend/fast/Form.php | 1201 ++++++++++++++++
extend/fast/Http.php | 190 +++
extend/fast/Menu.php | 166 +++
extend/fast/Pinyin.php | 89 ++
extend/fast/Random.php | 182 +++
extend/fast/Rsa.php | 187 +++
extend/fast/Tree.php | 480 +++++++
extend/fast/payment/Alipay.php | 447 ++++++
extend/fast/payment/Wechat.php | 440 ++++++
extend/fast/service/Alisms.php | 167 +++
extend/fast/service/Easemob.php | 307 ++++
extend/fast/service/Qiniu.php | 187 +++
extend/fast/service/Upyun.php | 572 ++++++++
extend/fast/service/Wechat.php | 213 +++
extend/fast/third/Application.php | 76 +
extend/fast/third/Qq.php | 145 ++
extend/fast/third/Wechat.php | 124 ++
extend/fast/third/Weibo.php | 124 ++
extend/fast/ucenter/client/Client.php | 31 +
.../fast/ucenter/client/uc_client/client.php | 840 +++++++++++
.../ucenter/client/uc_client/control/app.php | 63 +
.../client/uc_client/control/cache.php | 30 +
.../client/uc_client/control/client.php | 817 +++++++++++
.../client/uc_client/control/domain.php | 31 +
.../ucenter/client/uc_client/control/feed.php | 114 ++
.../client/uc_client/control/friend.php | 64 +
.../client/uc_client/control/index.htm | 1 +
.../ucenter/client/uc_client/control/mail.php | 42 +
.../ucenter/client/uc_client/control/pm.php | 463 ++++++
.../ucenter/client/uc_client/control/tag.php | 102 ++
.../ucenter/client/uc_client/control/user.php | 443 ++++++
.../client/uc_client/data/cache/apps.php | 40 +
.../client/uc_client/data/cache/badwords.php | 5 +
.../client/uc_client/data/cache/index.htm | 0
.../client/uc_client/data/cache/settings.php | 32 +
.../ucenter/client/uc_client/data/index.htm | 0
.../fast/ucenter/client/uc_client/index.htm | 1 +
.../ucenter/client/uc_client/lib/db.class.php | 210 +++
.../client/uc_client/lib/dbi.class.php | 200 +++
.../ucenter/client/uc_client/lib/index.htm | 1 +
.../client/uc_client/lib/sendmail.inc.php | 159 +++
.../client/uc_client/lib/uccode.class.php | 174 +++
.../client/uc_client/lib/xml.class.php | 129 ++
.../ucenter/client/uc_client/model/app.php | 40 +
.../ucenter/client/uc_client/model/base.php | 347 +++++
.../ucenter/client/uc_client/model/cache.php | 119 ++
.../ucenter/client/uc_client/model/domain.php | 63 +
.../ucenter/client/uc_client/model/friend.php | 148 ++
.../ucenter/client/uc_client/model/index.htm | 1 +
.../ucenter/client/uc_client/model/mail.php | 181 +++
.../ucenter/client/uc_client/model/misc.php | 198 +++
.../ucenter/client/uc_client/model/note.php | 230 +++
.../ucenter/client/uc_client/model/pm.php | 1261 +++++++++++++++++
.../ucenter/client/uc_client/model/tag.php | 84 ++
.../ucenter/client/uc_client/model/user.php | 439 ++++++
extend/fast/ucenter/common/Functions.php | 98 ++
extend/fast/ucenter/common/XML.php | 129 ++
61 files changed, 13203 insertions(+), 2 deletions(-)
delete mode 100755 extend/.gitignore
create mode 100644 extend/.htaccess
create mode 100644 extend/fast/Auth.php
create mode 100644 extend/fast/Date.php
create mode 100644 extend/fast/Form.php
create mode 100644 extend/fast/Http.php
create mode 100644 extend/fast/Menu.php
create mode 100644 extend/fast/Pinyin.php
create mode 100644 extend/fast/Random.php
create mode 100644 extend/fast/Rsa.php
create mode 100644 extend/fast/Tree.php
create mode 100644 extend/fast/payment/Alipay.php
create mode 100644 extend/fast/payment/Wechat.php
create mode 100644 extend/fast/service/Alisms.php
create mode 100644 extend/fast/service/Easemob.php
create mode 100644 extend/fast/service/Qiniu.php
create mode 100644 extend/fast/service/Upyun.php
create mode 100644 extend/fast/service/Wechat.php
create mode 100644 extend/fast/third/Application.php
create mode 100644 extend/fast/third/Qq.php
create mode 100644 extend/fast/third/Wechat.php
create mode 100644 extend/fast/third/Weibo.php
create mode 100644 extend/fast/ucenter/client/Client.php
create mode 100644 extend/fast/ucenter/client/uc_client/client.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/app.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/cache.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/client.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/domain.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/feed.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/friend.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/control/mail.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/pm.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/tag.php
create mode 100644 extend/fast/ucenter/client/uc_client/control/user.php
create mode 100644 extend/fast/ucenter/client/uc_client/data/cache/apps.php
create mode 100644 extend/fast/ucenter/client/uc_client/data/cache/badwords.php
create mode 100644 extend/fast/ucenter/client/uc_client/data/cache/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/data/cache/settings.php
create mode 100644 extend/fast/ucenter/client/uc_client/data/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/lib/db.class.php
create mode 100644 extend/fast/ucenter/client/uc_client/lib/dbi.class.php
create mode 100644 extend/fast/ucenter/client/uc_client/lib/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php
create mode 100644 extend/fast/ucenter/client/uc_client/lib/uccode.class.php
create mode 100644 extend/fast/ucenter/client/uc_client/lib/xml.class.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/app.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/base.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/cache.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/domain.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/friend.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/index.htm
create mode 100644 extend/fast/ucenter/client/uc_client/model/mail.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/misc.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/note.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/pm.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/tag.php
create mode 100644 extend/fast/ucenter/client/uc_client/model/user.php
create mode 100644 extend/fast/ucenter/common/Functions.php
create mode 100644 extend/fast/ucenter/common/XML.php
diff --git a/extend/.gitignore b/extend/.gitignore
deleted file mode 100755
index a3a0c8b5..00000000
--- a/extend/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
\ No newline at end of file
diff --git a/extend/.htaccess b/extend/.htaccess
new file mode 100644
index 00000000..3418e55a
--- /dev/null
+++ b/extend/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/extend/fast/Auth.php b/extend/fast/Auth.php
new file mode 100644
index 00000000..2d7d677f
--- /dev/null
+++ b/extend/fast/Auth.php
@@ -0,0 +1,288 @@
+
+// +----------------------------------------------------------------------
+// | 修改者: anuo (本权限类在原3.2.3的基础上修改过来的)
+// +----------------------------------------------------------------------
+
+namespace fast;
+
+use think\Db;
+use think\Config;
+use think\Session;
+use think\Request;
+use think\Loader;
+
+/**
+ * 权限认证类
+ * 功能特性:
+ * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
+ * $auth=new Auth(); $auth->check('规则名称','用户id')
+ * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
+ * $auth=new Auth(); $auth->check('规则1,规则2','用户id','and')
+ * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
+ * 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限)
+ * 4,支持规则表达式。
+ * 在think_auth_rule 表中定义一条规则,condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100
+ * 表示用户的分数在5-100之间时这条规则才会通过。
+ */
+class Auth
+{
+
+ /**
+ * @var object 对象实例
+ */
+ protected static $instance;
+
+ /**
+ * 当前请求实例
+ * @var Request
+ */
+ protected $request;
+ //默认配置
+ protected $config = [
+ 'auth_on' => 1, // 权限开关
+ 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。
+ 'auth_group' => 'auth_group', // 用户组数据表名
+ 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表
+ 'auth_rule' => 'auth_rule', // 权限规则表
+ 'auth_user' => 'user', // 用户信息表
+ ];
+
+ /**
+ * 类架构函数
+ * Auth constructor.
+ */
+ public function __construct()
+ {
+ if ($auth = Config::get('auth'))
+ {
+ $this->config = array_merge($this->config, $auth);
+ }
+ // 初始化request
+ $this->request = Request::instance();
+ }
+
+ /**
+ * 初始化
+ * @access public
+ * @param array $options 参数
+ * @return Auth
+ */
+ public static function instance($options = [])
+ {
+ if (is_null(self::$instance))
+ {
+ self::$instance = new static($options);
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * 检查权限
+ * @param $name string|array 需要验证的规则列表,支持逗号分隔的权限规则或索引数组
+ * @param $uid int 认证用户的id
+ * @param string $relation 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
+ * @param string $mode 执行验证的模式,可分为url,normal
+ * @return bool 通过验证返回true;失败返回false
+ */
+ public function check($name, $uid, $relation = 'or', $mode = 'url')
+ {
+ if (!$this->config['auth_on'])
+ {
+ return true;
+ }
+ // 获取用户需要验证的所有有效规则列表
+ $rulelist = $this->getRuleList($uid);
+ if (in_array('*', $rulelist))
+ return true;
+
+ if (is_string($name))
+ {
+ $name = strtolower($name);
+ if (strpos($name, ',') !== false)
+ {
+ $name = explode(',', $name);
+ }
+ else
+ {
+ $name = [$name];
+ }
+ }
+ $list = []; //保存验证通过的规则名
+ if ('url' == $mode)
+ {
+ $REQUEST = unserialize(strtolower(serialize($this->request->param())));
+ }
+ foreach ($rulelist as $rule)
+ {
+ $query = preg_replace('/^.+\?/U', '', $rule);
+ if ('url' == $mode && $query != $rule)
+ {
+ parse_str($query, $param); //解析规则中的param
+ $intersect = array_intersect_assoc($REQUEST, $param);
+ $rule = preg_replace('/\?.*$/U', '', $rule);
+ if (in_array($rule, $name) && $intersect == $param)
+ {
+ //如果节点相符且url参数满足
+ $list[] = $rule;
+ }
+ }
+ else
+ {
+ if (in_array($rule, $name))
+ {
+ $list[] = $rule;
+ }
+ }
+ }
+ if ('or' == $relation && !empty($list))
+ {
+ return true;
+ }
+ $diff = array_diff($name, $list);
+ if ('and' == $relation && empty($diff))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * 根据用户id获取用户组,返回值为数组
+ * @param $uid int 用户id
+ * @return array 用户所属的用户组 array(
+ * array('uid'=>'用户id','group_id'=>'用户组id','name'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'),
+ * ...)
+ */
+ public function getGroups($uid)
+ {
+ static $groups = [];
+ if (isset($groups[$uid]))
+ {
+ return $groups[$uid];
+ }
+ // 转换表名
+ $auth_group_access = Loader::parseName($this->config['auth_group_access'], 1);
+ $auth_group = Loader::parseName($this->config['auth_group'], 1);
+ // 执行查询
+ $user_groups = Db::view($auth_group_access, 'uid,group_id')
+ ->view($auth_group, 'id,pid,name,rules', "{$auth_group_access}.group_id={$auth_group}.id", 'LEFT')
+ ->where("{$auth_group_access}.uid='{$uid}' and {$auth_group}.status='normal'")
+ ->select();
+ $groups[$uid] = $user_groups ? : [];
+
+ return $groups[$uid];
+ }
+
+ /**
+ * 获得权限规则列表
+ * @param integer $uid 用户id
+ * @return array
+ */
+ public function getRuleList($uid)
+ {
+ static $_rulelist = []; //保存用户验证通过的权限列表
+ if (isset($_rulelist[$uid]))
+ {
+ return $_rulelist[$uid];
+ }
+ if (2 == $this->config['auth_type'] && Session::has('_rule_list_' . $uid))
+ {
+ return Session::get('_rule_list_' . $uid);
+ }
+
+ // 读取用户规则节点
+ $ids = $this->getRuleIds($uid);
+ if (empty($ids))
+ {
+ $_rulelist[$uid] = [];
+ return [];
+ }
+
+ // 筛选条件
+ $where = [
+ 'status' => 'normal'
+ ];
+ if (!in_array('*', $ids))
+ {
+ $where['id'] = ['in', $ids];
+ }
+ //读取用户组所有权限规则
+ $rules = Db::name($this->config['auth_rule'])->where($where)->field('id,condition,name,ismenu')->select();
+ //循环规则,判断结果。
+ $rulelist = []; //
+ foreach ($rules as $rule)
+ {
+ //超级管理员无需验证condition
+ if (!empty($rule['condition']) && !in_array('*', $ids))
+ {
+ //根据condition进行验证
+ $user = $this->getUserInfo($uid); //获取用户信息,一维数组
+ $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
+ @(eval('$condition=(' . $command . ');'));
+ if ($condition)
+ {
+ $rulelist[$rule['id']] = strtolower($rule['name']);
+ }
+ }
+ else
+ {
+ //只要存在就记录
+ $rulelist[$rule['id']] = strtolower($rule['name']);
+ }
+ }
+ $_rulelist[$uid] = $rulelist;
+
+ //登录验证则需要保存规则列表
+ if (2 == $this->config['auth_type'])
+ {
+ //规则列表结果保存到session
+ Session::set('_rule_list_' . $uid, $rulelist);
+ }
+ return array_unique($rulelist);
+ }
+
+ public function getRuleIds($uid)
+ {
+ //读取用户所属用户组
+ $groups = $this->getGroups($uid);
+ $ids = []; //保存用户所属用户组设置的所有权限规则id
+ foreach ($groups as $g)
+ {
+ $ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
+ }
+ $ids = array_unique($ids);
+ return $ids;
+ }
+
+ /**
+ * 获得用户资料
+ * @param $uid
+ * @return mixed
+ */
+ protected function getUserInfo($uid)
+ {
+ static $user_info = [];
+
+ $user = Db::name($this->config['auth_user']);
+ // 获取用户表主键
+ $_pk = is_string($user->getPk()) ? $user->getPk() : 'uid';
+ if (!isset($user_info[$uid]))
+ {
+ $user_info[$uid] = $user->where($_pk, $uid)->find();
+ }
+
+ return $user_info[$uid];
+ }
+
+}
diff --git a/extend/fast/Date.php b/extend/fast/Date.php
new file mode 100644
index 00000000..8e84d044
--- /dev/null
+++ b/extend/fast/Date.php
@@ -0,0 +1,287 @@
+.
+ *
+ * @param string $remote timezone that to find the offset of
+ * @param string $local timezone used as the baseline
+ * @param mixed $now UNIX timestamp or date string
+ * @return integer
+ */
+ public static function offset($remote, $local = NULL, $now = NULL)
+ {
+ if ($local === NULL)
+ {
+ // Use the default timezone
+ $local = date_default_timezone_get();
+ }
+ if (is_int($now))
+ {
+ // Convert the timestamp into a string
+ $now = date(DateTime::RFC2822, $now);
+ }
+ // Create timezone objects
+ $zone_remote = new DateTimeZone($remote);
+ $zone_local = new DateTimeZone($local);
+ // Create date objects from timezones
+ $time_remote = new DateTime($now, $zone_remote);
+ $time_local = new DateTime($now, $zone_local);
+ // Find the offset
+ $offset = $zone_remote->getOffset($time_remote) - $zone_local->getOffset($time_local);
+ return $offset;
+ }
+
+ /**
+ * 计算两个时间戳之间相差的时间
+ *
+ * $span = self::span(60, 182, 'minutes,seconds'); // array('minutes' => 2, 'seconds' => 2)
+ * $span = self::span(60, 182, 'minutes'); // 2
+ *
+ * @param int $remote timestamp to find the span of
+ * @param int $local timestamp to use as the baseline
+ * @param string $output formatting string
+ * @return string when only a single output is requested
+ * @return array associative list of all outputs requested
+ */
+ public static function span($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
+ {
+ // Normalize output
+ $output = trim(strtolower((string) $output));
+ if (!$output)
+ {
+ // Invalid output
+ return FALSE;
+ }
+ // Array with the output formats
+ $output = preg_split('/[^a-z]+/', $output);
+ // Convert the list of outputs to an associative array
+ $output = array_combine($output, array_fill(0, count($output), 0));
+ // Make the output values into keys
+ extract(array_flip($output), EXTR_SKIP);
+ if ($local === NULL)
+ {
+ // Calculate the span from the current time
+ $local = time();
+ }
+ // Calculate timespan (seconds)
+ $timespan = abs($remote - $local);
+ if (isset($output['years']))
+ {
+ $timespan -= self::YEAR * ($output['years'] = (int) floor($timespan / self::YEAR));
+ }
+ if (isset($output['months']))
+ {
+ $timespan -= self::MONTH * ($output['months'] = (int) floor($timespan / self::MONTH));
+ }
+ if (isset($output['weeks']))
+ {
+ $timespan -= self::WEEK * ($output['weeks'] = (int) floor($timespan / self::WEEK));
+ }
+ if (isset($output['days']))
+ {
+ $timespan -= self::DAY * ($output['days'] = (int) floor($timespan / self::DAY));
+ }
+ if (isset($output['hours']))
+ {
+ $timespan -= self::HOUR * ($output['hours'] = (int) floor($timespan / self::HOUR));
+ }
+ if (isset($output['minutes']))
+ {
+ $timespan -= self::MINUTE * ($output['minutes'] = (int) floor($timespan / self::MINUTE));
+ }
+ // Seconds ago, 1
+ if (isset($output['seconds']))
+ {
+ $output['seconds'] = $timespan;
+ }
+ if (count($output) === 1)
+ {
+ // Only a single output was requested, return it
+ return array_pop($output);
+ }
+ // Return array
+ return $output;
+ }
+
+ /**
+ * 格式化 UNIX 时间戳为人易读的字符串
+ *
+ * @param int Unix 时间戳
+ * @param mixed $local 本地时间
+ *
+ * @return string 格式化的日期字符串
+ */
+ public static function human($remote, $local = null)
+ {
+ $timediff = (is_null($local) || $local ? time() : $local) - $remote;
+ $chunks = array(
+ array(60 * 60 * 24 * 365, 'year'),
+ array(60 * 60 * 24 * 30, 'month'),
+ array(60 * 60 * 24 * 7, 'week'),
+ array(60 * 60 * 24, 'day'),
+ array(60 * 60, 'hour'),
+ array(60, 'minute'),
+ array(1, 'second')
+ );
+
+ for ($i = 0, $j = count($chunks); $i < $j; $i++)
+ {
+ $seconds = $chunks[$i][0];
+ $name = $chunks[$i][1];
+ if (($count = floor($timediff / $seconds)) != 0)
+ {
+ break;
+ }
+ }
+ return __("%d {$name}%s ago", $count, ($count > 1 ? 's' : ''));
+ }
+
+ /**
+ * 判断Unix时间是否满足Cron指定的执行条件
+ *
+ * @param string $cron Crontab格式
+ * @param string $time 时间,默认为当前时间
+ * @return boolean
+ */
+ public static function cron($cron, $time = null)
+ {
+ $time = is_null($time) ? time() : $time;
+ $cron_parts = explode(' ', $cron);
+ if (count($cron_parts) != 5)
+ {
+ return false;
+ }
+ list($min, $hour, $day, $mon, $week) = explode(' ', $cron);
+ $to_check = array('min' => 'i', 'hour' => 'G', 'day' => 'j', 'mon' => 'n', 'week' => 'w');
+ $ranges = array(
+ 'min' => '0-59',
+ 'hour' => '0-23',
+ 'day' => '1-31',
+ 'mon' => '1-12',
+ 'week' => '0-6',
+ );
+
+ foreach ($to_check as $part => $c)
+ {
+ $val = $$part;
+ $values = [];
+ if (strpos($val, '/') !== false)
+ {
+ //Get the range and step
+ list($range, $steps) = explode('/', $val);
+ //Now get the start and stop
+ if ($range == '*')
+ {
+ $range = $ranges[$part];
+ }
+ list($start, $stop) = explode('-', $range);
+ for ($i = $start; $i <= $stop; $i = $i + $steps)
+ {
+ $values[] = $i;
+ }
+ }
+ else
+ {
+ $k = explode(',', $val);
+ foreach ($k as $v)
+ {
+ if (strpos($v, '-') !== false)
+ {
+ list($start, $stop) = explode('-', $v);
+
+ for ($i = $start; $i <= $stop; $i++)
+ {
+ $values[] = $i;
+ }
+ }
+ else
+ {
+ $values[] = $v;
+ }
+ }
+ }
+ if (!in_array(date($c, $time), $values) and ( strval($val) != '*'))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 获取一个基于时间偏移的Unix时间戳
+ *
+ * @param string $type 时间类型,默认为day,可选minute,hour,day,week,month,quarter,year
+ * @param int $offset 时间偏移量 默认为0,正数表示当前type之后,负数表示当前type之前
+ * @param string $position 时间的开始或结束,默认为begin,可选前(begin,start,first,front),end
+ * @param int $year 基准年,默认为null,即以当前年为基准
+ * @param int $month 基准月,默认为null,即以当前月为基准
+ * @param int $day 基准天,默认为null,即以当前天为基准
+ * @param int $hour 基准小时,默认为null,即以当前年小时基准
+ * @param int $minute 基准分钟,默认为null,即以当前分钟为基准
+ * @return int 处理后的Unix时间戳
+ */
+ public static function unixtime($type = 'day', $offset = 0, $position = 'begin', $year = null, $month = null, $day = null, $hour = null, $minute = null)
+ {
+ $year = is_null($year) ? date('Y') : $year;
+ $month = is_null($month) ? date('m') : $month;
+ $day = is_null($day) ? date('d') : $day;
+ $hour = is_null($hour) ? date('H') : $hour;
+ $minute = is_null($minute) ? date('i') : $minute;
+ $position = in_array($position, array('begin', 'start', 'first', 'front'));
+
+ switch ($type)
+ {
+ case 'minute':
+ $time = $position ? mktime($hour, $minute + $offset, 0, $month, $day, $year) : mktime($hour, $minute + $offset, 59, $month, $day, $year);
+ break;
+ case 'hour':
+ $time = $position ? mktime($hour + $offset, 0, 0, $month, $day, $year) : mktime($hour + $offset, 59, 59, $month, $day, $year);
+ break;
+ case 'day':
+ $time = $position ? mktime(0, 0, 0, $month, $day + $offset, $year) : mktime(23, 59, 59, $month, $day + $offset, $year);
+ break;
+ case 'week':
+ $time = $position ?
+ mktime(0, 0, 0, $month, $day - date("w", mktime(0, 0, 0, $month, $day, $year)) + 1 - 7 * (-$offset), $year) :
+ mktime(23, 59, 59, $month, $day - date("w", mktime(0, 0, 0, $month, $day, $year)) + 7 - 7 * (-$offset), $year);
+ break;
+ case 'month':
+ $time = $position ? mktime(0, 0, 0, $month + $offset, 1, $year) : mktime(23, 59, 59, $month + $offset, get_month_days($month + $offset, $year), $year);
+ break;
+ case 'quarter':
+ $time = $position ?
+ mktime(0, 0, 0, 1 + ((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) - 1) * 3, 1, $year) :
+ mktime(23, 59, 59, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, get_month_days((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $year), $year);
+ break;
+ case 'year':
+ $time = $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
+ break;
+ default:
+ $time = mktime($hour, $minute, 0, $month, $day, $year);
+ break;
+ }
+ return $time;
+ }
+
+}
diff --git a/extend/fast/Form.php b/extend/fast/Form.php
new file mode 100644
index 00000000..af877e2e
--- /dev/null
+++ b/extend/fast/Form.php
@@ -0,0 +1,1201 @@
+ '__token__');
+
+ /**
+ * The current model instance for the form.
+ *
+ * @var mixed
+ */
+ protected $model;
+
+ /**
+ * An array of label names we've created.
+ *
+ * @var array
+ */
+ protected $labels = array();
+
+ /**
+ * The reserved form open attributes.
+ *
+ * @var array
+ */
+ protected $reserved = array('method', 'url', 'route', 'action', 'files');
+
+ /**
+ * The form methods that should be spoofed, in uppercase.
+ *
+ * @var array
+ */
+ protected $spoofedMethods = array('DELETE', 'PATCH', 'PUT');
+
+ /**
+ * The types of inputs to not fill values on by default.
+ *
+ * @var array
+ */
+ protected $skipValueTypes = array('file', 'password', 'checkbox', 'radio');
+ protected static $instance;
+
+ /**
+ * Create a new form builder instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+
+ }
+
+ public static function instance($options = [])
+ {
+ if (is_null(self::$instance))
+ {
+ self::$instance = new static($options);
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Open up a new HTML form.
+ *
+ * @param array $options
+ * @return string
+ */
+ public function open(array $options = array())
+ {
+ $method = array_get($options, 'method', 'post');
+
+ // We need to extract the proper method from the attributes. If the method is
+ // something other than GET or POST we'll use POST since we will spoof the
+ // actual method since forms don't support the reserved methods in HTML.
+ $attributes['method'] = $this->getMethod($method);
+
+ $attributes['action'] = array_get($options, 'action', '');
+
+ $attributes['accept-charset'] = 'UTF-8';
+
+ // If the method is PUT, PATCH or DELETE we will need to add a spoofer hidden
+ // field that will instruct the Symfony request to pretend the method is a
+ // different method than it actually is, for convenience from the forms.
+ $append = $this->getAppendage($method);
+
+ if (isset($options['files']) && $options['files'])
+ {
+ $options['enctype'] = 'multipart/form-data';
+ }
+
+ // Finally we're ready to create the final form HTML field. We will attribute
+ // format the array of attributes. We will also add on the appendage which
+ // is used to spoof requests for this PUT, PATCH, etc. methods on forms.
+ $attributes = array_merge(
+ $attributes, array_except($options, $this->reserved)
+ );
+ // Finally, we will concatenate all of the attributes into a single string so
+ // we can build out the final form open statement. We'll also append on an
+ // extra value for the hidden _method field if it's needed for the form.
+ $attributes = $this->attributes($attributes);
+
+ return '';
+ }
+
+ /**
+ * Generate a hidden field with the current CSRF token.
+ *
+ * @return string
+ */
+ public function token($name = '__token__', $type = 'md5')
+ {
+ if (function_exists('token'))
+ {
+ return token($name, $type);
+ }
+
+ return '';
+ }
+
+ /**
+ * Create a form label element.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function label($name, $value = null, $options = array())
+ {
+ $this->labels[] = $name;
+
+ $options = $this->attributes($options);
+
+ $value = e($this->formatLabel($name, $value));
+
+ return '';
+ }
+
+ /**
+ * Format the label value.
+ *
+ * @param string $name
+ * @param string|null $value
+ * @return string
+ */
+ protected function formatLabel($name, $value)
+ {
+ return $value ? : ucwords(str_replace('_', ' ', $name));
+ }
+
+ /**
+ * Create a form input field.
+ *
+ * @param string $type
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function input($type, $name, $value = null, $options = array())
+ {
+ if (!isset($options['name']))
+ $options['name'] = $name;
+
+ // We will get the appropriate value for the given field. We will look for the
+ // value in the session for the value in the old input data then we'll look
+ // in the model instance if one is set. Otherwise we will just use empty.
+ $id = $this->getIdAttribute($name, $options);
+
+ if (!in_array($type, $this->skipValueTypes))
+ {
+ $value = $this->getValueAttribute($name, $value);
+ }
+
+ // Once we have the type, value, and ID we can merge them into the rest of the
+ // attributes array so we can convert them into their HTML attribute format
+ // when creating the HTML element. Then, we will return the entire input.
+ $merge = compact('type', 'value', 'id');
+
+ $options = array_merge($options, $merge);
+
+ return 'attributes($options) . '>';
+ }
+
+ /**
+ * Create a text input field.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function text($name, $value = null, $options = array())
+ {
+ return $this->input('text', $name, $value, $options);
+ }
+
+ /**
+ * Create a password input field.
+ *
+ * @param string $name
+ * @param array $options
+ * @return string
+ */
+ public function password($name, $options = array())
+ {
+ return $this->input('password', $name, '', $options);
+ }
+
+ /**
+ * Create a hidden input field.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function hidden($name, $value = null, $options = array())
+ {
+ return $this->input('hidden', $name, $value, $options);
+ }
+
+ /**
+ * Create an e-mail input field.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function email($name, $value = null, $options = array())
+ {
+ return $this->input('email', $name, $value, $options);
+ }
+
+ /**
+ * Create a url input field.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function url($name, $value = null, $options = array())
+ {
+ return $this->input('url', $name, $value, $options);
+ }
+
+ /**
+ * Create a file input field.
+ *
+ * @param string $name
+ * @param array $options
+ * @return string
+ */
+ public function file($name, $options = array())
+ {
+ return $this->input('file', $name, null, $options);
+ }
+
+ /**
+ * Create a textarea input field.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function textarea($name, $value = null, $options = array())
+ {
+ if (!isset($options['name']))
+ $options['name'] = $name;
+
+ // Next we will look for the rows and cols attributes, as each of these are put
+ // on the textarea element definition. If they are not present, we will just
+ // assume some sane default values for these attributes for the developer.
+ $options = $this->setTextAreaSize($options);
+
+ $options['id'] = $this->getIdAttribute($name, $options);
+
+ $value = (string) $this->getValueAttribute($name, $value);
+
+ unset($options['size']);
+
+ // Next we will convert the attributes into a string form. Also we have removed
+ // the size attribute, as it was merely a short-cut for the rows and cols on
+ // the element. Then we'll create the final textarea elements HTML for us.
+ $options = $this->attributes($options);
+
+ return '';
+ }
+
+ /**
+ * Set the text area size on the attributes.
+ *
+ * @param array $options
+ * @return array
+ */
+ protected function setTextAreaSize($options)
+ {
+ if (isset($options['size']))
+ {
+ return $this->setQuickTextAreaSize($options);
+ }
+
+ // If the "size" attribute was not specified, we will just look for the regular
+ // columns and rows attributes, using sane defaults if these do not exist on
+ // the attributes array. We'll then return this entire options array back.
+ $cols = array_get($options, 'cols', 50);
+
+ $rows = array_get($options, 'rows', 10);
+
+ return array_merge($options, compact('cols', 'rows'));
+ }
+
+ /**
+ * Set the text area size using the quick "size" attribute.
+ *
+ * @param array $options
+ * @return array
+ */
+ protected function setQuickTextAreaSize($options)
+ {
+ $segments = explode('x', $options['size']);
+
+ return array_merge($options, array('cols' => $segments[0], 'rows' => $segments[1]));
+ }
+
+ /**
+ * Create a select box field.
+ *
+ * @param string $name
+ * @param array $list
+ * @param string $selected
+ * @param array $options
+ * @return string
+ */
+ public function select($name, $list = array(), $selected = null, $options = array())
+ {
+ // When building a select box the "value" attribute is really the selected one
+ // so we will use that when checking the model or session for a value which
+ // should provide a convenient method of re-populating the forms on post.
+ $selected = $this->getValueAttribute($name, $selected);
+
+ $options['id'] = $this->getIdAttribute($name, $options);
+
+ if (!isset($options['name']))
+ $options['name'] = $name;
+
+ // We will simply loop through the options and build an HTML value for each of
+ // them until we have an array of HTML declarations. Then we will join them
+ // all together into one single HTML element that can be put on the form.
+ $html = array();
+
+ foreach ($list as $value => $display)
+ {
+ $html[] = $this->getSelectOption($display, $value, $selected);
+ }
+
+ // Once we have all of this HTML, we can join this into a single element after
+ // formatting the attributes into an HTML "attributes" string, then we will
+ // build out a final select statement, which will contain all the values.
+ $options = $this->attributes($options);
+
+ $list = implode('', $html);
+
+ return "";
+ }
+
+ /**
+ * Create a select range field.
+ *
+ * @param string $name
+ * @param string $begin
+ * @param string $end
+ * @param string $selected
+ * @param array $options
+ * @return string
+ */
+ public function selectRange($name, $begin, $end, $selected = null, $options = array())
+ {
+
+ $range = array_combine($range = range($begin, $end), $range);
+
+ return $this->select($name, $range, $selected, $options);
+ }
+
+ /**
+ * Create a select year field.
+ *
+ * @param string $name
+ * @param string $begin
+ * @param string $end
+ * @param string $selected
+ * @param array $options
+ * @return string
+ */
+ public function selectYear()
+ {
+ return call_user_func_array(array($this, 'selectRange'), func_get_args());
+ }
+
+ /**
+ * Create a select month field.
+ *
+ * @param string $name
+ * @param string $selected
+ * @param array $options
+ * @param string $format
+ * @return string
+ */
+ public function selectMonth($name, $selected = null, $options = array(), $format = '%m')
+ {
+ $months = array();
+
+ foreach (range(1, 12) as $month)
+ {
+ $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
+ }
+
+ return $this->select($name, $months, $selected, $options);
+ }
+
+ /**
+ * Get the select option for the given value.
+ *
+ * @param string $display
+ * @param string $value
+ * @param string $selected
+ * @return string
+ */
+ public function getSelectOption($display, $value, $selected)
+ {
+ if (is_array($display))
+ {
+ return $this->optionGroup($display, $value, $selected);
+ }
+
+ return $this->option($display, $value, $selected);
+ }
+
+ /**
+ * Create an option group form element.
+ *
+ * @param array $list
+ * @param string $label
+ * @param string $selected
+ * @return string
+ */
+ protected function optionGroup($list, $label, $selected)
+ {
+ $html = array();
+
+ foreach ($list as $value => $display)
+ {
+ $html[] = $this->option($display, $value, $selected);
+ }
+
+ return '';
+ }
+
+ /**
+ * Create a select element option.
+ *
+ * @param string $display
+ * @param string $value
+ * @param string $selected
+ * @return string
+ */
+ protected function option($display, $value, $selected)
+ {
+ $selected = $this->getSelectedValue($value, $selected);
+
+ $options = array('value' => e($value), 'selected' => $selected);
+
+ return '';
+ }
+
+ /**
+ * Determine if the value is selected.
+ *
+ * @param string $value
+ * @param string $selected
+ * @return string
+ */
+ protected function getSelectedValue($value, $selected)
+ {
+ if (is_array($selected))
+ {
+ return in_array($value, $selected) ? 'selected' : null;
+ }
+
+ return ((string) $value == (string) $selected) ? 'selected' : null;
+ }
+
+ /**
+ * Create a checkbox input field.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @param array $options
+ * @return string
+ */
+ public function checkbox($name, $value = 1, $checked = null, $options = array())
+ {
+ return $this->checkable('checkbox', $name, $value, $checked, $options);
+ }
+
+ /**
+ * Create a radio button input field.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @param array $options
+ * @return string
+ */
+ public function radio($name, $value = null, $checked = null, $options = array())
+ {
+ if (is_null($value))
+ $value = $name;
+
+ return $this->checkable('radio', $name, $value, $checked, $options);
+ }
+
+ /**
+ * Create a checkable input field.
+ *
+ * @param string $type
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @param array $options
+ * @return string
+ */
+ protected function checkable($type, $name, $value, $checked, $options)
+ {
+ $checked = $this->getCheckedState($type, $name, $value, $checked);
+
+ if ($checked)
+ $options['checked'] = 'checked';
+
+ return $this->input($type, $name, $value, $options);
+ }
+
+ /**
+ * Get the check state for a checkable input.
+ *
+ * @param string $type
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @return bool
+ */
+ protected function getCheckedState($type, $name, $value, $checked)
+ {
+ switch ($type)
+ {
+ case 'checkbox':
+ return $this->getCheckboxCheckedState($name, $value, $checked);
+
+ case 'radio':
+ return $this->getRadioCheckedState($name, $value, $checked);
+
+ default:
+ return $this->getValueAttribute($name) == $value;
+ }
+ }
+
+ /**
+ * Get the check state for a checkbox input.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @return bool
+ */
+ protected function getCheckboxCheckedState($name, $value, $checked)
+ {
+ if (isset($this->session) && !$this->oldInputIsEmpty() && is_null($this->old($name)))
+ return false;
+
+ if ($this->missingOldAndModel($name))
+ return $checked;
+
+ $posted = $this->getValueAttribute($name);
+
+ return is_array($posted) ? in_array($value, $posted) : (bool) $posted;
+ }
+
+ /**
+ * Get the check state for a radio input.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param bool $checked
+ * @return bool
+ */
+ protected function getRadioCheckedState($name, $value, $checked)
+ {
+ if ($this->missingOldAndModel($name))
+ return $checked;
+
+ return $this->getValueAttribute($name) == $value;
+ }
+
+ /**
+ * Determine if old input or model input exists for a key.
+ *
+ * @param string $name
+ * @return bool
+ */
+ protected function missingOldAndModel($name)
+ {
+ return (is_null($this->old($name)) && is_null($this->getModelValueAttribute($name)));
+ }
+
+ /**
+ * Create a HTML reset input element.
+ *
+ * @param string $value
+ * @param array $attributes
+ * @return string
+ */
+ public function reset($value, $attributes = array())
+ {
+ return $this->input('reset', null, $value, $attributes);
+ }
+
+ /**
+ * Create a HTML image input element.
+ *
+ * @param string $url
+ * @param string $name
+ * @param array $attributes
+ * @return string
+ */
+ public function image($url, $name = null, $attributes = array())
+ {
+ $attributes['src'] = $url;
+
+ return $this->input('image', $name, null, $attributes);
+ }
+
+ /**
+ * Create a submit button element.
+ *
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function submit($value = null, $options = array())
+ {
+ return $this->input('submit', null, $value, $options);
+ }
+
+ /**
+ * Create a button element.
+ *
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function button($value = null, $options = array())
+ {
+ if (!array_key_exists('type', $options))
+ {
+ $options['type'] = 'button';
+ }
+
+ return '';
+ }
+
+ /**
+ * Parse the form action method.
+ *
+ * @param string $method
+ * @return string
+ */
+ protected function getMethod($method)
+ {
+ $method = strtoupper($method);
+
+ return $method != 'GET' ? 'POST' : $method;
+ }
+
+ /**
+ * Get the form action from the options.
+ *
+ * @param array $options
+ * @return string
+ */
+ /* protected function getAction(array $options)
+ {
+ // We will also check for a "route" or "action" parameter on the array so that
+ // developers can easily specify a route or controller action when creating
+ // a form providing a convenient interface for creating the form actions.
+ if (isset($options['url']))
+ {
+ return $this->getUrlAction($options['url']);
+ }
+
+ if (isset($options['route']))
+ {
+ return $this->getRouteAction($options['route']);
+ }
+
+ // If an action is available, we are attempting to open a form to a controller
+ // action route. So, we will use the URL generator to get the path to these
+ // actions and return them from the method. Otherwise, we'll use current.
+ elseif (isset($options['action']))
+ {
+ return $this->getControllerAction($options['action']);
+ }
+
+ return $this->url->current();
+ } */
+
+ /**
+ * Get the action for a "url" option.
+ *
+ * @param array|string $options
+ * @return string
+ */
+ /* protected function getUrlAction($options)
+ {
+ if (is_array($options))
+ {
+ return $this->url->to($options[0], array_slice($options, 1));
+ }
+
+ return $this->url->to($options);
+ } */
+
+ /**
+ * Get the action for a "route" option.
+ *
+ * @param array|string $options
+ * @return string
+ */
+ /* protected function getRouteAction($options)
+ {
+ if (is_array($options))
+ {
+ return $this->url->route($options[0], array_slice($options, 1));
+ }
+
+ return $this->url->route($options);
+ } */
+
+ /**
+ * Get the action for an "action" option.
+ *
+ * @param array|string $options
+ * @return string
+ */
+ /* protected function getControllerAction($options)
+ {
+ if (is_array($options))
+ {
+ return $this->url->action($options[0], array_slice($options, 1));
+ }
+
+ return $this->url->action($options);
+ } */
+
+ /**
+ * Get the form appendage for the given method.
+ *
+ * @param string $method
+ * @return string
+ */
+ protected function getAppendage($method)
+ {
+ list($method, $appendage) = array(strtoupper($method), '');
+
+ // If the HTTP method is in this list of spoofed methods, we will attach the
+ // method spoofer hidden input to the form. This allows us to use regular
+ // form to initiate PUT and DELETE requests in addition to the typical.
+ if (in_array($method, $this->spoofedMethods))
+ {
+ $appendage .= $this->hidden('_method', $method);
+ }
+
+
+ // If the method is something other than GET we will go ahead and attach the
+ // CSRF token to the form, as this can't hurt and is convenient to simply
+ // always have available on every form the developers creates for them.
+ if ($method != 'GET')
+ {
+ $appendage .= $this->token(array_get($this->csrfToken, 'name'), array_get($this->csrfToken, 'type'));
+ }
+
+ return $appendage;
+ }
+
+ /**
+ * Get the ID attribute for a field name.
+ *
+ * @param string $name
+ * @param array $attributes
+ * @return string
+ */
+ public function getIdAttribute($name, $attributes)
+ {
+
+ if (array_key_exists('id', $attributes))
+ {
+ return $attributes['id'];
+ }
+
+ if (in_array($name, $this->labels))
+ {
+ return $name;
+ }
+ }
+
+ /**
+ * Get the value that should be assigned to the field.
+ *
+ * @param string $name
+ * @param string $value
+ * @return string
+ */
+ public function getValueAttribute($name, $value = null)
+ {
+ if (is_null($name))
+ return $value;
+
+ if (!is_null($this->old($name)))
+ {
+ return $this->old($name);
+ }
+
+ if (!is_null($value))
+ return $value;
+
+ if (isset($this->model))
+ {
+ return $this->getModelValueAttribute($name);
+ }
+ }
+
+ /**
+ * Get the model value that should be assigned to the field.
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function getModelValueAttribute($name)
+ {
+ if (is_object($this->model))
+ {
+ return object_get($this->model, $this->transformKey($name));
+ }
+ elseif (is_array($this->model))
+ {
+ return array_get($this->model, $this->transformKey($name));
+ }
+ }
+
+ /**
+ * Get a value from the session's old input.
+ *
+ * @param string $name
+ * @return string
+ */
+ public function old($name)
+ {
+ if (isset($this->session))
+ {
+ return $this->session->getOldInput($this->transformKey($name));
+ }
+ }
+
+ /**
+ * Determine if the old input is empty.
+ *
+ * @return bool
+ */
+ public function oldInputIsEmpty()
+ {
+ return (isset($this->session) && count($this->session->getOldInput()) == 0);
+ }
+
+ /**
+ * Transform key from array to dot syntax.
+ *
+ * @param string $key
+ * @return string
+ */
+ protected function transformKey($key)
+ {
+ return str_replace(array('.', '[]', '[', ']'), array('_', '', '.', ''), $key);
+ }
+
+ /**
+ * 数组转换成一个HTML属性字符串。
+ *
+ * @param array $attributes
+ * @return string
+ */
+ public function attributes($attributes)
+ {
+ $html = array();
+ // 假设我们的keys 和 value 是相同的,
+ // 拿HTML“required”属性来说,假设是['required']数组,
+ // 会已 required="required" 拼接起来,而不是用数字keys去拼接
+ foreach ((array) $attributes as $key => $value)
+ {
+ $element = $this->attributeElement($key, $value);
+ if (!is_null($element))
+ $html[] = $element;
+ }
+ return count($html) > 0 ? ' ' . implode(' ', $html) : '';
+ }
+
+ /**
+ * 拼接成一个属性。
+ *
+ * @param string $key
+ * @param string $value
+ * @return string
+ */
+ protected function attributeElement($key, $value)
+ {
+ if (is_numeric($key))
+ $key = $value;
+ if (!is_null($value))
+ return $key . '="' . $value . '"';
+ }
+
+}
+
+class Arr
+{
+
+ /**
+ * Determine whether the given value is array accessible.
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ public static function accessible($value)
+ {
+ return is_array($value) || $value instanceof ArrayAccess;
+ }
+
+ /**
+ * Determine if the given key exists in the provided array.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|int $key
+ * @return bool
+ */
+ public static function exists($array, $key)
+ {
+ if ($array instanceof ArrayAccess)
+ {
+ return $array->offsetExists($key);
+ }
+ return array_key_exists($key, $array);
+ }
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public static function get($array, $key, $default = null)
+ {
+ if (!static::accessible($array))
+ {
+ return $default;
+ }
+ if (is_null($key))
+ {
+ return $array;
+ }
+ if (static::exists($array, $key))
+ {
+ return $array[$key];
+ }
+ foreach (explode('.', $key) as $segment)
+ {
+ if (static::accessible($array) && static::exists($array, $segment))
+ {
+ $array = $array[$segment];
+ }
+ else
+ {
+ return $default;
+ }
+ }
+ return $array;
+ }
+
+ /**
+ * Get all of the given array except for a specified array of items.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return array
+ */
+ public static function except($array, $keys)
+ {
+ static::forget($array, $keys);
+ return $array;
+ }
+
+ /**
+ * Remove one or many array items from a given array using "dot" notation.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return void
+ */
+ public static function forget(&$array, $keys)
+ {
+ $original = &$array;
+ $keys = (array) $keys;
+ if (count($keys) === 0)
+ {
+ return;
+ }
+ foreach ($keys as $key)
+ {
+ // if the exact key exists in the top-level, remove it
+ if (static::exists($array, $key))
+ {
+ unset($array[$key]);
+ continue;
+ }
+ $parts = explode('.', $key);
+ // clean up before each pass
+ $array = &$original;
+ while (count($parts) > 1)
+ {
+ $part = array_shift($parts);
+ if (isset($array[$part]) && is_array($array[$part]))
+ {
+ $array = &$array[$part];
+ }
+ else
+ {
+ continue 2;
+ }
+ }
+ unset($array[array_shift($parts)]);
+ }
+ }
+
+}
+
+if (!function_exists('array_get'))
+{
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ function array_get($array, $key, $default = null)
+ {
+ return Arr::get($array, $key, $default);
+ }
+
+}
+if (!function_exists('e'))
+{
+
+ /**
+ * Escape HTML special characters in a string.
+ *
+ *
+ * @return string
+ */
+ function e($value)
+ {
+ if (is_array($value))
+ {
+ $value = json_encode($value, JSON_UNESCAPED_UNICODE);
+ }
+ return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false);
+ }
+
+}
+if (!function_exists('array_except'))
+{
+
+ /**
+ * Get all of the given array except for a specified array of items.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return array
+ */
+ function array_except($array, $keys)
+ {
+ return Arr::except($array, $keys);
+ }
+
+}
diff --git a/extend/fast/Http.php b/extend/fast/Http.php
new file mode 100644
index 00000000..2206bb53
--- /dev/null
+++ b/extend/fast/Http.php
@@ -0,0 +1,190 @@
+ FALSE,
+ 'errno' => $errno,
+ 'msg' => $err,
+ 'info' => $info,
+ ];
+ }
+ curl_close($ch);
+ return [
+ 'ret' => TRUE,
+ 'msg' => $ret,
+ ];
+ }
+
+ /**
+ * 异步发送一个请求
+ * @param string $url 请求的链接
+ * @param mixed $params 请求的参数
+ * @param string $method 请求的方法
+ * @return boolean TRUE
+ */
+ public static function sendAsyncRequest($url, $params = [], $method = 'POST')
+ {
+ $method = strtoupper($method);
+ $method = $method == 'POST' ? 'POST' : 'GET';
+ //构造传递的参数
+ if (is_array($params))
+ {
+ $post_params = [];
+ foreach ($params as $k => &$v)
+ {
+ if (is_array($v))
+ $v = implode(',', $v);
+ $post_params[] = $k . '=' . urlencode($v);
+ }
+ $post_string = implode('&', $post_params);
+ }else
+ {
+ $post_string = $params;
+ }
+ $parts = parse_url($url);
+ //构造查询的参数
+ if ($method == 'GET' && $post_string)
+ {
+ $parts['query'] = isset($parts['query']) ? $parts['query'] . '&' . $post_string : $post_string;
+ $post_string = '';
+ }
+ $parts['query'] = isset($parts['query']) && $parts['query'] ? '?' . $parts['query'] : '';
+ //发送socket请求,获得连接句柄
+ $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 3);
+ if (!$fp)
+ return FALSE;
+ //设置超时时间
+ stream_set_timeout($fp, 3);
+ $out = "{$method} {$parts['path']}{$parts['query']} HTTP/1.1\r\n";
+ $out.= "Host: {$parts['host']}\r\n";
+ $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
+ $out.= "Content-Length: " . strlen($post_string) . "\r\n";
+ $out.= "Connection: Close\r\n\r\n";
+ if ($post_string !== '')
+ $out .= $post_string;
+ fwrite($fp, $out);
+ //不用关心服务器返回结果
+ //echo fread($fp, 1024);
+ fclose($fp);
+ return TRUE;
+ }
+
+ /**
+ * 发送文件到客户端
+ * @param string $file
+ * @param bool $delaftersend
+ * @param bool $exitaftersend
+ */
+ public static function sendToBrowser($file, $delaftersend = true, $exitaftersend = true)
+ {
+ if (file_exists($file) && is_readable($file))
+ {
+ header('Content-Description: File Transfer');
+ header('Content-Type: application/octet-stream');
+ header('Content-Disposition: attachment;filename = ' . basename($file));
+ header('Content-Transfer-Encoding: binary');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate, post-check = 0, pre-check = 0');
+ header('Pragma: public');
+ header('Content-Length: ' . filesize($file));
+ ob_clean();
+ flush();
+ readfile($file);
+ if ($delaftersend)
+ {
+ unlink($file);
+ }
+ if ($exitaftersend)
+ {
+ exit;
+ }
+ }
+ }
+
+}
diff --git a/extend/fast/Menu.php b/extend/fast/Menu.php
new file mode 100644
index 00000000..62081718
--- /dev/null
+++ b/extend/fast/Menu.php
@@ -0,0 +1,166 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * 单例
+ * @param array $options 参数
+ * @return Menu
+ */
+ public static function instance($options = [])
+ {
+ if (is_null(self::$instance))
+ {
+ self::$instance = new static($options);
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * 导入节点数据
+ * @param array $treearr
+ * @param int $pid
+ * @param string $module
+ */
+ public function import($treearr, $pid = 0, $module = NULL)
+ {
+ $module = is_null($module) ? Config::user('request.modulename') : $module;
+ foreach ($treearr as $key => & $v)
+ {
+ $controller = strtolower($v['controller']) . ($v['childlist'] ? "_folder" : '');
+ $icon = isset($v['icon']) ? $v['icon'] : (stripos($v['name'], '_') !== FALSE ? $v['childlist'] ? 'folder' : 'circle-o' : strtolower($v['name']));
+ $actionkeys = array_keys($v['actionlist']);
+ $action = '-' . ($v['actionlist'] ? reset($actionkeys) : '');
+ $values = array(
+ 'name' => $v['name'],
+ 'weigh' => $key,
+ 'pid' => $pid,
+ 'module' => $module,
+ 'controller' => $controller,
+ 'action' => $action,
+ 'icon' => $icon,
+ 'type' => 'menu',
+ 'status' => 'normal'
+ );
+ $id = Db::table("node")->data($values)->insert();
+ $v['id'] = $id;
+ }
+ unset($v);
+ foreach ($treearr as $k => $v)
+ {
+ if ($v['childlist'])
+ {
+ $this->import($v['childlist'], $v['id'], $module);
+ }
+ else
+ {
+ $i = 0;
+ foreach ($v['actionlist'] as $m => $n)
+ {
+ $values = array(
+ 'name' => $n ? $n : $m,
+ 'weigh' => $i,
+ 'pid' => $v['id'],
+ 'module' => $module,
+ 'controller' => strtolower($v['controller']),
+ 'action' => $m,
+ 'icon' => 'circle-o',
+ 'type' => 'file',
+ 'status' => 'normal'
+ );
+ Db::table("node")->data($values)->insert();
+ $i++;
+ }
+ }
+ }
+ }
+
+ /**
+ * 获取左侧菜单栏
+ *
+ * @param array $params URL对应的badge数据
+ * @return string
+ */
+ public function sidebar($params = [])
+ {
+ $colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
+ $colorNums = count($colorArr);
+ $badgeList = [];
+ // 生成菜单的badge
+ foreach ($params as $k => $v)
+ {
+ if (stripos($k, '/') === false)
+ {
+ $url = '/admin/' . $k;
+ }
+ else
+ {
+ $url = url($k);
+ }
+
+ if (is_array($v))
+ {
+ $nums = isset($v[0]) ? $v[0] : 0;
+ $color = isset($v[1]) ? $v[1] : $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
+ $class = isset($v[2]) ? $v[2] : 'label';
+ }
+ else
+ {
+ $nums = $v;
+ $color = $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
+ $class = 'label';
+ }
+ //必须nums大于0才显示
+ if ($nums)
+ {
+ $badgeList[$url] = '' . $nums . '';
+ }
+ }
+
+ // 读取管理员当前拥有的权限节点
+ $userRule = Auth::instance()->getRuleList();
+
+ $select_id = 0;
+ $dashboard = rtrim(url('dashboard/'), '/');
+ // 必须将结果集转换为数组
+ $ruleList = collection(model('AuthRule')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
+ foreach ($ruleList as $k => &$v)
+ {
+ if (!in_array($v['name'], $userRule))
+ continue;
+ $select_id = $v['name'] == $dashboard ? $v['id'] : $select_id;
+ $v['url'] = $v['name'];
+ $v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
+ }
+ // 构造菜单数据
+ Tree::instance()->init($ruleList);
+ $menu = Tree::instance()->getTreeMenu(0, ' @title @caret @badge @childlist', $select_id, '', 'ul', 'class="treeview-menu"');
+ return $menu;
+ }
+
+}
diff --git a/extend/fast/Pinyin.php b/extend/fast/Pinyin.php
new file mode 100644
index 00000000..be5f4ee2
--- /dev/null
+++ b/extend/fast/Pinyin.php
@@ -0,0 +1,89 @@
+ 160)
+ {
+ $_Q = ord(substr($chinese, ++$i, 1));
+ $_P = $_P * 256 + $_Q - 65536;
+ }
+ $result .= ($ucfirst ? ucfirst(self::_pinyin($_P, $data)) : self::_pinyin($_P, $data));
+ }
+
+ return preg_replace("/[^a-z0-9_\-]*/i", '', $result);
+ }
+
+ private static function _pinyin($num, $data)
+ {
+ if ($num > 0 && $num < 160)
+ return chr($num);
+ elseif ($num < -20319 || $num > -10247)
+ return '';
+ else
+ {
+ foreach ($data as $k => $v)
+ {
+ if ($v <= $num)
+ break;
+ }
+
+ return $k;
+ }
+ }
+
+ private static function _u2_utf8_gb($c)
+ {
+ $string = '';
+ if ($c < 0x80)
+ $string .= $c;
+ elseif ($c < 0x800)
+ {
+ $string .= chr(0xC0 | $c >> 6);
+ $string .= chr(0x80 | $c & 0x3F);
+ }
+ elseif ($c < 0x10000)
+ {
+ $string .= chr(0xE0 | $c >> 12);
+ $string .= chr(0x80 | $c >> 6 & 0x3F);
+ $string .= chr(0x80 | $c & 0x3F);
+ }
+ elseif ($c < 0x200000)
+ {
+ $string .= chr(0xF0 | $c >> 18);
+ $string .= chr(0x80 | $c >> 12 & 0x3F);
+ $string .= chr(0x80 | $c >> 6 & 0x3F);
+ $string .= chr(0x80 | $c & 0x3F);
+ }
+ return iconv('UTF-8', 'GB2312//IGNORE', $string);
+ }
+
+}
diff --git a/extend/fast/Random.php b/extend/fast/Random.php
new file mode 100644
index 00000000..8851488d
--- /dev/null
+++ b/extend/fast/Random.php
@@ -0,0 +1,182 @@
+20, 'p2'=>30, 'p3'=>50);
+ * @param array $num 默认为1,即随机出来的数量
+ * @param array $unique 默认为true,即当num>1时,随机出的数量是否唯一
+ * @return mixed 当num为1时返回键名,反之返回一维数组
+ */
+ public static function lottery($ps, $num = 1, $unique = true)
+ {
+ if (!$ps)
+ {
+ return $num == 1 ? '' : [];
+ }
+ if ($num >= count($ps) && $unique)
+ {
+ $res = array_keys($ps);
+ return $num == 1 ? $res[0] : $res;
+ }
+ $max_exp = 0;
+ $res = [];
+ foreach ($ps as $key => $value)
+ {
+ $value = substr($value, 0, stripos($value, ".") + 6);
+ $exp = strlen(strchr($value, '.')) - 1;
+ if ($exp > $max_exp)
+ {
+ $max_exp = $exp;
+ }
+ }
+ $pow_exp = pow(10, $max_exp);
+ if ($pow_exp > 1)
+ {
+ reset($ps);
+ foreach ($ps as $key => $value)
+ {
+ $ps[$key] = $value * $pow_exp;
+ }
+ }
+ $pro_sum = array_sum($ps);
+ if ($pro_sum < 1)
+ {
+ return $num == 1 ? '' : [];
+ }
+ for ($i = 0; $i < $num; $i++)
+ {
+ $rand_num = mt_rand(1, $pro_sum);
+ reset($ps);
+ foreach ($ps as $key => $value)
+ {
+ if ($rand_num <= $value)
+ {
+ break;
+ }
+ else
+ {
+ $rand_num -= $value;
+ }
+ }
+ if ($num == 1)
+ {
+ $res = $key;
+ break;
+ }
+ else
+ {
+ $res[$i] = $key;
+ }
+ if ($unique)
+ {
+ $pro_sum -= $value;
+ unset($ps[$key]);
+ }
+ }
+ return $res;
+ }
+
+ /**
+ * 获取全球唯一标识
+ * @return string
+ */
+ public static function uuid()
+ {
+ return sprintf(
+ '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
+ );
+ }
+
+}
diff --git a/extend/fast/Rsa.php b/extend/fast/Rsa.php
new file mode 100644
index 00000000..2fc1a8ed
--- /dev/null
+++ b/extend/fast/Rsa.php
@@ -0,0 +1,187 @@
+setKey($publicKey, $privateKey);
+ }
+
+ /**
+ * 设置公钥和私钥
+ * @param string $publicKey 公钥
+ * @param string $privateKey 私钥
+ */
+ public function setKey($publicKey = null, $privateKey = null)
+ {
+ if (!is_null($publicKey))
+ $this->publicKey = $publicKey;
+ if (!is_null($privateKey))
+ $this->privateKey = $privateKey;
+ }
+
+ /**
+ * * setup the private key
+ */
+ private function setupPrivKey()
+ {
+ if (is_resource($this->_privKey))
+ {
+ return true;
+ }
+ $pem = chunk_split($this->privateKey, 64, "\n");
+ $pem = "-----BEGIN PRIVATE KEY-----\n" . $pem . "-----END PRIVATE KEY-----\n";
+ $this->_privKey = openssl_pkey_get_private($pem);
+ return true;
+ }
+
+ /**
+ * * setup the public key
+ */
+ private function setupPubKey()
+ {
+ if (is_resource($this->_pubKey))
+ {
+ return true;
+ }
+ $pem = chunk_split($this->publicKey, 64, "\n");
+ $pem = "-----BEGIN PUBLIC KEY-----\n" . $pem . "-----END PUBLIC KEY-----\n";
+ $this->_pubKey = openssl_pkey_get_public($pem);
+ return true;
+ }
+
+ /**
+ * * encrypt with the private key
+ */
+ public function privEncrypt($data)
+ {
+ if (!is_string($data))
+ {
+ return null;
+ }
+ $this->setupPrivKey();
+ $r = openssl_private_encrypt($data, $encrypted, $this->_privKey);
+ if ($r)
+ {
+ return base64_encode($encrypted);
+ }
+ return null;
+ }
+
+ /**
+ * * decrypt with the private key
+ */
+ public function privDecrypt($encrypted)
+ {
+ if (!is_string($encrypted))
+ {
+ return null;
+ }
+ $this->setupPrivKey();
+ $encrypted = base64_decode($encrypted);
+ $r = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
+ if ($r)
+ {
+ return $decrypted;
+ }
+ return null;
+ }
+
+ /**
+ * * encrypt with public key
+ */
+ public function pubEncrypt($data)
+ {
+ if (!is_string($data))
+ {
+ return null;
+ }
+ $this->setupPubKey();
+ $r = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
+ if ($r)
+ {
+ return base64_encode($encrypted);
+ }
+ return null;
+ }
+
+ /**
+ * * decrypt with the public key
+ */
+ public function pubDecrypt($crypted)
+ {
+ if (!is_string($crypted))
+ {
+ return null;
+ }
+ $this->setupPubKey();
+ $crypted = base64_decode($crypted);
+ $r = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
+ if ($r)
+ {
+ return $decrypted;
+ }
+ return null;
+ }
+
+ /**
+ * 构造签名
+ * @param string $dataString 被签名数据
+ * @return string
+ */
+ public function sign($dataString)
+ {
+ $this->setupPrivKey();
+ $signature = false;
+ openssl_sign($dataString, $signature, $this->_privKey);
+ return base64_encode($signature);
+ }
+
+ /**
+ * 验证签名
+ * @param string $dataString 被签名数据
+ * @param string $signString 已经签名的字符串
+ * @return number 1签名正确 0签名错误
+ */
+ public function verify($dataString, $signString)
+ {
+ $this->setupPubKey();
+ $signature = base64_decode($signString);
+ $flg = openssl_verify($dataString, $signature, $this->_pubKey);
+ return $flg;
+ }
+
+ public function __destruct()
+ {
+ is_resource($this->_privKey) && @openssl_free_key($this->_privKey);
+ is_resource($this->_pubKey) && @openssl_free_key($this->_pubKey);
+ }
+
+}
diff --git a/extend/fast/Tree.php b/extend/fast/Tree.php
new file mode 100644
index 00000000..2c201bbe
--- /dev/null
+++ b/extend/fast/Tree.php
@@ -0,0 +1,480 @@
+
+ */
+class Tree
+{
+
+ protected static $instance;
+ //默认配置
+ protected $config = [];
+ public $options = [];
+
+ /**
+ * 生成树型结构所需要的2维数组
+ * @var array
+ */
+ public $arr = [];
+
+ /**
+ * 生成树型结构所需修饰符号,可以换成图片
+ * @var array
+ */
+ public $icon = array('│', '├', '└');
+ public $nbsp = " ";
+ public $pidname = 'pid';
+
+ public function __construct($options = [])
+ {
+ if ($config = Config::get('tree'))
+ {
+ $this->options = array_merge($this->config, $config);
+ }
+ $this->options = array_merge($this->config, $options);
+ }
+
+ /**
+ * 初始化
+ * @access public
+ * @param array $options 参数
+ * @return Tree
+ */
+ public static function instance($options = [])
+ {
+ if (is_null(self::$instance))
+ {
+ self::$instance = new static($options);
+ }
+
+ return self::$instance;
+ }
+
+ /**
+
+ * 初始化方法
+
+ * @param array 2维数组,例如:
+ * array(
+ * 1 => array('id'=>'1','pid'=>0,'name'=>'一级栏目一'),
+ * 2 => array('id'=>'2','pid'=>0,'name'=>'一级栏目二'),
+ * 3 => array('id'=>'3','pid'=>1,'name'=>'二级栏目一'),
+ * 4 => array('id'=>'4','pid'=>1,'name'=>'二级栏目二'),
+ * 5 => array('id'=>'5','pid'=>2,'name'=>'二级栏目三'),
+ * 6 => array('id'=>'6','pid'=>3,'name'=>'三级栏目一'),
+ * 7 => array('id'=>'7','pid'=>3,'name'=>'三级栏目二')
+ * )
+ */
+ public function init($arr = [], $pidname = NULL, $nbsp = NULL)
+ {
+ $this->arr = $arr;
+ if (!is_null($pidname))
+ $this->pidname = $pidname;
+ if (!is_null($nbsp))
+ $this->nbsp = $nbsp;
+ return $this;
+ }
+
+ /**
+ * 得到子级数组
+ * @param int
+ * @return array
+ */
+ public function getChild($myid)
+ {
+ $newarr = [];
+ foreach ($this->arr as $value)
+ {
+ if (!isset($value['id']))
+ continue;
+ if ($value[$this->pidname] == $myid)
+ $newarr[$value['id']] = $value;
+ }
+ return $newarr;
+ }
+
+ /**
+
+ * 读取指定节点的所有孩子节点
+ * @param int $myid 节点ID
+ * @param boolean $withself 是否包含自身
+ * @return array
+ */
+ public function getChildren($myid, $withself = FALSE)
+ {
+ $newarr = [];
+ foreach ($this->arr as $value)
+ {
+ if (!isset($value['id']))
+ continue;
+ if ($value[$this->pidname] == $myid)
+ {
+ $newarr[] = $value;
+ $newarr = array_merge($newarr, $this->getChildren($value['id']));
+ }
+ else if ($withself && $value['id'] == $myid)
+ {
+ $newarr[] = $value;
+ }
+ }
+ return $newarr;
+ }
+
+ /**
+
+ * 读取指定节点的所有孩子节点ID
+ * @param int $myid 节点ID
+ * @param boolean $withself 是否包含自身
+ * @return array
+ */
+ public function getChildrenIds($myid, $withself = FALSE)
+ {
+ $childrenlist = $this->getChildren($myid, $withself);
+ $childrenids = [];
+ foreach ($childrenlist as $k => $v)
+ {
+ $childrenids[] = $v['id'];
+ }
+ return $childrenids;
+ }
+
+ /**
+
+ * 得到当前位置父辈数组
+ * @param int
+ * @return array
+
+ */
+ public function getParent($myid)
+ {
+ $pid = 0;
+ $newarr = [];
+ foreach ($this->arr as $value)
+ {
+ if (!isset($value['id']))
+ continue;
+ if ($value['id'] == $myid)
+ {
+ $pid = $value[$this->pidname];
+ break;
+ }
+ }
+ if ($pid)
+ {
+ foreach ($this->arr as $value)
+ {
+ if ($value['id'] == $pid)
+ {
+ $newarr[] = $value;
+ break;
+ }
+ }
+ }
+ return $newarr;
+ }
+
+ /**
+
+ * 得到当前位置所有父辈数组
+ * @param int
+ * @return array
+
+ */
+ public function getParents($myid, $withself = FALSE)
+ {
+ $pid = 0;
+ $newarr = [];
+ foreach ($this->arr as $value)
+ {
+ if (!isset($value['id']))
+ continue;
+ if ($value['id'] == $myid)
+ {
+ if ($withself)
+ {
+ $newarr[] = $value;
+ }
+ $pid = $value[$this->pidname];
+ break;
+ }
+ }
+ if ($pid)
+ {
+ $arr = $this->getParents($pid, TRUE);
+ $newarr = array_merge($arr, $newarr);
+ }
+ return $newarr;
+ }
+
+ /**
+ * 读取指定节点所有父类节点ID
+ * @param int $myid
+ * @param boolean $withself
+ * @return array
+ */
+ public function getParentsIds($myid, $withself = FALSE)
+ {
+ $parentlist = $this->getParents($myid, $withself);
+ $parentsids = [];
+ foreach ($parentlist as $k => $v)
+ {
+ $parentsids[] = $v['id'];
+ }
+ return $parentsids;
+ }
+
+ /**
+
+ * 树型结构Option
+ * @param int $myid 表示获得这个ID下的所有子级
+ * @param string $itemtpl 条目模板 如:""
+ * @param mixed $selectedids 被选中的ID,比如在做树型下拉框的时候需要用到
+ * @param mixed $disabledids 被禁用的ID,比如在做树型下拉框的时候需要用到
+ * @param string $itemprefix 每一项前缀
+ * @param string $toptpl 顶级栏目的模板
+ * @return string
+
+ */
+ public function getTree($myid, $itemtpl = "", $selectedids = '', $disabledids = '', $itemprefix = '', $toptpl = '')
+ {
+ $ret = '';
+ $number = 1;
+ $childs = $this->getChild($myid);
+ if ($childs)
+ {
+ $total = count($childs);
+ foreach ($childs as $value)
+ {
+ $id = $value['id'];
+ $j = $k = '';
+ if ($number == $total)
+ {
+ $j .= $this->icon[2];
+ $k = $itemprefix ? $this->nbsp : '';
+ }
+ else
+ {
+ $j .= $this->icon[1];
+ $k = $itemprefix ? $this->icon[0] : '';
+ }
+ $spacer = $itemprefix ? $itemprefix . $j : '';
+ $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : '';
+ $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
+ $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled, 'spacer' => $spacer));
+ $value = array_combine(array_map(function($k)
+ {
+ return '@' . $k;
+ }, array_keys($value)), $value);
+ $nstr = strtr((($value["@{$this->pidname}"] == 0 || $this->getChild($id) ) && $toptpl ? $toptpl : $itemtpl), $value);
+ $ret .= $nstr;
+ $ret .= $this->getTree($id, $itemtpl, $selectedids, $disabledids, $itemprefix . $k . $this->nbsp, $toptpl);
+ $number++;
+ }
+ }
+ return $ret;
+ }
+
+ /**
+
+ * 树型结构UL
+ * @param int $myid 表示获得这个ID下的所有子级
+ * @param string $itemtpl 条目模板 如:"@name @childlist"
+ * @param string $selectedids 选中的ID
+ * @param string $disabledids 禁用的ID
+ * @param string $wraptag 子列表包裹标签
+ * @return string
+
+ */
+ public function getTreeUl($myid, $itemtpl, $selectedids = '', $disabledids = '', $wraptag = 'ul', $wrapattr = '')
+ {
+ $str = '';
+ $childs = $this->getChild($myid);
+ if ($childs)
+ {
+ foreach ($childs as $value)
+ {
+ $id = $value['id'];
+ unset($value['child']);
+ $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : '';
+ $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
+ $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled));
+ $value = array_combine(array_map(function($k)
+ {
+ return '@' . $k;
+ }, array_keys($value)), $value);
+ $nstr = strtr($itemtpl, $value);
+ $childdata = $this->getTreeUl($id, $itemtpl, $selectedids, $disabledids, $wraptag, $wrapattr);
+ $childlist = $childdata ? "<{$wraptag} {$wrapattr}>" . $childdata . "{$wraptag}>" : "";
+ $str .= strtr($nstr, array('@childlist' => $childlist));
+ }
+ }
+ return $str;
+ }
+
+ /**
+ * 菜单数据
+ * @param int $myid
+ * @param string $itemtpl
+ * @param mixed $selectedids
+ * @param mixed $disabledids
+ * @param string $wraptag
+ * @param string $wrapattr
+ * @param int $deeplevel
+ * @return string
+ */
+ public function getTreeMenu($myid, $itemtpl, $selectedids = '', $disabledids = '', $wraptag = 'ul', $wrapattr = '', $deeplevel = 0)
+ {
+ $str = '';
+ $childs = $this->getChild($myid);
+ if ($childs)
+ {
+ foreach ($childs as $value)
+ {
+ $id = $value['id'];
+ unset($value['child']);
+ $selected = in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : '';
+ $disabled = in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
+ $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled));
+ $value = array_combine(array_map(function($k)
+ {
+ return '@' . $k;
+ }, array_keys($value)), $value);
+ $bakvalue = array_intersect_key($value, array_flip(['@url', '@caret', '@class']));
+ $value = array_diff_key($value, $bakvalue);
+ $nstr = strtr($itemtpl, $value);
+ $value = array_merge($value, $bakvalue);
+ $childdata = $this->getTreeMenu($id, $itemtpl, $selectedids, $disabledids, $wraptag, $wrapattr, $deeplevel + 1);
+ $childlist = $childdata ? "<{$wraptag} {$wrapattr}>" . $childdata . "{$wraptag}>" : "";
+ $childlist = strtr($childlist, array('@class' => $childdata ? 'last' : ''));
+ $value = array(
+ '@childlist' => $childlist,
+ '@url' => $childdata || !isset($value['@url']) ? "javascript:;" : url($value['@url']),
+ '@caret' => ($childdata && !$value['@badge'] ? '' : ''),
+ '@badge' => $value['@badge'],
+ '@class' => ($selected ? ' active' : '') . ($disabled ? ' disabled' : '') . ($childdata ? ' treeview' : ''),
+ );
+ $str .= strtr($nstr, $value);
+ }
+ }
+ return $str;
+ }
+
+ /**
+ * 特殊
+ * @param integer $myid 要查询的ID
+ * @param string $itemtpl1 第一种HTML代码方式
+ * @param string $itemtpl2 第二种HTML代码方式
+ * @param mixed $selectedids 默认选中
+ * @param mixed $disabledids 禁用
+ * @param integer $itemprefix 前缀
+ */
+ public function getTreeSpecial($myid, $itemtpl1, $itemtpl2, $selectedids = 0, $disabledids = 0, $itemprefix = '')
+ {
+ $ret = '';
+ $number = 1;
+ $childs = $this->getChild($myid);
+ if ($childs)
+ {
+ $total = count($childs);
+ foreach ($childs as $id => $value)
+ {
+ $j = $k = '';
+ if ($number == $total)
+ {
+ $j .= $this->icon[2];
+ $k = $itemprefix ? $this->nbsp : '';
+ }
+ else
+ {
+ $j .= $this->icon[1];
+ $k = $itemprefix ? $this->icon[0] : '';
+ }
+ $spacer = $itemprefix ? $itemprefix . $j : '';
+ $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : '';
+ $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
+ $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled, 'spacer' => $spacer));
+ $value = array_combine(array_map(function($k)
+ {
+ return '@' . $k;
+ }, array_keys($value)), $value);
+ $nstr = strtr(!isset($value['@disabled']) || !$value['@disabled'] ? $itemtpl1 : $itemtpl2, $value);
+
+ $ret .= $nstr;
+ $ret .= $this->getTreeSpecial($id, $itemtpl1, $itemtpl2, $selectedids, $disabledids, $itemprefix . $k . $this->nbsp);
+ $number++;
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ *
+ * 获取树状数组
+ * @param string $myid 要查询的ID
+ * @param string $nametpl 名称条目模板
+ * @param string $itemprefix 前缀
+ * @return string
+ */
+ public function getTreeArray($myid, $itemprefix = '')
+ {
+ $childs = $this->getChild($myid);
+ $n = 0;
+ $data = [];
+ $number = 1;
+ if ($childs)
+ {
+ $total = count($childs);
+ foreach ($childs as $id => $value)
+ {
+ $j = $k = '';
+ if ($number == $total)
+ {
+ $j .= $this->icon[2];
+ $k = $itemprefix ? $this->nbsp : '';
+ }
+ else
+ {
+ $j .= $this->icon[1];
+ $k = $itemprefix ? $this->icon[0] : '';
+ }
+ $spacer = $itemprefix ? $itemprefix . $j : '';
+ $value['spacer'] = $spacer;
+ $data[$n] = $value;
+ $data[$n]['childlist'] = $this->getTreeArray($id, $itemprefix . $k . $this->nbsp);
+ $n++;
+ $number++;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 将getTreeArray的结果返回为二维数组
+ * @param array $data
+ * @return array
+ */
+ public function getTreeList($data = [], $field = 'name')
+ {
+ $arr = [];
+ foreach ($data as $k => $v)
+ {
+ $childlist = isset($v['childlist']) ? $v['childlist'] : [];
+ unset($v['childlist']);
+ $v[$field] = $v['spacer'] . ' ' . $v[$field];
+ $v['haschild'] = $childlist ? 1 : 0;
+ if ($v['id'])
+ $arr[] = $v;
+ if ($childlist)
+ {
+ $arr = array_merge($arr, $this->getTreeList($childlist, $field));
+ }
+ }
+ return $arr;
+ }
+
+}
diff --git a/extend/fast/payment/Alipay.php b/extend/fast/payment/Alipay.php
new file mode 100644
index 00000000..97d4e522
--- /dev/null
+++ b/extend/fast/payment/Alipay.php
@@ -0,0 +1,447 @@
+ 1,
+ // 传输协议
+ 'transport' => 'http',
+ // 编码方式
+ 'input_charset' => 'utf-8',
+ // 签名方法
+ 'sign_type' => 'MD5',
+ // 证书路径
+ 'cacert' => './cacert.pem',
+ //验签公钥地址
+ 'public_key_path' => './alipay_public_key.pem',
+ 'private_key_path' => '',
+ // 支付完成异步通知调用地址
+ // 'notify_url' => 'http://'.$_SERVER['HTTP_HOST'].'/order/callback_alipay/notify',
+ // 支付完成同步返回地址
+ // 'return_url' => 'http://'.$_SERVER['HTTP_HOST'].'/order/callback_alipay/return',
+ // 支付宝商家 ID
+ 'partner' => '2088xxxxxxxx',
+ // // 支付宝商家 KEY
+ 'key' => 'xxxxxxxxxxxx',
+ // // 支付宝商家注册邮箱
+ 'seller_email' => 'email@domain.com'
+ );
+ private $is_mobile = FALSE;
+ public $service = self::SERVICE;
+ public $gateway = self::GATEWAY;
+
+ /**
+ * 配置
+ * @param $options array 配置信息
+ * @param null $type string 类型 wap app
+ */
+ public function __construct($options = [], $type = null)
+ {
+ if ($config = Config::get('payment.alipay'))
+ {
+ $this->config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ $this->is_mobile = (($type == 'wap' || $type === true) ? true : false);
+ if ($this->is_mobile)
+ {
+ $this->gateway = self::GATEWAY_MOBILE;
+ }
+
+ if ($type == 'wap' || $type === true)
+ {
+ $this->service = self::SERVICE_WAP;
+ }
+ elseif ($type == 'app')
+ {
+ $this->service = self::SERVICE_APP;
+ }
+ }
+
+ /**
+ * 生成请求参数的签名
+ *
+ * @param $params
+ * @return
+ *
+ */
+ function signParameters($params)
+ {
+ // 支付宝的签名串必须是未经过 urlencode 的字符串
+ // 不清楚为何 PHP 5.5 里没有 http_build_str() 方法
+ $paramStr = urldecode(http_build_query($params));
+ switch (strtoupper(trim($this->config['sign_type'])))
+ {
+ case "MD5" :
+ $result = md5($paramStr . $this->config['key']);
+ break;
+ case "RSA" :
+ case "0001" :
+ $priKey = file_get_contents($this->config['private_key_path']);
+ $res = openssl_get_privatekey($priKey);
+ openssl_sign($paramStr, $sign, $res);
+ openssl_free_key($res);
+ //base64编码
+ $result = base64_encode($sign);
+ break;
+ default :
+ $result = "";
+ }
+ return $result;
+ }
+
+ /**
+ * 准备签名参数
+ *
+ * @param $params
+ * $params['out_trade_no'] 唯一订单编号
+ * $params['subject']
+ * $params['total_fee']
+ * $params['body']
+ * $params['show_url']
+ * $params['anti_phishing_key']
+ * $params['exter_invoke_ip']
+ * $params['it_b_pay']
+ * $params['_input_charset']
+ * @return
+ */
+ function prepareParameters($params)
+ {
+ $default = array(
+ 'service' => $this->service,
+ 'partner' => $this->config['partner'],
+ '_input_charset' => trim(strtolower($this->config['input_charset']))
+ );
+ if (!$this->is_mobile)
+ {
+ $default = array_merge($default, array(
+ 'payment_type' => $this->config['payment_type'],
+ 'seller_id' => $this->config['partner'],
+ 'notify_url' => $this->config['notify_url'],
+ ));
+ if (isset($this->config['return_url']))
+ {
+ $default['return_url'] = $this->config['return_url'];
+ }
+ }
+
+ $params = $this->filterSignParameter(array_merge($default, (array) $params));
+ ksort($params);
+ reset($params);
+ return $params;
+ }
+
+ /**
+ * 生成签名后的请求参数
+ *
+ */
+ function buildSignedParameters($params)
+ {
+ $params = $this->prepareParameters($params);
+ $params['sign'] = $this->signParameters($params);
+ if ($params['service'] != self::SERVICE_WAP && $params['service'] != self::SERVICE_WAP_AUTH)
+ {
+ $params['sign_type'] = strtoupper(trim($this->config['sign_type']));
+ }
+ return $params;
+ }
+
+ /**
+ * https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.NgdeQA&treeId=59&articleId=103663&docType=1
+ * 服务端生成app支付使用的参数以及签名
+ * @param $params
+ * @return
+ */
+ function buildSignedParametersForApp($params)
+ {
+ $params = $this->prepareParameters($params);
+ $params['sign'] = urlencode($this->signParameters($params));
+ $params['sign_type'] = 'RSA';
+ $paramStr = [];
+ foreach ($params as $k => &$param)
+ {
+ $param = '"' . $param . '"';
+ $paramStr[] = $k . '=' . $param;
+ }
+
+ return implode('&', $paramStr);
+ }
+
+ /**
+ * 生成请求参数的发送表单HTML
+ *
+ * 其实这个函数没有必要,更应该使用签名后的参数自己组装,只不过有时候方便就从官方 SDK 里留下了。
+ *
+ * @param $params 请求参数(未签名的)
+ * @param $method 请求方法,默认:post,可选 get
+ * @param $target 提交目标,默认:_self
+ * @return
+ *
+ */
+ function buildRequestFormHTML($params, $method = 'post', $target = '_self')
+ {
+ $params = $this->buildSignedParameters($params);
+ $html = '";
+ return $html;
+ }
+
+ /**
+ * 准备移动网页支付的请求参数
+ *
+ * 移动网页支付接口不同,需要先服务器提交一次请求,拿到返回 token 再返回客户端发起真实支付请求。
+ * 该方法只完成第一次服务端请求,生成参数后需要客户端另行处理(可调用`buildRequestFormHTML`生成表单提交)。
+ *
+ * @param $params
+ * $params['out_trade_no'] 订单唯一编号
+ * $params['subject'] 商品标题
+ * $params['total_fee'] 支付总费用
+ * $params['merchant_url'] 商品链接地址
+ * $params['req_id'] 请求唯一 ID
+ * $params['it_b_pay'] 超期时间(秒)
+ * @return /
+ */
+ function prepareMobileTradeData($params)
+ {
+ // 不要用 SimpleXML 来构建 xml 结构,因为有第一行文档申明支付宝验证不通过
+ $xml_str = '' .
+ '' . $this->config['notify_url'] . '' .
+ '' . $this->config['return_url'] . '' .
+ '' . $this->config['seller_email'] . '' .
+ '' . $params['out_trade_no'] . '' .
+ '' . htmlspecialchars($params['subject'], ENT_XML1, 'UTF-8') . '' .
+ '' . $params['total_fee'] . '' .
+ '' . $params['merchant_url'] . '' .
+ (isset($params['it_b_pay']) ? '' . $params['it_b_pay'] . '' : '') .
+ '';
+ $request_data = $this->buildSignedParameters(array(
+ 'service' => $this->service,
+ 'partner' => $this->config['partner'],
+ 'sec_id' => $this->config['sign_type'],
+ 'format' => 'xml',
+ 'v' => '2.0',
+ 'req_id' => $params['req_id'],
+ 'req_data' => $xml_str
+ ));
+ $url = $this->gateway;
+ $input_charset = trim(strtolower($this->config['input_charset']));
+ if (trim($input_charset) != '')
+ {
+ $url = $url . "_input_charset=" . $input_charset;
+ }
+ $curl = curl_init($url);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证
+ curl_setopt($curl, CURLOPT_CAINFO, $this->config['cacert']); //证书地址
+ curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果
+ curl_setopt($curl, CURLOPT_POST, true); // post传输数据
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request_data); // post传输数据
+ $responseText = curl_exec($curl);
+ //var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容
+ curl_close($curl);
+ if (empty($responseText))
+ {
+ return NULL;
+ }
+ parse_str($responseText, $responseData);
+ if (empty($responseData['res_data']))
+ {
+ return NULL;
+ }
+ if ($this->config['sign_type'] == '0001')
+ {
+ $responseData['res_data'] = $this->rsaDecrypt($responseData['res_data'], $this->config['private_key_path']);
+ }
+ //token从res_data中解析出来(也就是说res_data中已经包含token的内容)
+ $doc = new DOMDocument();
+ $doc->loadXML($responseData['res_data']);
+ $responseData['request_token'] = $doc->getElementsByTagName("request_token")->item(0)->nodeValue;
+ $xml_str = '' .
+ '' . $responseData['request_token'] . '' .
+ '';
+ return array(
+ 'service' => self::SERVICE_WAP_AUTH,
+ 'partner' => $this->config['partner'],
+ 'sec_id' => $this->config['sign_type'],
+ 'format' => 'xml',
+ 'v' => '2.0',
+ 'req_data' => $xml_str
+ );
+ }
+
+ /**
+ * 支付完成验证返回参数(包含同步和异步)
+ *
+ * @return
+ */
+ function verifyCallback()
+ {
+ $async = empty($_GET);
+ $data = $async ? $_POST : $_GET;
+ if (empty($data))
+ {
+ return FALSE;
+ }
+ $signValid = $this->verifyParameters($data, $data["sign"]);
+ $notify_id = isset($data['notify_id']) ? $data['notify_id'] : NULL;
+ if ($async && $this->is_mobile)
+ {
+ //对notify_data解密
+ if ($this->config['sign_type'] == '0001')
+ {
+ $data['notify_data'] = $this->rsaDecrypt($data['notify_data'], $this->config['private_key_path']);
+ }
+ //notify_id从decrypt_post_para中解析出来(也就是说decrypt_post_para中已经包含notify_id的内容)
+ $doc = new DOMDocument();
+ $doc->loadXML($data['notify_data']);
+ $notify_id = $doc->getElementsByTagName('notify_id')->item(0)->nodeValue;
+ }
+ //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)
+ $responseTxt = 'true';
+ if (!empty($notify_id))
+ {
+ $responseTxt = $this->verifyFromServer($notify_id);
+ }
+ //验证
+ //$signValid的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
+ //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
+ return $signValid && preg_match("/true$/i", $responseTxt);
+ }
+
+ function verifyParameters($params, $sign)
+ {
+ $params = $this->filterSignParameter($params);
+ if (isset($params['notify_data']))
+ {
+ $params = array(
+ 'service' => $params['service'],
+ 'v' => $params['v'],
+ 'sec_id' => $params['sec_id'],
+ 'notify_data' => $params['notify_data']
+ );
+ }
+ else
+ {
+ ksort($params);
+ reset($params);
+ }
+ $content = urldecode(http_build_query($params));
+ switch (strtoupper(trim($this->config['sign_type'])))
+ {
+ case "MD5" :
+ return md5($content . $this->config['key']) == $sign;
+ case "RSA" :
+ case "0001" :
+ return $this->rsaVerify($content, $this->config['public_key_path'], $sign);
+ default :
+ return FALSE;
+ }
+ }
+
+ /**
+ * 过滤参数,去除sign/sign_type参数
+ * @param $params
+ * @return
+ */
+ function filterSignParameter($params)
+ {
+ $result = array();
+ foreach ($params as $key => $value)
+ {
+ if ($key != 'sign' && $key != 'sign_type' && $value)
+ {
+ $result[$key] = $value;
+ }
+ }
+ return $result;
+ }
+
+ function verifyFromServer($notify_id)
+ {
+ $transport = strtolower(trim($this->config['transport']));
+ $partner = trim($this->config['partner']);
+ $veryfy_url = ($transport == 'https' ? self::VERIFY_URL_HTTPS : self::VERIFY_URL) . "partner=$partner¬ify_id=$notify_id";
+ $curl = curl_init($veryfy_url);
+ curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); //SSL证书认证
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); //严格认证
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 显示输出结果
+ curl_setopt($curl, CURLOPT_CAINFO, $this->config['cacert']); //证书地址
+ $responseText = curl_exec($curl);
+ // var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容
+ curl_close($curl);
+ return $responseText;
+ }
+
+ /**
+ * RSA验签,注意验签的公钥是支付宝的公钥,不是自己生成的rsa公钥,可以在淘宝的demo中获得
+ * @param $data string 待签名数据
+ * @param $ali_public_key_path string 支付宝的公钥文件路径
+ * @param $sign string 要校对的的签名结果
+ * @return 验证结果
+ * @throws Exception
+ */
+ function rsaVerify($data, $ali_public_key_path, $sign)
+ {
+ $pubKey = file_get_contents($ali_public_key_path);
+ $res = openssl_get_publickey($pubKey);
+ if (!$res)
+ {
+ throw new Exception('公钥格式错误');
+ }
+ $result = (bool) openssl_verify($data, base64_decode($sign), $res);
+ openssl_free_key($res);
+ return $result;
+ }
+
+ /**
+ * RSA解密
+ * @param $content string 需要解密的内容,密文
+ * @param $private_key_path string 商户私钥文件路径
+ * @return string 解密后内容,明文
+ */
+ function rsaDecrypt($content, $private_key_path)
+ {
+ $priKey = file_get_contents($private_key_path);
+ $res = openssl_get_privatekey($priKey);
+ //用base64将内容还原成二进制
+ $content = base64_decode($content);
+ //把需要解密的内容,按128位拆开解密
+ $result = '';
+ for ($i = 0; $i < strlen($content) / 128; $i++)
+ {
+ $data = substr($content, $i * 128, 128);
+ openssl_private_decrypt($data, $decrypt, $res);
+ $result .= $decrypt;
+ }
+ openssl_free_key($res);
+ return $result;
+ }
+
+}
diff --git a/extend/fast/payment/Wechat.php b/extend/fast/payment/Wechat.php
new file mode 100644
index 00000000..fc02c943
--- /dev/null
+++ b/extend/fast/payment/Wechat.php
@@ -0,0 +1,440 @@
+config = array_merge($this->config, $config);
+ }
+ $this->_config = array_merge($this->_config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * JSAPI获取prepay_id
+ *
+ * @param string $body
+ * @param string $out_trade_no
+ * @param int $total_fee
+ * @param string $openid
+ * @param array $ext
+ * @return string
+ */
+ public function getPrepayId($body, $out_trade_no, $total_fee, $openid, $ext = null)
+ {
+ $data = $ext? : [];
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["body"] = $body;
+ $data["out_trade_no"] = $out_trade_no;
+ $data["total_fee"] = $total_fee;
+ $data["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"];
+ $data["trade_type"] = self::TRADETYPE_JSAPI;
+ $data["openid"] = $openid;
+ $result = $this->unifiedOrder($data);
+ if ($result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS")
+ {
+ return $result["prepay_id"];
+ }
+ else
+ {
+ $this->error = $result["return_code"] == "SUCCESS" ? $result["err_code_des"] : $result["return_msg"];
+ $this->errorXML = $this->array2xml($result);
+ return null;
+ }
+ }
+
+ private function getNonceStr()
+ {
+ return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 32);
+ }
+
+ /**
+ * 统一下单接口
+ */
+ public function unifiedOrder($params)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["device_info"] = (isset($params['device_info']) && trim($params['device_info']) != '') ? $params['device_info'] : null;
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["body"] = $params['body'];
+ $data["detail"] = isset($params['detail']) ? $params['detail'] : null; //optional
+ $data["attach"] = isset($params['attach']) ? $params['attach'] : null; //optional
+ $data["out_trade_no"] = isset($params['out_trade_no']) ? $params['out_trade_no'] : null;
+ $data["fee_type"] = isset($params['fee_type']) ? $params['fee_type'] : 'CNY';
+ $data["total_fee"] = $params['total_fee'];
+ $data["spbill_create_ip"] = $params['spbill_create_ip'];
+ $data["time_start"] = isset($params['time_start']) ? $params['time_start'] : null; //optional
+ $data["time_expire"] = isset($params['time_expire']) ? $params['time_expire'] : null; //optional
+ $data["goods_tag"] = isset($params['goods_tag']) ? $params['goods_tag'] : null;
+ $data["notify_url"] = isset($params['notify_url']) ? $params['notify_url'] : $this->_config['notify_url'];
+ $data["trade_type"] = $params['trade_type'];
+ $data["product_id"] = isset($params['product_id']) ? $params['product_id'] : null; //required when trade_type = NATIVE
+ $data["openid"] = isset($params['openid']) ? $params['openid'] : null; //required when trade_type = JSAPI
+ $result = $this->post(self::URL_UNIFIEDORDER, $data);
+ return $result;
+ }
+
+ private function post($url, $data, $cert = false)
+ {
+ if (!isset($data['sign']))
+ $data["sign"] = $this->sign($data);
+ $xml = $this->array2xml($data);
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_URL, $url);
+ if ($cert == true)
+ {
+ //使用证书:cert 与 key 分别属于两个.pem文件
+ curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
+ curl_setopt($ch, CURLOPT_SSLCERT, $this->_config['sslcertPath']);
+ curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
+ curl_setopt($ch, CURLOPT_SSLKEY, $this->_config['sslkeyPath']);
+ }
+ $content = curl_exec($ch);
+ $array = $this->xml2array($content);
+ return $array;
+ }
+
+ /**
+ * 扫码支付(模式二)获取支付二维码
+ *
+ * @param string $body
+ * @param string $out_trade_no
+ * @param int $total_fee
+ * @param string $product_id
+ * @param array $ext
+ * @return string
+ */
+ public function getCodeUrl($body, $out_trade_no, $total_fee, $product_id, $ext = null)
+ {
+ $data = $ext ? $ext : [];
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["body"] = $body;
+ $data["out_trade_no"] = $out_trade_no;
+ $data["total_fee"] = $total_fee;
+ $data["spbill_create_ip"] = $_SERVER["SERVER_ADDR"];
+ $data["trade_type"] = self::TRADETYPE_NATIVE;
+ $data["product_id"] = $product_id;
+ $result = $this->unifiedOrder($data);
+ if ($result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS")
+ {
+ return $result["code_url"];
+ }
+ else
+ {
+ $this->error = $result["return_code"] == "SUCCESS" ? $result["err_code_des"] : $result["return_msg"];
+ return null;
+ }
+ }
+
+ /**
+ * 查询订单
+ * @param $transaction_id
+ * @param $out_trade_no
+ * @return array
+ */
+ public function orderQuery($transaction_id, $out_trade_no)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["transaction_id"] = $transaction_id;
+ $data["out_trade_no"] = $out_trade_no;
+ $data["nonce_str"] = $this->getNonceStr();
+ $result = $this->post(self::URL_ORDERQUERY, $data);
+ return $result;
+ }
+
+ /**
+ * 关闭订单
+ * @param $out_trade_no
+ * @return array
+ */
+ public function closeOrder($out_trade_no)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["out_trade_no"] = $out_trade_no;
+ $data["nonce_str"] = $this->getNonceStr();
+ $result = $this->post(self::URL_CLOSEORDER, $data);
+ return $result;
+ }
+
+ /**
+ * 申请退款 - 使用商户订单号
+ * @param $out_trade_no 商户订单号
+ * @param $out_refund_no 退款单号
+ * @param $total_fee 总金额(单位:分)
+ * @param $refund_fee 退款金额(单位:分)
+ * @param $op_user_id 操作员账号
+ * @return array
+ */
+ public function refund($out_trade_no, $out_refund_no, $total_fee, $refund_fee, $op_user_id)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["out_trade_no"] = $out_trade_no;
+ $data["out_refund_no"] = $out_refund_no;
+ $data["total_fee"] = $total_fee;
+ $data["refund_fee"] = $refund_fee;
+ $data["op_user_id"] = $op_user_id;
+ $result = $this->post(self::URL_REFUND, $data, true);
+ return $result;
+ }
+
+ /**
+ * 申请退款 - 使用微信订单号
+ * @param $transaction_id 微信订单号
+ * @param $out_refund_no 退款单号
+ * @param $total_fee 总金额(单位:分)
+ * @param $refund_fee 退款金额(单位:分)
+ * @param $op_user_id 操作员账号
+ * @return array
+ */
+ public function refundByTransId($transaction_id, $out_refund_no, $total_fee, $refund_fee, $op_user_id)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["transaction_id"] = $transaction_id;
+ $data["out_refund_no"] = $out_refund_no;
+ $data["total_fee"] = $total_fee;
+ $data["refund_fee"] = $refund_fee;
+ $data["op_user_id"] = $op_user_id;
+ $result = $this->post(self::URL_REFUND, $data, true);
+ return $result;
+ }
+
+ /**
+ * 下载对账单
+ * @param $bill_date 下载对账单的日期,格式:20140603
+ * @param string $bill_type 类型
+ * @return array
+ */
+ public function downloadBill($bill_date, $bill_type = 'ALL')
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["bill_date"] = $bill_date;
+ $data["bill_type"] = $bill_type;
+ $data["nonce_str"] = $this->getNonceStr();
+ $result = $this->post(self::URL_DOWNLOADBILL, $data);
+ return $result;
+ }
+
+ /**
+ * 扫码原生支付模式一中的二维码链接转成短链接
+ * @param $long_url 需要转换的URL,签名用原串,传输需URLencode
+ * @return array
+ */
+ public function shortUrl($long_url)
+ {
+ $data = array();
+ $data["appid"] = $this->_config["appid"];
+ $data["mch_id"] = $this->_config["mch_id"];
+ $data["long_url"] = $long_url;
+ $data["nonce_str"] = $this->getNonceStr();
+ $data["sign"] = $this->sign($data);
+ $data["long_url"] = urlencode($long_url);
+ $result = $this->post(self::URL_SHORTURL, $data);
+ return $result;
+ }
+
+ /**
+ * 获取jsapi支付所需参数
+ *
+ * @param string $prepay_id
+ * @return array
+ */
+ public function getPackageData($prepay_id)
+ {
+ $data = array();
+ $data["appId"] = $this->_config["appid"];
+ //解决微信支付调用JSAPI缺少参数:timeStamp
+ $data["timeStamp"] = time();
+ $data["nonceStr"] = $this->getNonceStr();
+ $data["package"] = "prepay_id=$prepay_id";
+ $data["signType"] = "MD5";
+ $data["paySign"] = $this->sign($data);
+ return $data;
+ }
+
+ /**
+ * 获取发送到通知地址的数据(在通知地址内使用)
+ * @return string 结果数组,如果不是微信服务器发送的数据返回null
+ * appid
+ * bank_type
+ * cash_fee
+ * fee_type
+ * is_subscribe
+ * mch_id
+ * nonce_str
+ * openid
+ * out_trade_no 商户订单号
+ * result_code
+ * return_code
+ * sign
+ * time_end
+ * total_fee 总金额
+ * trade_type
+ * transaction_id 微信支付订单号
+ */
+ public function getNotifyData()
+ {
+ $xml = file_get_contents("php://input");
+ $data = $this->xml2array($xml);
+ if ($this->validate($data))
+ {
+ return $data;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * 验证数据签名
+ * @param $data 数据数组
+ * @return 数据校验结果
+ */
+ public function validate($data)
+ {
+ if (!isset($data["sign"]))
+ {
+ return false;
+ }
+ $sign = $data["sign"];
+ unset($data["sign"]);
+ return $this->sign($data) == $sign;
+ }
+
+ /**
+ * 响应微信支付后台通知
+ * @param string $return_code 返回状态码 SUCCESS/FAIL
+ * @param $return_msg 返回信息
+ */
+ public function response_back($return_code = "SUCCESS", $return_msg = null)
+ {
+ $data = array();
+ $data["return_code"] = $return_code;
+ if ($return_msg)
+ {
+ $data["return_msg"] = $return_msg;
+ }
+ $xml = $this->array2xml($data);
+ print $xml;
+ }
+
+ /**
+ * 数据签名
+ * @param $data
+ * @return string
+ */
+ private function sign($data)
+ {
+ ksort($data);
+ $string1 = "";
+ foreach ($data as $k => $v)
+ {
+ if ($v && trim($v) != '')
+ {
+ $string1 .= "$k=$v&";
+ }
+ }
+ $stringSignTemp = $string1 . "key=" . $this->_config["apikey"];
+ $sign = strtoupper(md5($stringSignTemp));
+ return $sign;
+ }
+
+ private function array2xml($array)
+ {
+ $xml = "" . PHP_EOL;
+ foreach ($array as $k => $v)
+ {
+ if ($v && trim($v) != '')
+ $xml .= "<$k>$k>" . PHP_EOL;
+ }
+ $xml .= "";
+ return $xml;
+ }
+
+ private function xml2array($xml)
+ {
+ $array = array();
+ $tmp = null;
+ try
+ {
+ $tmp = (array) simplexml_load_string($xml);
+ }
+ catch (Exception $e)
+ {
+
+ }
+ if ($tmp && is_array($tmp))
+ {
+ foreach ($tmp as $k => $v)
+ {
+ $array[$k] = (string) $v;
+ }
+ }
+ return $array;
+ }
+
+}
diff --git a/extend/fast/service/Alisms.php b/extend/fast/service/Alisms.php
new file mode 100644
index 00000000..92d87cf4
--- /dev/null
+++ b/extend/fast/service/Alisms.php
@@ -0,0 +1,167 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * 单例
+ * @param array $options 参数
+ * @return Alisms
+ */
+ public static function instance($options = [])
+ {
+ if (is_null(self::$instance))
+ {
+ self::$instance = new static($options);
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * 设置签名
+ * @param string $sign
+ * @return Alisms
+ */
+ public function sign($sign = '')
+ {
+ $this->_params['sms_free_sign_name'] = $sign;
+ return $this;
+ }
+
+ /**
+ * 设置参数
+ * @param array $param
+ * @return Alisms
+ */
+ public function param(array $param = [])
+ {
+ foreach ($param as $k => &$v)
+ {
+ $v = (string) $v;
+ }
+ unset($v);
+ $this->_params['sms_param'] = json_encode($param);
+ return $this;
+ }
+
+ /**
+ * 设置模板
+ * @param string $code 短信模板
+ * @return Alisms
+ */
+ public function template($code = '')
+ {
+ $this->_params['sms_template_code'] = $code;
+ return $this;
+ }
+
+ /**
+ * 接收手机
+ * @param string $mobile 手机号码
+ * @return Alisms
+ */
+ public function mobile($mobile = '')
+ {
+ $this->_params['rec_num'] = $mobile;
+ return $this;
+ }
+
+ /**
+ * 立即发送
+ * @return boolean
+ */
+ public function send()
+ {
+ $this->error = [];
+ $params = $this->_params();
+ $params['sign'] = $this->_signed($params);
+ $reponse = $this->_curl($params);
+ if ($reponse !== FALSE)
+ {
+ $res = json_decode($reponse, TRUE);
+ $res = array_pop($res);
+ if (isset($res['result']))
+ return TRUE;
+ $this->error = $res;
+ }
+ else
+ {
+ $this->error = array('code' => 0, 'msg' => 'HTTP_RESPONSE_NOT_WELL_FORMED');
+ }
+ return FALSE;
+ }
+
+ /**
+ * 获取错误信息
+ * @return array
+ */
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ private function _params()
+ {
+ return array_merge([
+ 'app_key' => $this->config['key'],
+ 'format' => 'json',
+ 'method' => 'alibaba.aliqin.fc.sms.num.send',
+ 'v' => '2.0',
+ 'timestamp' => date('Y-m-d H:i:s'),
+ 'sign_method' => 'md5',
+ 'sms_type' => 'normal'
+ ], $this->_params);
+ }
+
+ private function _signed($params)
+ {
+ ksort($params);
+ $sign = $this->config['secret'];
+ foreach ($params as $k => $v)
+ {
+ if (is_string($v) && '@' != substr($v, 0, 1))
+ $sign .= $k . $v;
+ }
+ $sign .= $this->config['secret'];
+ return strtoupper(md5($sign));
+ }
+
+ private function _curl($params)
+ {
+ $uri = 'https://eco.taobao.com/router/rest?' . http_build_query($params);
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
+ curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36");
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+ $reponse = curl_exec($ch);
+ curl_close($ch);
+ return $reponse;
+ }
+
+}
diff --git a/extend/fast/service/Easemob.php b/extend/fast/service/Easemob.php
new file mode 100644
index 00000000..c1a9da54
--- /dev/null
+++ b/extend/fast/service/Easemob.php
@@ -0,0 +1,307 @@
+ $username, 'password' => $password];
+ if ($nickname)
+ {
+ $params['nickname'] = $nickname;
+ }
+ return self::api('users', $params, $token);
+ }
+
+ /**
+ * 创建聊天室
+ *
+ * @param string $name 名称
+ * @param string $description 描述
+ * @param string $owner 创建人
+ * @param int $maxusers 最多参与者
+ * @param array $members 成员
+ * @return array
+ */
+ public static function createRoom($name, $description, $owner, $maxusers = 5000, $members = [])
+ {
+ $owner = (string) $owner;
+ $params = [
+ "name" => $name, //聊天室名称,此属性为必须的
+ "description" => $description, //聊天室描述,此属性为必须的
+ "maxusers" => $maxusers, //聊天室成员最大数(包括群主),值为数值类型,默认值200,最大值5000,此属性为可选的
+ "owner" => $owner, //聊天室的管理员,此属性为必须的
+ ];
+ if ($members)
+ {
+ if (!in_array($owner, $members))
+ {
+ $members[] = $owner;
+ }
+ $params['members'] = $members;
+ }
+ return self::api('chatrooms', $params, TRUE);
+ }
+
+ /**
+ * 创建群组
+ *
+ * @param string $name 名称
+ * @param string $description 描述
+ * @param string $owner 管理员
+ * @param int $maxusers 最大成员数量
+ * @param array $members 成员列表
+ * @param boolean $public 是否公开
+ * @param boolean $approval 加入是否审核
+ * @return array
+ */
+ public static function createGroup($name, $description, $owner, $maxusers = 2000, $members = [], $public = TRUE, $approval = FALSE)
+ {
+ $owner = (string) $owner;
+ $params = [
+ "groupname" => $name,
+ "desc" => $description,
+ "public" => (bool) $public,
+ "maxusers" => $maxusers,
+ "approval" => (bool) $approval,
+ "owner" => $owner,
+ ];
+ if ($members)
+ {
+ if (!in_array($owner, $members))
+ {
+ $members[] = $owner;
+ }
+ $params['members'] = $members;
+ }
+ return self::api('chatgroups', $params, TRUE);
+ }
+
+ /**
+ * 修改群组信息
+ *
+ * @param int $group_id
+ * @param string $name
+ * @param string $description
+ * @param int $maxusers
+ * @return array
+ */
+ public static function editGroup($group_id, $name, $description, $maxusers)
+ {
+ $params = [
+ "groupname" => $name,
+ "desc" => $description,
+ "maxusers" => $maxusers,
+ ];
+ return self::api('chatgroups/' . $group_id, $params, TRUE, 'PUT');
+ }
+
+ /**
+ * 获取好友列表
+ */
+ public static function getFiends($owner_username)
+ {
+ return self::api("users/{$owner_username}/contacts/users", [], TRUE, 'GET');
+ }
+
+ /**
+ * 删除群组
+ *
+ * @param int $group_id
+ * @return array
+ */
+ public static function deleteGroup($group_id)
+ {
+ $params = [];
+ return self::api('chatgroups/' . $group_id, $params, TRUE, 'DELETE');
+ }
+
+ /**
+ * 发送消息
+ *
+ * @param string $from 发件人
+ * @param string $to 收件人
+ * @param mixed $msg 消息内容
+ * @param string $target_type 消息类型 users/chatgroups/chatrooms
+ * @return array
+ */
+ public static function sendMessage($from, $to, $msg, $target_type = 'users')
+ {
+ if (!is_array($msg))
+ {
+ $msg = [
+ 'type' => 'txt',
+ 'msg' => $msg
+ ];
+ }
+ $data = [
+ 'target_type' => $target_type,
+ 'target' => is_array($to) ? $to : [$to],
+ 'from' => $from,
+ ];
+ if (isset($msg['ext']))
+ {
+ $data['ext'] = $msg['ext'];
+ }
+ unset($msg['ext']);
+ $data['msg'] = $msg;
+ return self::api('messages', $data);
+ }
+
+ /**
+ * 获取离线消息记录条数
+ * @param string $owner_username
+ * @return array
+ */
+ public static function getOfflineMsgCount($owner_username)
+ {
+ return self::api("users/{$owner_username}/offline_msg_count", [], TRUE, 'GET');
+ }
+
+ /**
+ * 群组添加成员
+ * @param int $chatroom_id
+ * @param array $usernames
+ * @param array
+ */
+ public static function addChatRoomMembers($chatroom_id, $usernames)
+ {
+ return self::api("chatgroups/{$chatroom_id}/users", $usernames, TRUE);
+ }
+
+ /**
+ * 添加单个成员POST
+ */
+ public static function addOneChatRoomMember($chatroom_id, $username)
+ {
+ //return $chatroom_id;
+ return self::api("chatgroups/{$chatroom_id}/users/{$username}", [], TRUE);
+ }
+
+ /**
+ * 群组删除成员
+ * @param int $chatroom_id
+ * @param string $usernames
+ * @return array
+ */
+ public static function minusChatRoomMembers($chatroom_id, $usernames)
+ {
+ return self::api("chatgroups/{$chatroom_id}/users/{$usernames}", [], TRUE, 'DELETE');
+ }
+
+ /**
+ * 添加好友
+ */
+ public static function addFriends($owner_username, $friend_username)
+ {
+ return self::api("users/{$owner_username}/contacts/users/{$friend_username}", [], TRUE);
+ }
+
+ /**
+ * 删除好友
+ */
+ public static function minusFriends($owner_username, $friend_username)
+ {
+ return self::api("users/{$owner_username}/contacts/users/{$friend_username}", [], TRUE, 'DELETE');
+ }
+
+ /**
+ * 查看用户参与的所有群组
+ * @param type $owner_username
+ * @return type
+ */
+ public static function joinedChatgroups($owner_username)
+ {
+ return self::api("users/{$owner_username}/joined_chatgroups", [], TRUE, 'GET');
+ }
+
+ /**
+ * 调用API接口
+ *
+ * @param string $api 接口
+ * @param array $params request head参数
+ * @param boolean $token 是否认证模式
+ * @param string $method 请求方法 POST/GET
+ * @param array $options 扩展配置
+ * @return array
+ */
+ public static function api($api, $params = [], $token = TRUE, $method = 'POST', $options = [])
+ {
+ $header = ['Content-Type:application/json'];
+ if ($token)
+ {
+ $header[] = self::getNewToken();
+ }
+ $config = Config::get('service.easemob');
+ $options[CURLOPT_HTTPHEADER] = $header;
+
+ $url = self::URL . '/' . $config['org_name'] . '/' . $config['app_name'] . '/' . $api;
+ //return $url;
+ $ret = Http::sendRequest($url, json_encode($params), $method, $options);
+ if ($ret['ret'] && $ret['msg'])
+ {
+ $msg = json_decode($ret['msg'], TRUE);
+ if (isset($msg['error']))
+ {
+ Log::error($ret['msg']);
+ }
+ return isset($msg['error']) ? [] : $msg;
+ }
+ else
+ {
+ return [];
+ }
+ }
+
+ private static function getToken()
+ {
+ $tokendata = Cache::get('easemobtoken');
+ if ($tokendata && $tokendata['expiretime'] > time())
+ {
+ return $tokendata['access_token'];
+ }
+ else
+ {
+ $config = Config::get('service.easemob');
+ $data = self::api('token', [
+ 'grant_type' => 'client_credentials',
+ 'client_id' => $config['client_id'],
+ 'client_secret' => $config['client_secret'],
+ ], FALSE, 'POST');
+ if ($data)
+ {
+ $data['expiretime'] = time() + $data['expires_in'];
+ Cache::set('easemobtoken', $data, $data['expires_in'] - 10);
+ return $data['access_token'];
+ }
+ else
+ {
+ return '';
+ }
+ }
+ }
+
+}
diff --git a/extend/fast/service/Qiniu.php b/extend/fast/service/Qiniu.php
new file mode 100644
index 00000000..c240bd58
--- /dev/null
+++ b/extend/fast/service/Qiniu.php
@@ -0,0 +1,187 @@
+_config['bucket'];
+ $op = '/move/' . self::qiniuEncode($from) . '/' . self::qiniuEncode($to);
+ return self::opration($op);
+ }
+
+ /**
+ * 复制文件
+ *
+ * @param string $from 来源文件
+ * @param string $saveas 目标文件
+ * @return bool
+ */
+ public static function copy($from, $saveas)
+ {
+ // $bucket = $this->_config['bucket'];
+ $op = '/copy/' . self::qiniuEncode($from) . '/' . self::qiniuEncode($saveas);
+ return self::opration($op);
+ }
+
+ /**
+ * 获取token
+ *
+ * @param string $bucket 空间名
+ * @param string $key 密钥
+ * @param int $max 文件大小限制
+ * @param int $timeout 超时时间
+ * @return string
+ */
+ public static function getToken($bucket, $key, $max = 10485760, $timeout = 600)
+ {
+ $setting = array(
+ 'scope' => $bucket,
+ 'saveKey' => $key,
+ 'deadline' => $timeout + $_SERVER['REQUEST_TIME'],
+ 'fsizeLimit' => intval($max),
+ );
+ $setting = self::qiniuEncode(json_encode($setting));
+ return self::sign($setting) . ':' . $setting;
+ }
+
+ /**
+ * 删除
+ *
+ * @param string $uri 文件路径
+ * @return boolean
+ */
+ public static function delete($uri)
+ {
+ $file = self::qiniuEncode($uri);
+ return self::opration('/delete/' . $file);
+ }
+
+ /**
+ * 判断文件是否存在
+ *
+ * @param string $uri
+ * @return boolean
+ */
+ public static function has($uri)
+ {
+ $op = '/stat/' . self::qiniuEncode($uri);
+ return self::opration($op);
+ }
+
+ /**
+ * 转pdf
+ *
+ * @param string $bucket
+ * @param string $key
+ * @param string $saveas
+ * @return boolean
+ */
+ public static function toPdf($bucket, $key, $saveas)
+ {
+ $API = 'http://api.qiniu.com';
+ $op = '/pfop/';
+ $data = 'bucket=' . $bucket . '&key=' . $key . '&fops=yifangyun_preview|saveas/' . self::qiniuEncode($saveas);
+ return self::opration($op, $data, $API);
+ }
+
+ /**
+ * 七牛操作
+ *
+ * @param string $op 操作命令
+ * @param string $data 操作结果
+ * @param string $host
+ * @return boolean
+ */
+ private static function opration($op, $data = null, $host = self::QINIU_RS)
+ {
+ $token = self::sign(is_string($data) ? $op . "\n" . $data : $op . "\n");
+ $url = $host . $op;
+ $header = array('Authorization: QBox ' . $token);
+
+ if ($ch = curl_init($url))
+ {
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+ if ($data)
+ {
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
+ }
+ curl_setopt($ch, CURLOPT_HEADER, 1);
+ $response = curl_exec($ch);
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+ if ($status == 200)
+ {
+ return true;
+ }
+ // elseif (\Config::get('debug'))
+ // {
+ // /*操作出错*/
+ // \Log::debug($response, '七牛请求出错');
+ // }
+ }
+ Log::error('[QINIU]七牛错误' . $url . ':' . ($response ? : '请求失败'), 'ERROR');
+ return false;
+ }
+
+ /**
+ * 获取url签名
+ *
+ * @param string $url
+ * @return string
+ */
+ private static function sign($url)
+ {
+ $config = self::$_config ? : (self::$_config = Config::get('service.qiniu'));
+ $sign = hash_hmac('sha1', $url, $config['secretkey'], true);
+ $ak = $config['accesskey'];
+ return $ak . ':' . self::qiniuEncode($sign);
+ }
+
+ /**
+ * 七牛安全编码
+ */
+ private static function qiniuEncode($str)
+ {
+ return strtr(base64_encode($str), ['+' => '-', '/' => '_']);
+ }
+
+}
diff --git a/extend/fast/service/Upyun.php b/extend/fast/service/Upyun.php
new file mode 100644
index 00000000..2155aee7
--- /dev/null
+++ b/extend/fast/service/Upyun.php
@@ -0,0 +1,572 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /* }}} */
+
+ /**
+ * 获取当前SDK版本号
+ */
+ public function version()
+ {
+ return self::VERSION;
+ }
+
+ /**
+ * 创建目录
+ * @param $path 路径
+ * @param $auto_mkdir 是否自动创建父级目录,最多10层次
+ *
+ * @return void
+ */
+ public function makeDir($path, $auto_mkdir = false)
+ {/* {{{ */
+ $headers = array('Folder' => 'true');
+ if ($auto_mkdir)
+ $headers['Mkdir'] = 'true';
+ return $this->_do_request('PUT', $path, $headers);
+ }
+
+ /* }}} */
+
+ /**
+ * 删除目录和文件
+ * @param string $path 路径
+ *
+ * @return boolean
+ */
+ public function delete($path)
+ {/* {{{ */
+ return $this->_do_request('DELETE', $path);
+ }
+
+ /* }}} */
+
+ /**
+ * 上传文件
+ * @param string $path 存储路径
+ * @param mixed $file 需要上传的文件,可以是文件流或者文件内容
+ * @param boolean $auto_mkdir 自动创建目录
+ * @param array $opts 可选参数
+ */
+ public function upload($path, $file = NULL, $auto_mkdir = True, $opts = NULL)
+ {
+ return $this->writeFile($path, $file = NULL, $auto_mkdir, $opts);
+ }
+
+ public function writeFile($path, $file = NULL, $auto_mkdir = True, $opts = NULL)
+ {/* {{{ */
+ if (is_null($file))
+ $file = ROOT_PATH . 'public/' . $path;
+ if (is_null($opts))
+ $opts = array();
+ if (!is_null($this->_content_md5) || !is_null($this->_file_secret))
+ {
+ //if (!is_null($this->_content_md5)) array_push($opts, self::CONTENT_MD5 . ": {$this->_content_md5}");
+ //if (!is_null($this->_file_secret)) array_push($opts, self::CONTENT_SECRET . ": {$this->_file_secret}");
+ if (!is_null($this->_content_md5))
+ $opts[self::CONTENT_MD5] = $this->_content_md5;
+ if (!is_null($this->_file_secret))
+ $opts[self::CONTENT_SECRET] = $this->_file_secret;
+ }
+
+ // 如果设置了缩略版本或者缩略图类型,则添加默认压缩质量和锐化参数
+ //if (isset($opts[self::X_GMKERL_THUMBNAIL]) || isset($opts[self::X_GMKERL_TYPE])) {
+ // if (!isset($opts[self::X_GMKERL_QUALITY])) $opts[self::X_GMKERL_QUALITY] = 95;
+ // if (!isset($opts[self::X_GMKERL_UNSHARP])) $opts[self::X_GMKERL_UNSHARP] = 'true';
+ //}
+
+ if ($auto_mkdir === True)
+ $opts['Mkdir'] = 'true';
+
+ $this->_file_infos = $this->_do_request('PUT', $path, $opts, $file);
+
+ return $this->_file_infos;
+ }
+
+ /* }}} */
+
+ /**
+ * 下载文件
+ * @param string $path 文件路径
+ * @param mixed $file_handle
+ *
+ * @return mixed
+ */
+ public function readFile($path, $file_handle = NULL)
+ {/* {{{ */
+ return $this->_do_request('GET', $path, NULL, NULL, $file_handle);
+ }
+
+ /* }}} */
+
+ /**
+ * 获取目录文件列表
+ *
+ * @param string $path 查询路径
+ *
+ * @return mixed
+ */
+ public function getList($path = '/')
+ {/* {{{ */
+ $rsp = $this->_do_request('GET', $path);
+
+ $list = array();
+ if ($rsp)
+ {
+ $rsp = explode("\n", $rsp);
+ foreach ($rsp as $item)
+ {
+ @list($name, $type, $size, $time) = explode("\t", trim($item));
+ if (!empty($time))
+ {
+ $type = $type == 'N' ? 'file' : 'folder';
+ }
+
+ $item = array(
+ 'name' => $name,
+ 'type' => $type,
+ 'size' => intval($size),
+ 'time' => intval($time),
+ );
+ array_push($list, $item);
+ }
+ }
+
+ return $list;
+ }
+
+ /* }}} */
+
+ /**
+ * @deprecated
+ * @param string $path 目录路径
+ * @return mixed
+ */
+ public function getFolderUsage($path = '/')
+ {/* {{{ */
+ $rsp = $this->_do_request('GET', '/?usage');
+ return floatval($rsp);
+ }
+
+ /* }}} */
+
+ /**
+ * 获取文件、目录信息
+ *
+ * @param string $path 路径
+ *
+ * @return mixed
+ */
+ public function getFileInfo($path)
+ {/* {{{ */
+ $rsp = $this->_do_request('HEAD', $path);
+
+ return $rsp;
+ }
+
+ /* }}} */
+
+ /**
+ * 连接签名方法
+ * @param $method 请求方式 {GET, POST, PUT, DELETE}
+ * return 签名字符串
+ */
+ private function sign($method, $uri, $date, $length)
+ {/* {{{ */
+ //$uri = urlencode($uri);
+ $sign = "{$method}&{$uri}&{$date}&{$length}&{$this->config['password']}";
+ return 'UpYun ' . $this->config['username'] . ':' . md5($sign);
+ }
+
+ /* }}} */
+
+ /**
+ * HTTP REQUEST 封装
+ * @param string $method HTTP REQUEST方法,包括PUT、POST、GET、OPTIONS、DELETE
+ * @param string $path 除Bucketname之外的请求路径,包括get参数
+ * @param array $headers 请求需要的特殊HTTP HEADERS
+ * @param array $body 需要POST发送的数据
+ *
+ * @return mixed
+ */
+ protected function _do_request($method, $path, $headers = NULL, $body = NULL, $file_handle = NULL)
+ {/* {{{ */
+ $uri = "/{$this->config['bucket']}{$path}";
+ $ch = curl_init("http://{$this->config['endpoint']}{$uri}");
+
+ $_headers = array('Expect:');
+ if (!is_null($headers) && is_array($headers))
+ {
+ foreach ($headers as $k => $v)
+ {
+ array_push($_headers, "{$k}: {$v}");
+ }
+ }
+
+ $length = 0;
+ $date = gmdate('D, d M Y H:i:s \G\M\T');
+
+ if (!is_null($body))
+ {
+ if (!is_resource($body) && file_exists($body))
+ {
+ $body = fopen($body, "rb");
+ }
+ if (is_resource($body))
+ {
+ fseek($body, 0, SEEK_END);
+ $length = ftell($body);
+ fseek($body, 0);
+
+ array_push($_headers, "Content-Length: {$length}");
+ curl_setopt($ch, CURLOPT_INFILE, $body);
+ curl_setopt($ch, CURLOPT_INFILESIZE, $length);
+ }
+ else
+ {
+ $length = @strlen($body);
+ array_push($_headers, "Content-Length: {$length}");
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
+ }
+ }
+ else
+ {
+ array_push($_headers, "Content-Length: {$length}");
+ }
+
+ array_push($_headers, "Authorization: {$this->sign($method, $uri, $date, $length)}");
+ array_push($_headers, "Date: {$date}");
+
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->config['timeout']);
+ curl_setopt($ch, CURLOPT_HEADER, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+
+ if ($method == 'PUT' || $method == 'POST')
+ {
+ curl_setopt($ch, CURLOPT_POST, 1);
+ }
+ else
+ {
+ curl_setopt($ch, CURLOPT_POST, 0);
+ }
+
+ if ($method == 'GET' && is_resource($file_handle))
+ {
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_FILE, $file_handle);
+ }
+
+ if ($method == 'HEAD')
+ {
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ }
+ $response = curl_exec($ch);
+ $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ if ($http_code == 0)
+ throw new Exception('Connection Failed', $http_code);
+
+ curl_close($ch);
+
+ $header_string = '';
+ $body = '';
+
+ if ($method == 'GET' && is_resource($file_handle))
+ {
+ $header_string = '';
+ $body = $response;
+ }
+ else
+ {
+ list($header_string, $body) = explode("\r\n\r\n", $response, 2);
+ }
+ $this->setXRequestId($header_string);
+ if ($http_code == 200)
+ {
+ if ($method == 'GET' && is_null($file_handle))
+ {
+ return $body;
+ }
+ else
+ {
+ $data = $this->_getHeadersData($header_string);
+ return count($data) > 0 ? $data : true;
+ }
+ }
+ else
+ {
+ $message = $this->_getErrorMessage($header_string);
+ if (is_null($message) && $method == 'GET' && is_resource($file_handle))
+ {
+ $message = 'File Not Found';
+ }
+ switch ($http_code)
+ {
+ case 401:
+ throw new Exception($message, $http_code);
+ break;
+ case 403:
+ throw new Exception($message, $http_code);
+ break;
+ case 404:
+ throw new Exception($message, $http_code);
+ break;
+ case 406:
+ throw new Exception($message, $http_code);
+ break;
+ case 503:
+ throw new Exception($message, $http_code);
+ break;
+ default:
+ throw new Exception($message, $http_code);
+ }
+ }
+ }
+
+ /* }}} */
+
+ /**
+ * 处理HTTP HEADERS中返回的自定义数据
+ *
+ * @param string $text header字符串
+ *
+ * @return array
+ */
+ private function _getHeadersData($text)
+ {/* {{{ */
+ $headers = explode("\r\n", $text);
+ $items = array();
+ foreach ($headers as $header)
+ {
+ $header = trim($header);
+ if (stripos($header, 'x-upyun') !== False)
+ {
+ list($k, $v) = explode(':', $header);
+ $items[trim($k)] = in_array(substr($k, 8, 5), array('width', 'heigh', 'frame')) ? intval($v) : trim($v);
+ }
+ }
+ return $items;
+ }
+
+ /* }}} */
+
+ /**
+ * 获取返回的错误信息
+ *
+ * @param string $header_string
+ *
+ * @return mixed
+ */
+ private function _getErrorMessage($header_string)
+ {
+ list($status, $stash) = explode("\r\n", $header_string, 2);
+ list($v, $code, $message) = explode(" ", $status, 3);
+ return $message . " X-Request-Id: " . $this->getXRequestId();
+ }
+
+ private function setXRequestId($header_string)
+ {
+ preg_match('~^X-Request-Id: ([0-9a-zA-Z]{32})~ism', $header_string, $result);
+ $this->x_request_id = isset($result[1]) ? $result[1] : '';
+ }
+
+ public function getXRequestId()
+ {
+ return $this->x_request_id;
+ }
+
+ /**
+ * 删除目录
+ * @deprecated
+ * @param $path 路径
+ *
+ * @return void
+ */
+ public function rmDir($path)
+ {/* {{{ */
+ $this->_do_request('DELETE', $path);
+ }
+
+ /* }}} */
+
+ /**
+ * 删除文件
+ *
+ * @deprecated
+ * @param string $path 要删除的文件路径
+ *
+ * @return boolean
+ */
+ public function deleteFile($path)
+ {/* {{{ */
+ $rsp = $this->_do_request('DELETE', $path);
+ }
+
+ /* }}} */
+
+ /**
+ * 获取目录文件列表
+ * @deprecated
+ *
+ * @param string $path 要获取列表的目录
+ *
+ * @return array
+ */
+ public function readDir($path)
+ {/* {{{ */
+ return $this->getList($path);
+ }
+
+ /* }}} */
+
+ /**
+ * 获取空间使用情况
+ *
+ * @deprecated 推荐直接使用 getFolderUsage('/')来获取
+ * @return mixed
+ */
+ public function getBucketUsage()
+ {/* {{{ */
+ return $this->getFolderUsage('/');
+ }
+
+ /* }}} */
+
+ /**
+ * 获取文件信息
+ *
+ * #deprecated
+ * @param $file 文件路径(包含文件名)
+ * return array('type'=> file | folder, 'size'=> file size, 'date'=> unix time) 或 null
+ */
+ //public function getFileInfo($file){/*{{{*/
+ // $result = $this->head($file);
+ // if(is_null($r))return null;
+ // return array('type'=> $this->tmp_infos['x-upyun-file-type'], 'size'=> @intval($this->tmp_infos['x-upyun-file-size']), 'date'=> @intval($this->tmp_infos['x-upyun-file-date']));
+ //}/*}}}*/
+
+ /**
+ * 切换 API 接口的域名
+ *
+ * @deprecated
+ * @param $domain {默然 v0.api.upyun.com 自动识别, v1.api.upyun.com 电信, v2.api.upyun.com 联通, v3.api.upyun.com 移动}
+ * return null;
+ */
+ public function setApiDomain($domain)
+ {/* {{{ */
+ $this->config['endpoint'] = $domain;
+ }
+
+ /* }}} */
+
+ /**
+ * 设置待上传文件的 Content-MD5 值(如又拍云服务端收到的文件MD5值与用户设置的不一致,将回报 406 Not Acceptable 错误)
+ *
+ * @deprecated
+ * @param $str (文件 MD5 校验码)
+ * return null;
+ */
+ public function setContentMD5($str)
+ {/* {{{ */
+ $this->_content_md5 = $str;
+ }
+
+ /* }}} */
+
+ /**
+ * 设置待上传文件的 访问密钥(注意:仅支持图片空!,设置密钥后,无法根据原文件URL直接访问,需带 URL 后面加上 (缩略图间隔标志符+密钥) 进行访问)
+ * 如缩略图间隔标志符为 ! ,密钥为 bac,上传文件路径为 /folder/test.jpg ,那么该图片的对外访问地址为: http://空间域名/folder/test.jpg!bac
+ *
+ * @deprecated
+ * @param $str (文件 MD5 校验码)
+ * return null;
+ */
+ public function setFileSecret($str)
+ {/* {{{ */
+ $this->_file_secret = $str;
+ }
+
+ /* }}} */
+
+ /**
+ * @deprecated
+ * 获取上传文件后的信息(仅图片空间有返回数据)
+ * @param $key 信息字段名(x-upyun-width、x-upyun-height、x-upyun-frames、x-upyun-file-type)
+ * return value or NULL
+ */
+ public function getWritedFileInfo($key)
+ {/* {{{ */
+ if (!isset($this->_file_infos))
+ return NULL;
+ return $this->_file_infos[$key];
+ }
+
+ /* }}} */
+}
diff --git a/extend/fast/service/Wechat.php b/extend/fast/service/Wechat.php
new file mode 100644
index 00000000..f64438b2
--- /dev/null
+++ b/extend/fast/service/Wechat.php
@@ -0,0 +1,213 @@
+ array(
+ 'name' => '签到送积分',
+ 'config' => array(
+ )
+ ),
+ 'article' => array(
+ 'name' => '关联文章',
+ 'config' => array(
+ array(
+ 'type' => 'text',
+ 'caption' => '文章ID',
+ 'field' => 'id',
+ 'options' => ''
+ )
+ )
+ ),
+ 'page' => array(
+ 'name' => '关联单页',
+ 'config' => array(
+ array(
+ 'type' => 'text',
+ 'caption' => '单页ID',
+ 'field' => 'id',
+ 'options' => ''
+ )
+ )
+ ),
+ 'service' => array(
+ 'name' => '在线客服',
+ 'config' => array(
+ )
+ ),
+ );
+ }
+
+ // 微信输入交互内容指令
+ public function command($obj, $openid, $content, $context)
+ {
+ $content = [];
+ $response = FALSE;
+ if (isset($content['app']))
+ {
+ switch ($content['app'])
+ {
+ case 'signin':
+ case 'article':
+ case 'page':
+ break;
+ case 'service':
+ $service = configvalue('service');
+ list($begintime, $endtime) = explode('-', $service['onlinetime']);
+ $session = $obj->app->staff_session;
+ $staff = $obj->app->staff;
+
+ $kf_account = $session->get($openid)->kf_account;
+ $time = time();
+ if (!$kf_account && ($time < strtotime(date("Y-m-d {$begintime}")) || $time > strtotime(date("Y-m-d {$endtime}"))))
+ {
+ return $service['offlinemsg'];
+ }
+ if (!$kf_account)
+ {
+ $kf_list = $staff->onlines()->kf_online_list;
+ if ($kf_list)
+ {
+ $kfarr = [];
+ foreach ($kf_list as $k => $v)
+ {
+ $kfarr[$v['kf_account']] = $v['accepted_case'];
+ }
+ $kfkeys = array_keys($kfarr, min($kfarr));
+ $kf_account = reset($kfkeys);
+ $session->create($kf_account, $openid);
+ $response = $service['waitformsg'];
+ }
+ else
+ {
+ $response = $service['nosessionmsg'];
+ }
+ }
+ else
+ {
+ $server = $obj->app->server;
+ $server->setMessageHandler(function($message)
+ {
+ return new Transfer();
+ });
+ $response = $server->serve();
+ $response->send();
+ exit;
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ $response = isset($content['content']) ? $content['content'] : $response;
+ }
+ return $response;
+ }
+
+ // 微信点击菜单event指令
+ public function response($obj, $openid, $content, $context)
+ {
+ $content = [];
+ $response = FALSE;
+ if (isset($content['app']))
+ {
+ switch ($content['app'])
+ {
+ case 'signin':
+ $thirdinfo = UserThird::get(['platform' => 'wechat', 'openid' => $openid]);
+ if (!$thirdinfo)
+ {
+ $response = '您还没有绑定用户还不能签到!';
+ }
+ else
+ {
+ $user_id = $thirdinfo->user_id;
+ $usersign = new UserSignin;
+ $signdata = $usersign->get([['user_id', '=', $user_id], ['createtime', '>=', Date::unixtime()]]);
+ if ($signdata)
+ {
+ $response = '今天已签到,请明天再来!';
+ }
+ else
+ {
+ $signdata = configvalue('signin');
+
+ $lastdata = $usersign->where('user_id', $user_id)->order('id', 'desc')->limit(1)->get();
+ $successions = $lastdata && $lastdata['createtime'] > Date::unixtime('day', -1) ? $lastdata['successions'] + 1 : 1;
+ $usersign->save(['user_id' => $thirdinfo['user_id'], 'successions' => $successions, 'createtime' => time()]);
+ $score = isset($signdata['s' . $successions]) ? $signdata['s' . $successions] : $signdata['sn'];
+ User::where(['id' => $user_id])->setInc('score', $score);
+ $response = '签到成功!连续签到' . $successions . '天!获得' . $score . '积分';
+ }
+ }
+
+ break;
+ case 'article':
+ $id = explode(',', $content['id']);
+ $pagelist = Page::all($id);
+ $response = [];
+ foreach ($pagelist as $k => $pageinfo)
+ {
+ if ($pageinfo)
+ {
+ $news = new News();
+ $news->title = $pageinfo['title'];
+ $news->url = $pageinfo['outlink'] ? $pageinfo['outlink'] : url('page/show/' . $pageinfo['id'], 1);
+ $news->image = cdn($pageinfo['image']);
+ $news->description = $pageinfo['description'];
+ $response[] = $news;
+ }
+ }
+
+ case 'page':
+ $id = isset($content['id']) ? $content['id'] : 0;
+ $pageinfo = Page::get($id);
+ if ($pageinfo)
+ {
+ $news = new News();
+ $news->title = $pageinfo['title'];
+ $news->url = $pageinfo['outlink'] ? $pageinfo['outlink'] : url('page/show/' . $pageinfo['id'], 1);
+ $news->image = cdn($pageinfo['image']);
+ $news->description = $pageinfo['description'];
+ return $news;
+ }
+ break;
+ case 'service':
+ $response = $this->command($obj, $openid, $content, $context);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ $response = isset($content['content']) ? $content['content'] : $response;
+ }
+ return $response;
+ }
+
+}
diff --git a/extend/fast/third/Application.php b/extend/fast/third/Application.php
new file mode 100644
index 00000000..de16a3a6
--- /dev/null
+++ b/extend/fast/third/Application.php
@@ -0,0 +1,76 @@
+ 'Qq',
+ 'weibo' => 'Weibo',
+ 'wechat' => 'Wechat',
+ ];
+
+ /**
+ * 服务对象信息
+ * @var array
+ */
+ protected $services = [];
+
+ public function __construct($options = [])
+ {
+ if ($config = Config::get('third'))
+ {
+ $this->config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+
+ //注册服务器提供者
+ $this->registerProviders();
+ }
+
+ /**
+ * 注册服务提供者
+ */
+ private function registerProviders()
+ {
+ foreach ($this->providers as $k => $v)
+ {
+ $this->services[$k] = function() use ($k, $v)
+ {
+ $options = $this->config[$k];
+ $options['app_id'] = isset($options['app_id']) ? $options['app_id'] : '';
+ $options['app_secret'] = isset($options['app_secret']) ? $options['app_secret'] : '';
+ // 如果未定义回调地址则自动生成
+ $options['callback'] = isset($options['callback']) && $options['callback'] ? $options['callback'] : url('user/third?action=callback&platform=' . $k, [], false, true);
+ // 如果非http地址则转换一下
+ $options['callback'] = substr($options['callback'], 0, 7) == 'http://' || substr($options['callback'], 0, 8) == 'https://' ? $options['callback'] : url($options['callback'], '', false, true);
+ $objname = __NAMESPACE__ . "\\{$v}";
+ return new $objname($options);
+ };
+ }
+ }
+
+ public function __set($key, $value)
+ {
+ $this->services[$key] = $value;
+ }
+
+ public function __get($key)
+ {
+ return $this->services[$key]($this);
+ }
+
+}
diff --git a/extend/fast/third/Qq.php b/extend/fast/third/Qq.php
new file mode 100644
index 00000000..f7a2e65b
--- /dev/null
+++ b/extend/fast/third/Qq.php
@@ -0,0 +1,145 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * 登陆
+ */
+ public function login()
+ {
+ header("Location:" . $this->getAuthorizeUrl());
+ }
+
+ /**
+ * 获取authorize_url
+ */
+ public function getAuthorizeUrl()
+ {
+ $state = md5(uniqid(rand(), TRUE));
+ Session::set('state', $state);
+ $queryarr = array(
+ "response_type" => "code",
+ "client_id" => $this->config['app_id'],
+ "redirect_uri" => $this->config['callback'],
+ "scope" => $this->config['scope'],
+ "state" => $state,
+ );
+ request()->isMobile() && $queryarr['display'] = 'mobile';
+ $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr);
+ return $url;
+ }
+
+ /**
+ * 获取用户信息
+ * @param array $params
+ * @return array
+ */
+ public function getUserInfo($params = [])
+ {
+ $params = $params ? $params : $_GET;
+ if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code'])))
+ {
+ //获取access_token
+ $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
+ $access_token = isset($data['access_token']) ? $data['access_token'] : '';
+ $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
+ $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
+ if ($access_token)
+ {
+ $openid = $this->getOpenId($access_token);
+ //获取用户信息
+ $queryarr = [
+ "access_token" => $access_token,
+ "oauth_consumer_key" => $this->config['app_id'],
+ "openid" => $openid,
+ ];
+ $ret = Http::get(self::GET_USERINFO_URL, $queryarr);
+ $userinfo = json_decode($ret, TRUE);
+ if (!$userinfo || !isset($userinfo['ret']) || $userinfo['ret'] !== 0)
+ return [];
+ $userinfo = $userinfo ? $userinfo : [];
+ $userinfo['avatar'] = isset($userinfo['figureurl_qq_2']) ? $userinfo['figureurl_qq_2'] : '';
+ $data = [
+ 'access_token' => $access_token,
+ 'refresh_token' => $refresh_token,
+ 'expires_in' => $expires_in,
+ 'openid' => $openid,
+ 'userinfo' => $userinfo
+ ];
+ return $data;
+ }
+ }
+ return [];
+ }
+
+ /**
+ * 获取access_token
+ * @param string $code
+ * @return array
+ */
+ private function getAccessToken($code = '')
+ {
+ if (!$code)
+ return '';
+ $queryarr = array(
+ "grant_type" => "authorization_code",
+ "client_id" => $this->config['app_id'],
+ "client_secret" => $this->config['app_secret'],
+ "redirect_uri" => $this->config['callback'],
+ "code" => $code,
+ );
+ $ret = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr);
+ $params = [];
+ parse_str($ret, $params);
+ return $params ? $params : [];
+ }
+
+ /**
+ * 获取open_id
+ * @param string $access_token
+ * @return string
+ */
+ private function getOpenId($access_token = '')
+ {
+ $response = Http::get(self::GET_OPENID_URL, ['access_token' => $access_token]);
+ if (strpos($response, "callback") !== false)
+ {
+ $lpos = strpos($response, "(");
+ $rpos = strrpos($response, ")");
+ $response = substr($response, $lpos + 1, $rpos - $lpos - 1);
+ }
+ $user = json_decode($response, TRUE);
+ return isset($user['openid']) ? $user['openid'] : '';
+ }
+
+}
diff --git a/extend/fast/third/Wechat.php b/extend/fast/third/Wechat.php
new file mode 100644
index 00000000..6dd7f292
--- /dev/null
+++ b/extend/fast/third/Wechat.php
@@ -0,0 +1,124 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * 登陆
+ */
+ public function login()
+ {
+ header("Location:" . $this->getAuthorizeUrl());
+ }
+
+ /**
+ * 获取authorize_url
+ */
+ public function getAuthorizeUrl()
+ {
+ $state = md5(uniqid(rand(), TRUE));
+ Session::set('state', $state);
+ $queryarr = array(
+ "app_id" => $this->config['app_id'],
+ "redirect_uri" => $this->config['callback'],
+ "response_type" => "code",
+ "scope" => $this->config['scope'],
+ "state" => $state,
+ );
+ request()->isMobile() && $queryarr['display'] = 'mobile';
+ $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect';
+ return $url;
+ }
+
+ /**
+ * 获取用户信息
+ * @param array $params
+ * @return array
+ */
+ public function getUserInfo($params = [])
+ {
+ $params = $params ? $params : $_GET;
+ if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code'])))
+ {
+ //获取access_token
+ $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
+ $access_token = isset($data['access_token']) ? $data['access_token'] : '';
+ $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
+ $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
+ if ($access_token)
+ {
+ $openid = isset($data['openid']) ? $data['openid'] : '';
+ //获取用户信息
+ $queryarr = [
+ "access_token" => $access_token,
+ "openid" => $openid,
+ "lang" => 'zh_CN'
+ ];
+ $ret = Http::post(self::GET_USERINFO_URL, $queryarr);
+ $userinfo = json_decode($ret, TRUE);
+ if (!$userinfo || isset($userinfo['errcode']))
+ return [];
+ $userinfo = $userinfo ? $userinfo : [];
+ $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : '';
+ $data = [
+ 'access_token' => $access_token,
+ 'refresh_token' => $refresh_token,
+ 'expires_in' => $expires_in,
+ 'openid' => $openid,
+ 'userinfo' => $userinfo
+ ];
+ return $data;
+ }
+ }
+ return [];
+ }
+
+ /**
+ * 获取access_token
+ * @param string code
+ * @return array
+ */
+ private function getAccessToken($code = '')
+ {
+ if (!$code)
+ return '';
+ $queryarr = array(
+ "appid" => $this->config['app_id'],
+ "secret" => $this->config['app_secret'],
+ "code" => $code,
+ "grant_type" => "authorization_code",
+ );
+ $response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr);
+ $ret = json_decode($response, TRUE);
+ return $ret ? $ret : [];
+ }
+
+}
diff --git a/extend/fast/third/Weibo.php b/extend/fast/third/Weibo.php
new file mode 100644
index 00000000..fb1dbabc
--- /dev/null
+++ b/extend/fast/third/Weibo.php
@@ -0,0 +1,124 @@
+config = array_merge($this->config, $config);
+ }
+ $this->config = array_merge($this->config, is_array($options) ? $options : []);
+ }
+
+ /**
+ * 登陆
+ */
+ public function login()
+ {
+ header("Location:" . $this->getAuthorizeUrl());
+ }
+
+ /**
+ * 获取authorize_url
+ */
+ public function getAuthorizeUrl()
+ {
+ $state = md5(uniqid(rand(), TRUE));
+ Session::set('state', $state);
+ $queryarr = array(
+ "response_type" => "code",
+ "client_id" => $this->config['app_id'],
+ "redirect_uri" => $this->config['callback'],
+ "state" => $state,
+ );
+ request()->isMobile() && $queryarr['display'] = 'mobile';
+ $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr);
+ return $url;
+ }
+
+ /**
+ * 获取用户信息
+ * @param array $params
+ * @return array
+ */
+ public function getUserInfo($params = [])
+ {
+ $params = $params ? $params : $_GET;
+ if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code'])))
+ {
+ //获取access_token
+ $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params;
+ $access_token = isset($data['access_token']) ? $data['access_token'] : '';
+ $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
+ $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
+ if ($access_token)
+ {
+ $uid = isset($data['uid']) ? $data['uid'] : '';
+ //获取用户信息
+ $queryarr = [
+ "access_token" => $access_token,
+ "uid" => $uid,
+ ];
+ $ret = Http::get(self::GET_USERINFO_URL, $queryarr);
+ $userinfo = json_decode($ret, TRUE);
+ if (!$userinfo || isset($userinfo['error_code']))
+ return [];
+ $userinfo = $userinfo ? $userinfo : [];
+ $userinfo['nickname'] = isset($userinfo['screen_name']) ? $userinfo['screen_name'] : '';
+ $userinfo['avatar'] = isset($userinfo['profile_image_url']) ? $userinfo['profile_image_url'] : '';
+ $data = [
+ 'access_token' => $access_token,
+ 'refresh_token' => $refresh_token,
+ 'expires_in' => $expires_in,
+ 'openid' => $uid,
+ 'userinfo' => $userinfo
+ ];
+ return $data;
+ }
+ }
+ return [];
+ }
+
+ /**
+ * 获取access_token
+ * @param string code
+ * @return array
+ */
+ private function getAccessToken($code = '')
+ {
+ if (!$code)
+ return '';
+ $queryarr = array(
+ "grant_type" => "authorization_code",
+ "client_id" => $this->config['app_id'],
+ "client_secret" => $this->config['app_secret'],
+ "redirect_uri" => $this->config['callback'],
+ "code" => $code,
+ );
+ $response = Http::post(self::GET_ACCESS_TOKEN_URL, $queryarr);
+ $ret = json_decode($response, TRUE);
+ return $ret ? $ret : [];
+ }
+
+}
diff --git a/extend/fast/ucenter/client/Client.php b/extend/fast/ucenter/client/Client.php
new file mode 100644
index 00000000..58ed17be
--- /dev/null
+++ b/extend/fast/ucenter/client/Client.php
@@ -0,0 +1,31 @@
+initConfig();
+ Loader::import('client', dirname(__FILE__) . "/uc_client/"); //加载uc客户端主脚本
+ }
+
+ //加载配置
+ public function initConfig()
+ {
+ if (!defined('UC_API'))
+ {
+ new Exception('未发现uc常量配置信息');
+ }
+ }
+
+ function __call($method, $params)
+ {
+ return call_user_func_array($method, $params);
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/client.php b/extend/fast/ucenter/client/uc_client/client.php
new file mode 100644
index 00000000..67f361ff
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/client.php
@@ -0,0 +1,840 @@
+ $val)
+ {
+ $string[$key] = uc_addslashes($val, $force, $strip);
+ }
+ }
+ else
+ {
+ $string = addslashes($strip ? stripslashes($string) : $string);
+ }
+ }
+ return $string;
+}
+
+if (!function_exists('daddslashes'))
+{
+
+ function daddslashes($string, $force = 0)
+ {
+ return uc_addslashes($string, $force);
+ }
+
+}
+
+if (!function_exists('dhtmlspecialchars'))
+{
+
+ function dhtmlspecialchars($string, $flags = null)
+ {
+ if (is_array($string))
+ {
+ foreach ($string as $key => $val)
+ {
+ $string[$key] = dhtmlspecialchars($val, $flags);
+ }
+ }
+ else
+ {
+ if ($flags === null)
+ {
+ $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
+ if (strpos($string, '&#') !== false)
+ {
+ $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
+ }
+ }
+ else
+ {
+ if (PHP_VERSION < '5.4.0')
+ {
+ $string = htmlspecialchars($string, $flags);
+ }
+ else
+ {
+ if (strtolower(CHARSET) == 'utf-8')
+ {
+ $charset = 'UTF-8';
+ }
+ else
+ {
+ $charset = 'ISO-8859-1';
+ }
+ $string = htmlspecialchars($string, $flags, $charset);
+ }
+ }
+ }
+ return $string;
+ }
+
+}
+
+if (!function_exists('fsocketopen'))
+{
+
+ function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15)
+ {
+ $fp = '';
+ if (function_exists('fsockopen'))
+ {
+ $fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout);
+ }
+ elseif (function_exists('pfsockopen'))
+ {
+ $fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout);
+ }
+ elseif (function_exists('stream_socket_client'))
+ {
+ $fp = @stream_socket_client($hostname . ':' . $port, $errno, $errstr, $timeout);
+ }
+ return $fp;
+ }
+
+}
+
+function uc_stripslashes($string)
+{
+ !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
+ if (MAGIC_QUOTES_GPC)
+ {
+ return stripslashes($string);
+ }
+ else
+ {
+ return $string;
+ }
+}
+
+// 采用POST请求形式
+function uc_api_post($module, $action, $arg = array())
+{
+ $s = $sep = '';
+ foreach ($arg as $k => $v)
+ {
+ $k = urlencode($k);
+ if (is_array($v))
+ {
+ $s2 = $sep2 = '';
+ foreach ($v as $k2 => $v2)
+ {
+ $k2 = urlencode($k2);
+ $s2 .= "$sep2{$k}[$k2]=" . urlencode(uc_stripslashes($v2));
+ $sep2 = '&';
+ }
+ $s .= $sep . $s2;
+ }
+ else
+ {
+ $s .= "$sep$k=" . urlencode(uc_stripslashes($v));
+ }
+ $sep = '&';
+ }
+ $postdata = uc_api_requestdata($module, $action, $s);
+ return uc_fopen2(UC_API . '/index.php', 500000, $postdata, '', TRUE, UC_IP, 20);
+}
+
+function uc_api_requestdata($module, $action, $arg = '', $extra = '')
+{
+ $input = uc_api_input($arg);
+ $post = "m=$module&a=$action&inajax=2&release=" . UC_CLIENT_RELEASE . "&input=$input&appid=" . UC_APPID . $extra;
+ return $post;
+}
+
+function uc_api_url($module, $action, $arg = '', $extra = '')
+{
+ $url = UC_API . '/index.php?' . uc_api_requestdata($module, $action, $arg, $extra);
+ return $url;
+}
+
+function uc_api_input($data)
+{
+ $s = urlencode(uc_authcode($data . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . "&time=" . time(), 'ENCODE', UC_KEY));
+ return $s;
+}
+
+// 直连数据库的形式
+function uc_api_mysql($model, $action, $args = array())
+{
+ global $uc_controls;
+ if (empty($uc_controls[$model]))
+ {
+ // 优先使用mysqli
+ if (function_exists("mysqli_connect"))
+ {
+ include_once UC_ROOT . './lib/dbi.class.php';
+ }
+ else
+ {
+ include_once UC_ROOT . './lib/db.class.php';
+ }
+ include_once UC_ROOT . './model/base.php';
+ include_once UC_ROOT . "./control/$model.php";
+ $classname = $model . 'control';
+ $uc_controls[$model] = new $classname();
+ }
+ if ($action{0} != '_')
+ {
+ $args = uc_addslashes($args, 1, TRUE);
+ $action = 'on' . $action;
+ $uc_controls[$model]->input = $args;
+ return $uc_controls[$model]->$action($args);
+ }
+ else
+ {
+ return '';
+ }
+}
+
+function uc_serialize($arr, $htmlon = 0)
+{
+ include_once UC_ROOT . './lib/xml.class.php';
+ return xml_serialize($arr, $htmlon);
+}
+
+function uc_unserialize($s)
+{
+ include_once UC_ROOT . './lib/xml.class.php';
+ return @xml_unserialize($s);
+}
+
+function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
+{
+
+ $ckey_length = 4;
+
+ $key = md5($key ? $key : UC_KEY);
+ $keya = md5(substr($key, 0, 16));
+ $keyb = md5(substr($key, 16, 16));
+ $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
+
+ $cryptkey = $keya . md5($keya . $keyc);
+ $key_length = strlen($cryptkey);
+
+ $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
+ $string_length = strlen($string);
+
+ $result = '';
+ $box = range(0, 255);
+
+ $rndkey = array();
+ for ($i = 0; $i <= 255; $i++)
+ {
+ $rndkey[$i] = ord($cryptkey[$i % $key_length]);
+ }
+
+ for ($j = $i = 0; $i < 256; $i++)
+ {
+ $j = ($j + $box[$i] + $rndkey[$i]) % 256;
+ $tmp = $box[$i];
+ $box[$i] = $box[$j];
+ $box[$j] = $tmp;
+ }
+
+ for ($a = $j = $i = 0; $i < $string_length; $i++)
+ {
+ $a = ($a + 1) % 256;
+ $j = ($j + $box[$a]) % 256;
+ $tmp = $box[$a];
+ $box[$a] = $box[$j];
+ $box[$j] = $tmp;
+ $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
+ }
+
+ if ($operation == 'DECODE')
+ {
+ if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16))
+ {
+ return substr($result, 26);
+ }
+ else
+ {
+ return '';
+ }
+ }
+ else
+ {
+ return $keyc . str_replace('=', '', base64_encode($result));
+ }
+}
+
+function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE)
+{
+ $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1;
+ if ($__times__ > 2)
+ {
+ return '';
+ }
+ $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__";
+ return uc_fopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block);
+}
+
+function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE)
+{
+ $return = '';
+ $matches = parse_url($url);
+ !isset($matches['scheme']) && $matches['scheme'] = '';
+ !isset($matches['host']) && $matches['host'] = '';
+ !isset($matches['path']) && $matches['path'] = '';
+ !isset($matches['query']) && $matches['query'] = '';
+ !isset($matches['port']) && $matches['port'] = '';
+ $scheme = $matches['scheme'];
+ $host = $matches['host'];
+ $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/';
+ $port = !empty($matches['port']) ? $matches['port'] : 80;
+ if ($post)
+ {
+ $out = "POST $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+ $header .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n";
+ $header .= "Host: $host\r\n";
+ $header .= 'Content-Length: ' . strlen($post) . "\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cache-Control: no-cache\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header . $post;
+ }
+ else
+ {
+ $out = "GET $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $header .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n";
+ $header .= "Host: $host\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header;
+ }
+ $fpflag = 0;
+ if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout))
+ {
+ $context = array(
+ 'http' => array(
+ 'method' => $post ? 'POST' : 'GET',
+ 'header' => $header,
+ 'content' => $post,
+ 'timeout' => $timeout,
+ ),
+ );
+ $context = stream_context_create($context);
+ $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context);
+ $fpflag = 1;
+ }
+ if (!$fp)
+ {
+ return '';
+ }
+ else
+ {
+ stream_set_blocking($fp, $block);
+ stream_set_timeout($fp, $timeout);
+ @fwrite($fp, $out);
+ $status = stream_get_meta_data($fp);
+ if (!$status['timed_out'])
+ {
+ while (!feof($fp) && !$fpflag)
+ {
+ if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n"))
+ {
+ break;
+ }
+ }
+
+ $stop = false;
+ while (!feof($fp) && !$stop)
+ {
+ $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
+ $return .= $data;
+ if ($limit)
+ {
+ $limit -= strlen($data);
+ $stop = $limit <= 0;
+ }
+ }
+ }
+ @fclose($fp);
+ return $return;
+ }
+}
+
+function uc_app_ls()
+{
+ $return = call_user_func(UC_API_FUNC, 'app', 'ls', array());
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_feed_add($icon, $uid, $username, $title_template = '', $title_data = '', $body_template = '', $body_data = '', $body_general = '', $target_ids = '', $images = array())
+{
+ return call_user_func(UC_API_FUNC, 'feed', 'add', array(
+ 'icon' => $icon,
+ 'appid' => UC_APPID,
+ 'uid' => $uid,
+ 'username' => $username,
+ 'title_template' => $title_template,
+ 'title_data' => $title_data,
+ 'body_template' => $body_template,
+ 'body_data' => $body_data,
+ 'body_general' => $body_general,
+ 'target_ids' => $target_ids,
+ 'image_1' => $images[0]['url'],
+ 'image_1_link' => $images[0]['link'],
+ 'image_2' => $images[1]['url'],
+ 'image_2_link' => $images[1]['link'],
+ 'image_3' => $images[2]['url'],
+ 'image_3_link' => $images[2]['link'],
+ 'image_4' => $images[3]['url'],
+ 'image_4_link' => $images[3]['link']
+ )
+ );
+}
+
+function uc_feed_get($limit = 100, $delete = TRUE)
+{
+ $return = call_user_func(UC_API_FUNC, 'feed', 'get', array('limit' => $limit, 'delete' => $delete));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_friend_add($uid, $friendid, $comment = '')
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'add', array('uid' => $uid, 'friendid' => $friendid, 'comment' => $comment));
+}
+
+function uc_friend_delete($uid, $friendids)
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'delete', array('uid' => $uid, 'friendids' => $friendids));
+}
+
+function uc_friend_totalnum($uid, $direction = 0)
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'totalnum', array('uid' => $uid, 'direction' => $direction));
+}
+
+function uc_friend_ls($uid, $page = 1, $pagesize = 10, $totalnum = 10, $direction = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'friend', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'totalnum' => $totalnum, 'direction' => $direction));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_user_register($username, $password, $email = '', $mobile = '', $extend = [])
+{
+ return call_user_func(UC_API_FUNC, 'user', 'register', array('username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend));
+}
+
+function uc_user_login($username, $password, $isuid = 0, $extend = [])
+{
+ $isuid = intval($isuid);
+ $return = call_user_func(UC_API_FUNC, 'user', 'login', array('username' => $username, 'password' => $password, 'isuid' => $isuid, 'extend' => $extend));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+/**
+ * 同步注册
+ * @param int $uid
+ * @param string $password
+ * @return string
+ */
+function uc_user_synregister($uid, $password)
+{
+ $uid = intval($uid);
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synregister', array('uid' => $uid, 'password' => $password));
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+/**
+ * 同步登录
+ * @param int $uid
+ * @return string
+ */
+function uc_user_synlogin($uid)
+{
+ $uid = intval($uid);
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synlogin', array('uid' => $uid));
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+/**
+ * 同步退出
+ * @return string
+ */
+function uc_user_synlogout()
+{
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synlogout', array());
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+/**
+ * 修改用户信息
+ * @param int $uid 会员ID
+ * @param string $username 用户名
+ * @param string $password 密码
+ * @param string $email 邮箱
+ * @param string $mobile 手机号
+ * @param array $extend 扩展信息
+ * @return type
+ */
+function uc_user_edit($uid, $username, $password, $email = '', $mobile = '', $extend = [])
+{
+ return call_user_func(UC_API_FUNC, 'user', 'edit', array('uid' => $uid, 'username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend));
+}
+
+function uc_user_delete($uid)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'delete', array('uid' => $uid));
+}
+
+function uc_user_deleteavatar($uid)
+{
+ uc_api_post('user', 'deleteavatar', array('uid' => $uid));
+}
+
+function uc_user_checkname($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_username', array('username' => $username));
+}
+
+function uc_user_checkemail($email)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_email', array('email' => $email));
+}
+
+function uc_user_checkmobile($mobile)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_mobile', array('mobile' => $mobile));
+}
+
+function uc_user_addprotected($username, $admin = '')
+{
+ return call_user_func(UC_API_FUNC, 'user', 'addprotected', array('username' => $username, 'admin' => $admin));
+}
+
+function uc_user_deleteprotected($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'deleteprotected', array('username' => $username));
+}
+
+function uc_user_getprotected()
+{
+ $return = call_user_func(UC_API_FUNC, 'user', 'getprotected', array('1' => 1));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_get_user($username, $isuid = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'user', 'get_user', array('username' => $username, 'isuid' => $isuid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_user_merge($oldusername, $newusername, $uid, $password, $email)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'merge', array('oldusername' => $oldusername, 'newusername' => $newusername, 'uid' => $uid, 'password' => $password, 'email' => $email));
+}
+
+function uc_user_merge_remove($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'merge_remove', array('username' => $username));
+}
+
+function uc_user_getcredit($appid, $uid, $credit)
+{
+ return uc_api_post('user', 'getcredit', array('appid' => $appid, 'uid' => $uid, 'credit' => $credit));
+}
+
+function uc_user_logincheck($username, $ip)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'logincheck', array('username' => $username, 'ip' => $ip));
+}
+
+function uc_pm_location($uid, $newpm = 0)
+{
+ $apiurl = uc_api_url('pm_client', 'ls', "uid=$uid", ($newpm ? '&folder=newbox' : ''));
+ @header("Expires: 0");
+ @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE);
+ @header("Pragma: no-cache");
+ @header("location: $apiurl");
+}
+
+function uc_pm_checknew($uid, $more = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'pm', 'check_newpm', array('uid' => $uid, 'more' => $more));
+ return (!$more || UC_CONNECT == 'mysql') ? $return : uc_unserialize($return);
+}
+
+function uc_pm_send($fromuid, $msgto, $subject, $message, $instantly = 1, $replypmid = 0, $isusername = 0, $type = 0)
+{
+ if ($instantly)
+ {
+ $replypmid = @is_numeric($replypmid) ? $replypmid : 0;
+ return call_user_func(UC_API_FUNC, 'pm', 'sendpm', array('fromuid' => $fromuid, 'msgto' => $msgto, 'subject' => $subject, 'message' => $message, 'replypmid' => $replypmid, 'isusername' => $isusername, 'type' => $type));
+ }
+ else
+ {
+ $fromuid = intval($fromuid);
+ $subject = rawurlencode($subject);
+ $msgto = rawurlencode($msgto);
+ $message = rawurlencode($message);
+ $replypmid = @is_numeric($replypmid) ? $replypmid : 0;
+ $replyadd = $replypmid ? "&pmid=$replypmid&do=reply" : '';
+ $apiurl = uc_api_url('pm_client', 'send', "uid=$fromuid", "&msgto=$msgto&subject=$subject&message=$message$replyadd");
+ @header("Expires: 0");
+ @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE);
+ @header("Pragma: no-cache");
+ @header("location: " . $apiurl);
+ }
+}
+
+function uc_pm_delete($uid, $folder, $pmids)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'delete', array('uid' => $uid, 'pmids' => $pmids));
+}
+
+function uc_pm_deleteuser($uid, $touids)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'deleteuser', array('uid' => $uid, 'touids' => $touids));
+}
+
+function uc_pm_deletechat($uid, $plids, $type = 0)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'deletechat', array('uid' => $uid, 'plids' => $plids, 'type' => $type));
+}
+
+function uc_pm_readstatus($uid, $uids, $plids = array(), $status = 0)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'readstatus', array('uid' => $uid, 'uids' => $uids, 'plids' => $plids, 'status' => $status));
+}
+
+function uc_pm_list($uid, $page = 1, $pagesize = 10, $folder = 'inbox', $filter = 'newpm', $msglen = 0)
+{
+ $uid = intval($uid);
+ $page = intval($page);
+ $pagesize = intval($pagesize);
+ $return = call_user_func(UC_API_FUNC, 'pm', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'filter' => $filter, 'msglen' => $msglen));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_ignore($uid)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'ignore', array('uid' => $uid));
+}
+
+function uc_pm_view($uid, $pmid = 0, $touid = 0, $daterange = 1, $page = 0, $pagesize = 10, $type = 0, $isplid = 0)
+{
+ $uid = intval($uid);
+ $touid = intval($touid);
+ $page = intval($page);
+ $pagesize = intval($pagesize);
+ $pmid = @is_numeric($pmid) ? $pmid : 0;
+ $return = call_user_func(UC_API_FUNC, 'pm', 'view', array('uid' => $uid, 'pmid' => $pmid, 'touid' => $touid, 'daterange' => $daterange, 'page' => $page, 'pagesize' => $pagesize, 'type' => $type, 'isplid' => $isplid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_view_num($uid, $touid, $isplid)
+{
+ $uid = intval($uid);
+ $touid = intval($touid);
+ $isplid = intval($isplid);
+ return call_user_func(UC_API_FUNC, 'pm', 'viewnum', array('uid' => $uid, 'touid' => $touid, 'isplid' => $isplid));
+}
+
+function uc_pm_viewnode($uid, $type, $pmid)
+{
+ $uid = intval($uid);
+ $type = intval($type);
+ $pmid = @is_numeric($pmid) ? $pmid : 0;
+ $return = call_user_func(UC_API_FUNC, 'pm', 'viewnode', array('uid' => $uid, 'type' => $type, 'pmid' => $pmid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_chatpmmemberlist($uid, $plid = 0)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $return = call_user_func(UC_API_FUNC, 'pm', 'chatpmmemberlist', array('uid' => $uid, 'plid' => $plid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_kickchatpm($plid, $uid, $touid)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $touid = intval($touid);
+ return call_user_func(UC_API_FUNC, 'pm', 'kickchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid));
+}
+
+function uc_pm_appendchatpm($plid, $uid, $touid)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $touid = intval($touid);
+ return call_user_func(UC_API_FUNC, 'pm', 'appendchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid));
+}
+
+function uc_pm_blackls_get($uid)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_get', array('uid' => $uid));
+}
+
+function uc_pm_blackls_set($uid, $blackls)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_set', array('uid' => $uid, 'blackls' => $blackls));
+}
+
+function uc_pm_blackls_add($uid, $username)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_add', array('uid' => $uid, 'username' => $username));
+}
+
+function uc_pm_blackls_delete($uid, $username)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_delete', array('uid' => $uid, 'username' => $username));
+}
+
+function uc_domain_ls()
+{
+ $return = call_user_func(UC_API_FUNC, 'domain', 'ls', array('1' => 1));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_credit_exchange_request($uid, $from, $to, $toappid, $amount)
+{
+ $uid = intval($uid);
+ $from = intval($from);
+ $toappid = intval($toappid);
+ $to = intval($to);
+ $amount = intval($amount);
+ return uc_api_post('credit', 'request', array('uid' => $uid, 'from' => $from, 'to' => $to, 'toappid' => $toappid, 'amount' => $amount));
+}
+
+function uc_tag_get($tagname, $nums = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'tag', 'gettag', array('tagname' => $tagname, 'nums' => $nums));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_avatar($uid, $type = 'virtual', $returnhtml = 1)
+{
+ $uid = intval($uid);
+ $uc_input = uc_api_input("uid=$uid");
+ $uc_avatarflash = UC_API . '/images/camera.swf?inajax=1&appid=' . UC_APPID . '&input=' . $uc_input . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . '&ucapi=' . urlencode(str_replace('http://', '', UC_API)) . '&avatartype=' . $type . '&uploadSize=2048';
+ if ($returnhtml)
+ {
+ return '';
+ }
+ else
+ {
+ return array(
+ 'width', '450',
+ 'height', '253',
+ 'scale', 'exactfit',
+ 'src', $uc_avatarflash,
+ 'id', 'mycamera',
+ 'name', 'mycamera',
+ 'quality', 'high',
+ 'bgcolor', '#ffffff',
+ 'menu', 'false',
+ 'swLiveConnect', 'true',
+ 'allowScriptAccess', 'always'
+ );
+ }
+}
+
+function uc_mail_queue($uids, $emails, $subject, $message, $frommail = '', $charset = 'gbk', $htmlon = FALSE, $level = 1)
+{
+ return call_user_func(UC_API_FUNC, 'mail', 'add', array('uids' => $uids, 'emails' => $emails, 'subject' => $subject, 'message' => $message, 'frommail' => $frommail, 'charset' => $charset, 'htmlon' => $htmlon, 'level' => $level));
+}
+
+function uc_check_avatar($uid, $size = 'middle', $type = 'virtual')
+{
+ $url = UC_API . "/avatar.php?uid=$uid&size=$size&type=$type&check_file_exists=1";
+ $res = uc_fopen2($url, 500000, '', '', TRUE, UC_IP, 20);
+ if ($res == 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+function uc_check_version()
+{
+ $return = uc_api_post('version', 'check', array());
+ $data = uc_unserialize($return);
+ return is_array($data) ? $data : $return;
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/app.php b/extend/fast/ucenter/client/uc_client/control/app.php
new file mode 100644
index 00000000..dc66f54b
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/app.php
@@ -0,0 +1,63 @@
+appcontrol();
+ }
+
+ function appcontrol()
+ {
+ parent::__construct();
+ $this->load('app');
+ }
+
+ function onls()
+ {
+ $this->init_input();
+ $applist = $_ENV['app']->get_apps('appid, type, name, url, tagtemplates, viewprourl, synlogin');
+ $applist2 = array();
+ foreach ($applist as $key => $app)
+ {
+ $app['tagtemplates'] = $this->unserialize($app['tagtemplates']);
+ $applist2[$app['appid']] = $app;
+ }
+ return $applist2;
+ }
+
+ function onadd()
+ {
+
+ }
+
+ function onucinfo()
+ {
+
+ }
+
+ function _random($length, $numeric = 0)
+ {
+
+ }
+
+ function _generate_key()
+ {
+
+ }
+
+ function _format_notedata($notedata)
+ {
+
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/cache.php b/extend/fast/ucenter/client/uc_client/control/cache.php
new file mode 100644
index 00000000..e8a621c8
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/cache.php
@@ -0,0 +1,30 @@
+cachecontrol();
+ }
+
+ function cachecontrol()
+ {
+ parent::__construct();
+ }
+
+ function onupdate($arr)
+ {
+ $this->load("cache");
+ $_ENV['cache']->updatedata();
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/client.php b/extend/fast/ucenter/client/uc_client/control/client.php
new file mode 100644
index 00000000..9536bca1
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/client.php
@@ -0,0 +1,817 @@
+ $val)
+ {
+ $string[$key] = uc_addslashes($val, $force, $strip);
+ }
+ }
+ else
+ {
+ $string = addslashes($strip ? stripslashes($string) : $string);
+ }
+ }
+ return $string;
+}
+
+if (!function_exists('daddslashes'))
+{
+
+ function daddslashes($string, $force = 0)
+ {
+ return uc_addslashes($string, $force);
+ }
+
+}
+
+if (!function_exists('dhtmlspecialchars'))
+{
+
+ function dhtmlspecialchars($string, $flags = null)
+ {
+ if (is_array($string))
+ {
+ foreach ($string as $key => $val)
+ {
+ $string[$key] = dhtmlspecialchars($val, $flags);
+ }
+ }
+ else
+ {
+ if ($flags === null)
+ {
+ $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
+ if (strpos($string, '&#') !== false)
+ {
+ $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
+ }
+ }
+ else
+ {
+ if (PHP_VERSION < '5.4.0')
+ {
+ $string = htmlspecialchars($string, $flags);
+ }
+ else
+ {
+ if (strtolower(CHARSET) == 'utf-8')
+ {
+ $charset = 'UTF-8';
+ }
+ else
+ {
+ $charset = 'ISO-8859-1';
+ }
+ $string = htmlspecialchars($string, $flags, $charset);
+ }
+ }
+ }
+ return $string;
+ }
+
+}
+
+if (!function_exists('fsocketopen'))
+{
+
+ function fsocketopen($hostname, $port = 80, &$errno, &$errstr, $timeout = 15)
+ {
+ $fp = '';
+ if (function_exists('fsockopen'))
+ {
+ $fp = @fsockopen($hostname, $port, $errno, $errstr, $timeout);
+ }
+ elseif (function_exists('pfsockopen'))
+ {
+ $fp = @pfsockopen($hostname, $port, $errno, $errstr, $timeout);
+ }
+ elseif (function_exists('stream_socket_client'))
+ {
+ $fp = @stream_socket_client($hostname . ':' . $port, $errno, $errstr, $timeout);
+ }
+ return $fp;
+ }
+
+}
+
+function uc_stripslashes($string)
+{
+ !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
+ if (MAGIC_QUOTES_GPC)
+ {
+ return stripslashes($string);
+ }
+ else
+ {
+ return $string;
+ }
+}
+
+// 采用POST请求形式
+function uc_api_post($module, $action, $arg = array())
+{
+ $s = $sep = '';
+ foreach ($arg as $k => $v)
+ {
+ $k = urlencode($k);
+ if (is_array($v))
+ {
+ $s2 = $sep2 = '';
+ foreach ($v as $k2 => $v2)
+ {
+ $k2 = urlencode($k2);
+ $s2 .= "$sep2{$k}[$k2]=" . urlencode(uc_stripslashes($v2));
+ $sep2 = '&';
+ }
+ $s .= $sep . $s2;
+ }
+ else
+ {
+ $s .= "$sep$k=" . urlencode(uc_stripslashes($v));
+ }
+ $sep = '&';
+ }
+ $postdata = uc_api_requestdata($module, $action, $s);
+ return uc_fopen2(UC_API . '/index.php', 500000, $postdata, '', TRUE, UC_IP, 20);
+}
+
+function uc_api_requestdata($module, $action, $arg = '', $extra = '')
+{
+ $input = uc_api_input($arg);
+ $post = "m=$module&a=$action&inajax=2&release=" . UC_CLIENT_RELEASE . "&input=$input&appid=" . UC_APPID . $extra;
+ return $post;
+}
+
+function uc_api_url($module, $action, $arg = '', $extra = '')
+{
+ $url = UC_API . '/index.php?' . uc_api_requestdata($module, $action, $arg, $extra);
+ return $url;
+}
+
+function uc_api_input($data)
+{
+ $s = urlencode(uc_authcode($data . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . "&time=" . time(), 'ENCODE', UC_KEY));
+ return $s;
+}
+
+// 直连数据库的形式
+function uc_api_mysql($model, $action, $args = array())
+{
+ global $uc_controls;
+ if (empty($uc_controls[$model]))
+ {
+ // 优先使用mysqli
+ if (function_exists("mysqli_connect"))
+ {
+ include_once UC_ROOT . './lib/dbi.class.php';
+ }
+ else
+ {
+ include_once UC_ROOT . './lib/db.class.php';
+ }
+ include_once UC_ROOT . './model/base.php';
+ include_once UC_ROOT . "./control/$model.php";
+ $classname = $model . 'control';
+ $uc_controls[$model] = new $classname();
+ }
+ if ($action{0} != '_')
+ {
+ $args = uc_addslashes($args, 1, TRUE);
+ $action = 'on' . $action;
+ $uc_controls[$model]->input = $args;
+ return $uc_controls[$model]->$action($args);
+ }
+ else
+ {
+ return '';
+ }
+}
+
+function uc_serialize($arr, $htmlon = 0)
+{
+ include_once UC_ROOT . './lib/xml.class.php';
+ return xml_serialize($arr, $htmlon);
+}
+
+function uc_unserialize($s)
+{
+ include_once UC_ROOT . './lib/xml.class.php';
+ return @xml_unserialize($s);
+}
+
+function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
+{
+
+ $ckey_length = 4;
+
+ $key = md5($key ? $key : UC_KEY);
+ $keya = md5(substr($key, 0, 16));
+ $keyb = md5(substr($key, 16, 16));
+ $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
+
+ $cryptkey = $keya . md5($keya . $keyc);
+ $key_length = strlen($cryptkey);
+
+ $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
+ $string_length = strlen($string);
+
+ $result = '';
+ $box = range(0, 255);
+
+ $rndkey = array();
+ for ($i = 0; $i <= 255; $i++)
+ {
+ $rndkey[$i] = ord($cryptkey[$i % $key_length]);
+ }
+
+ for ($j = $i = 0; $i < 256; $i++)
+ {
+ $j = ($j + $box[$i] + $rndkey[$i]) % 256;
+ $tmp = $box[$i];
+ $box[$i] = $box[$j];
+ $box[$j] = $tmp;
+ }
+
+ for ($a = $j = $i = 0; $i < $string_length; $i++)
+ {
+ $a = ($a + 1) % 256;
+ $j = ($j + $box[$a]) % 256;
+ $tmp = $box[$a];
+ $box[$a] = $box[$j];
+ $box[$j] = $tmp;
+ $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
+ }
+
+ if ($operation == 'DECODE')
+ {
+ if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16))
+ {
+ return substr($result, 26);
+ }
+ else
+ {
+ return '';
+ }
+ }
+ else
+ {
+ return $keyc . str_replace('=', '', base64_encode($result));
+ }
+}
+
+function uc_fopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE)
+{
+ $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1;
+ if ($__times__ > 2)
+ {
+ return '';
+ }
+ $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__";
+ return uc_fopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block);
+}
+
+function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE)
+{
+ $return = '';
+ $matches = parse_url($url);
+ !isset($matches['scheme']) && $matches['scheme'] = '';
+ !isset($matches['host']) && $matches['host'] = '';
+ !isset($matches['path']) && $matches['path'] = '';
+ !isset($matches['query']) && $matches['query'] = '';
+ !isset($matches['port']) && $matches['port'] = '';
+ $scheme = $matches['scheme'];
+ $host = $matches['host'];
+ $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/';
+ $port = !empty($matches['port']) ? $matches['port'] : 80;
+ if ($post)
+ {
+ $out = "POST $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+ $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
+ $header .= "Host: $host\r\n";
+ $header .= 'Content-Length: ' . strlen($post) . "\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cache-Control: no-cache\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header . $post;
+ }
+ else
+ {
+ $out = "GET $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
+ $header .= "Host: $host\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header;
+ }
+
+ $fpflag = 0;
+ if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout))
+ {
+ $context = array(
+ 'http' => array(
+ 'method' => $post ? 'POST' : 'GET',
+ 'header' => $header,
+ 'content' => $post,
+ 'timeout' => $timeout,
+ ),
+ );
+ $context = stream_context_create($context);
+ $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context);
+ $fpflag = 1;
+ }
+
+ if (!$fp)
+ {
+ return '';
+ }
+ else
+ {
+ stream_set_blocking($fp, $block);
+ stream_set_timeout($fp, $timeout);
+ @fwrite($fp, $out);
+ $status = stream_get_meta_data($fp);
+ if (!$status['timed_out'])
+ {
+ while (!feof($fp) && !$fpflag)
+ {
+ if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n"))
+ {
+ break;
+ }
+ }
+
+ $stop = false;
+ while (!feof($fp) && !$stop)
+ {
+ $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
+ $return .= $data;
+ if ($limit)
+ {
+ $limit -= strlen($data);
+ $stop = $limit <= 0;
+ }
+ }
+ }
+ @fclose($fp);
+ return $return;
+ }
+}
+
+function uc_app_ls()
+{
+ $return = call_user_func(UC_API_FUNC, 'app', 'ls', array());
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_feed_add($icon, $uid, $username, $title_template = '', $title_data = '', $body_template = '', $body_data = '', $body_general = '', $target_ids = '', $images = array())
+{
+ return call_user_func(UC_API_FUNC, 'feed', 'add', array(
+ 'icon' => $icon,
+ 'appid' => UC_APPID,
+ 'uid' => $uid,
+ 'username' => $username,
+ 'title_template' => $title_template,
+ 'title_data' => $title_data,
+ 'body_template' => $body_template,
+ 'body_data' => $body_data,
+ 'body_general' => $body_general,
+ 'target_ids' => $target_ids,
+ 'image_1' => $images[0]['url'],
+ 'image_1_link' => $images[0]['link'],
+ 'image_2' => $images[1]['url'],
+ 'image_2_link' => $images[1]['link'],
+ 'image_3' => $images[2]['url'],
+ 'image_3_link' => $images[2]['link'],
+ 'image_4' => $images[3]['url'],
+ 'image_4_link' => $images[3]['link']
+ )
+ );
+}
+
+function uc_feed_get($limit = 100, $delete = TRUE)
+{
+ $return = call_user_func(UC_API_FUNC, 'feed', 'get', array('limit' => $limit, 'delete' => $delete));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_friend_add($uid, $friendid, $comment = '')
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'add', array('uid' => $uid, 'friendid' => $friendid, 'comment' => $comment));
+}
+
+function uc_friend_delete($uid, $friendids)
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'delete', array('uid' => $uid, 'friendids' => $friendids));
+}
+
+function uc_friend_totalnum($uid, $direction = 0)
+{
+ return call_user_func(UC_API_FUNC, 'friend', 'totalnum', array('uid' => $uid, 'direction' => $direction));
+}
+
+function uc_friend_ls($uid, $page = 1, $pagesize = 10, $totalnum = 10, $direction = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'friend', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'totalnum' => $totalnum, 'direction' => $direction));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_user_register($username, $password, $email = '', $mobile = '', $extend = [])
+{
+ return call_user_func(UC_API_FUNC, 'user', 'register', array('username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend));
+}
+
+function uc_user_login($username, $password, $isuid = 0, $extend = [])
+{
+ $isuid = intval($isuid);
+ $return = call_user_func(UC_API_FUNC, 'user', 'login', array('username' => $username, 'password' => $password, 'isuid' => $isuid, 'extend' => $extend));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_user_synregister($uid, $password)
+{
+ $uid = intval($uid);
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synregister', array('uid' => $uid, 'password' => $password));
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+function uc_user_synlogin($uid)
+{
+ $uid = intval($uid);
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synlogin', array('uid' => $uid));
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+function uc_user_synlogout()
+{
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ $return = uc_api_post('user', 'synlogout', array());
+ }
+ else
+ {
+ $return = '';
+ }
+ }
+ return $return;
+}
+
+function uc_user_edit($uid, $username, $password, $email = '', $mobile = '', $extend = [])
+{
+ return call_user_func(UC_API_FUNC, 'user', 'edit', array('uid' => $uid, 'username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'extend' => $extend));
+}
+
+function uc_user_delete($uid)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'delete', array('uid' => $uid));
+}
+
+function uc_user_deleteavatar($uid)
+{
+ uc_api_post('user', 'deleteavatar', array('uid' => $uid));
+}
+
+function uc_user_checkname($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_username', array('username' => $username));
+}
+
+function uc_user_checkemail($email)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_email', array('email' => $email));
+}
+
+function uc_user_checkmobile($mobile)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'check_mobile', array('mobile' => $mobile));
+}
+
+function uc_user_addprotected($username, $admin = '')
+{
+ return call_user_func(UC_API_FUNC, 'user', 'addprotected', array('username' => $username, 'admin' => $admin));
+}
+
+function uc_user_deleteprotected($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'deleteprotected', array('username' => $username));
+}
+
+function uc_user_getprotected()
+{
+ $return = call_user_func(UC_API_FUNC, 'user', 'getprotected', array('1' => 1));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_get_user($username, $isuid = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'user', 'get_user', array('username' => $username, 'isuid' => $isuid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_user_merge($oldusername, $newusername, $uid, $password, $email)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'merge', array('oldusername' => $oldusername, 'newusername' => $newusername, 'uid' => $uid, 'password' => $password, 'email' => $email));
+}
+
+function uc_user_merge_remove($username)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'merge_remove', array('username' => $username));
+}
+
+function uc_user_getcredit($appid, $uid, $credit)
+{
+ return uc_api_post('user', 'getcredit', array('appid' => $appid, 'uid' => $uid, 'credit' => $credit));
+}
+
+function uc_user_logincheck($username, $ip)
+{
+ return call_user_func(UC_API_FUNC, 'user', 'logincheck', array('username' => $username, 'ip' => $ip));
+}
+
+function uc_pm_location($uid, $newpm = 0)
+{
+ $apiurl = uc_api_url('pm_client', 'ls', "uid=$uid", ($newpm ? '&folder=newbox' : ''));
+ @header("Expires: 0");
+ @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE);
+ @header("Pragma: no-cache");
+ @header("location: $apiurl");
+}
+
+function uc_pm_checknew($uid, $more = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'pm', 'check_newpm', array('uid' => $uid, 'more' => $more));
+ return (!$more || UC_CONNECT == 'mysql') ? $return : uc_unserialize($return);
+}
+
+function uc_pm_send($fromuid, $msgto, $subject, $message, $instantly = 1, $replypmid = 0, $isusername = 0, $type = 0)
+{
+ if ($instantly)
+ {
+ $replypmid = @is_numeric($replypmid) ? $replypmid : 0;
+ return call_user_func(UC_API_FUNC, 'pm', 'sendpm', array('fromuid' => $fromuid, 'msgto' => $msgto, 'subject' => $subject, 'message' => $message, 'replypmid' => $replypmid, 'isusername' => $isusername, 'type' => $type));
+ }
+ else
+ {
+ $fromuid = intval($fromuid);
+ $subject = rawurlencode($subject);
+ $msgto = rawurlencode($msgto);
+ $message = rawurlencode($message);
+ $replypmid = @is_numeric($replypmid) ? $replypmid : 0;
+ $replyadd = $replypmid ? "&pmid=$replypmid&do=reply" : '';
+ $apiurl = uc_api_url('pm_client', 'send', "uid=$fromuid", "&msgto=$msgto&subject=$subject&message=$message$replyadd");
+ @header("Expires: 0");
+ @header("Cache-Control: private, post-check=0, pre-check=0, max-age=0", FALSE);
+ @header("Pragma: no-cache");
+ @header("location: " . $apiurl);
+ }
+}
+
+function uc_pm_delete($uid, $folder, $pmids)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'delete', array('uid' => $uid, 'pmids' => $pmids));
+}
+
+function uc_pm_deleteuser($uid, $touids)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'deleteuser', array('uid' => $uid, 'touids' => $touids));
+}
+
+function uc_pm_deletechat($uid, $plids, $type = 0)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'deletechat', array('uid' => $uid, 'plids' => $plids, 'type' => $type));
+}
+
+function uc_pm_readstatus($uid, $uids, $plids = array(), $status = 0)
+{
+ return call_user_func(UC_API_FUNC, 'pm', 'readstatus', array('uid' => $uid, 'uids' => $uids, 'plids' => $plids, 'status' => $status));
+}
+
+function uc_pm_list($uid, $page = 1, $pagesize = 10, $folder = 'inbox', $filter = 'newpm', $msglen = 0)
+{
+ $uid = intval($uid);
+ $page = intval($page);
+ $pagesize = intval($pagesize);
+ $return = call_user_func(UC_API_FUNC, 'pm', 'ls', array('uid' => $uid, 'page' => $page, 'pagesize' => $pagesize, 'filter' => $filter, 'msglen' => $msglen));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_ignore($uid)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'ignore', array('uid' => $uid));
+}
+
+function uc_pm_view($uid, $pmid = 0, $touid = 0, $daterange = 1, $page = 0, $pagesize = 10, $type = 0, $isplid = 0)
+{
+ $uid = intval($uid);
+ $touid = intval($touid);
+ $page = intval($page);
+ $pagesize = intval($pagesize);
+ $pmid = @is_numeric($pmid) ? $pmid : 0;
+ $return = call_user_func(UC_API_FUNC, 'pm', 'view', array('uid' => $uid, 'pmid' => $pmid, 'touid' => $touid, 'daterange' => $daterange, 'page' => $page, 'pagesize' => $pagesize, 'type' => $type, 'isplid' => $isplid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_view_num($uid, $touid, $isplid)
+{
+ $uid = intval($uid);
+ $touid = intval($touid);
+ $isplid = intval($isplid);
+ return call_user_func(UC_API_FUNC, 'pm', 'viewnum', array('uid' => $uid, 'touid' => $touid, 'isplid' => $isplid));
+}
+
+function uc_pm_viewnode($uid, $type, $pmid)
+{
+ $uid = intval($uid);
+ $type = intval($type);
+ $pmid = @is_numeric($pmid) ? $pmid : 0;
+ $return = call_user_func(UC_API_FUNC, 'pm', 'viewnode', array('uid' => $uid, 'type' => $type, 'pmid' => $pmid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_chatpmmemberlist($uid, $plid = 0)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $return = call_user_func(UC_API_FUNC, 'pm', 'chatpmmemberlist', array('uid' => $uid, 'plid' => $plid));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_pm_kickchatpm($plid, $uid, $touid)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $touid = intval($touid);
+ return call_user_func(UC_API_FUNC, 'pm', 'kickchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid));
+}
+
+function uc_pm_appendchatpm($plid, $uid, $touid)
+{
+ $uid = intval($uid);
+ $plid = intval($plid);
+ $touid = intval($touid);
+ return call_user_func(UC_API_FUNC, 'pm', 'appendchatpm', array('uid' => $uid, 'plid' => $plid, 'touid' => $touid));
+}
+
+function uc_pm_blackls_get($uid)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_get', array('uid' => $uid));
+}
+
+function uc_pm_blackls_set($uid, $blackls)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_set', array('uid' => $uid, 'blackls' => $blackls));
+}
+
+function uc_pm_blackls_add($uid, $username)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_add', array('uid' => $uid, 'username' => $username));
+}
+
+function uc_pm_blackls_delete($uid, $username)
+{
+ $uid = intval($uid);
+ return call_user_func(UC_API_FUNC, 'pm', 'blackls_delete', array('uid' => $uid, 'username' => $username));
+}
+
+function uc_domain_ls()
+{
+ $return = call_user_func(UC_API_FUNC, 'domain', 'ls', array('1' => 1));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_credit_exchange_request($uid, $from, $to, $toappid, $amount)
+{
+ $uid = intval($uid);
+ $from = intval($from);
+ $toappid = intval($toappid);
+ $to = intval($to);
+ $amount = intval($amount);
+ return uc_api_post('credit', 'request', array('uid' => $uid, 'from' => $from, 'to' => $to, 'toappid' => $toappid, 'amount' => $amount));
+}
+
+function uc_tag_get($tagname, $nums = 0)
+{
+ $return = call_user_func(UC_API_FUNC, 'tag', 'gettag', array('tagname' => $tagname, 'nums' => $nums));
+ return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
+}
+
+function uc_avatar($uid, $type = 'virtual', $returnhtml = 1)
+{
+ $uid = intval($uid);
+ $uc_input = uc_api_input("uid=$uid");
+ $uc_avatarflash = UC_API . '/images/camera.swf?inajax=1&appid=' . UC_APPID . '&input=' . $uc_input . '&agent=' . md5($_SERVER['HTTP_USER_AGENT']) . '&ucapi=' . urlencode(str_replace('http://', '', UC_API)) . '&avatartype=' . $type . '&uploadSize=2048';
+ if ($returnhtml)
+ {
+ return '';
+ }
+ else
+ {
+ return array(
+ 'width', '450',
+ 'height', '253',
+ 'scale', 'exactfit',
+ 'src', $uc_avatarflash,
+ 'id', 'mycamera',
+ 'name', 'mycamera',
+ 'quality', 'high',
+ 'bgcolor', '#ffffff',
+ 'menu', 'false',
+ 'swLiveConnect', 'true',
+ 'allowScriptAccess', 'always'
+ );
+ }
+}
+
+function uc_mail_queue($uids, $emails, $subject, $message, $frommail = '', $charset = 'gbk', $htmlon = FALSE, $level = 1)
+{
+ return call_user_func(UC_API_FUNC, 'mail', 'add', array('uids' => $uids, 'emails' => $emails, 'subject' => $subject, 'message' => $message, 'frommail' => $frommail, 'charset' => $charset, 'htmlon' => $htmlon, 'level' => $level));
+}
+
+function uc_check_avatar($uid, $size = 'middle', $type = 'virtual')
+{
+ $url = UC_API . "/avatar.php?uid=$uid&size=$size&type=$type&check_file_exists=1";
+ $res = uc_fopen2($url, 500000, '', '', TRUE, UC_IP, 20);
+ if ($res == 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+function uc_check_version()
+{
+ $return = uc_api_post('version', 'check', array());
+ $data = uc_unserialize($return);
+ return is_array($data) ? $data : $return;
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/domain.php b/extend/fast/ucenter/client/uc_client/control/domain.php
new file mode 100644
index 00000000..a7c76a94
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/domain.php
@@ -0,0 +1,31 @@
+domaincontrol();
+ }
+
+ function domaincontrol()
+ {
+ parent::__construct();
+ $this->init_input();
+ $this->load('domain');
+ }
+
+ function onls()
+ {
+ return $_ENV['domain']->get_list(1, 9999, 9999);
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/feed.php b/extend/fast/ucenter/client/uc_client/control/feed.php
new file mode 100644
index 00000000..86a58b39
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/feed.php
@@ -0,0 +1,114 @@
+feedcontrol();
+ }
+
+ function feedcontrol()
+ {
+ parent::__construct();
+ $this->init_input();
+ }
+
+ function onadd()
+ {
+ $this->load('misc');
+ $appid = intval($this->input('appid'));
+ $icon = $this->input('icon');
+ $uid = intval($this->input('uid'));
+ $username = $this->input('username');
+ $body_data = $_ENV['misc']->array2string($this->input('body_data'));
+ $title_data = $_ENV['misc']->array2string($this->input('title_data'));
+
+ $title_template = $this->_parsetemplate($this->input('title_template'));
+ $body_template = $this->_parsetemplate($this->input('body_template'));
+ $body_general = $this->input('body_general');
+ $target_ids = $this->input('target_ids');
+ $image_1 = $this->input('image_1');
+ $image_1_link = $this->input('image_1_link');
+ $image_2 = $this->input('image_2');
+ $image_2_link = $this->input('image_2_link');
+ $image_3 = $this->input('image_3');
+ $image_3_link = $this->input('image_3_link');
+ $image_4 = $this->input('image_4');
+ $image_4_link = $this->input('image_4_link');
+
+ $hash_template = md5($title_template . $body_template);
+ $hash_data = md5($title_template . $title_data . $body_template . $body_data);
+ $dateline = $this->time;
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "feeds SET appid='$appid', icon='$icon', uid='$uid', username='$username',
+ title_template='$title_template', title_data='$title_data', body_template='$body_template', body_data='$body_data', body_general='$body_general',
+ image_1='$image_1', image_1_link='$image_1_link', image_2='$image_2', image_2_link='$image_2_link',
+ image_3='$image_3', image_3_link='$image_3_link', image_4='$image_4', image_4_link='$image_4_link',
+ hash_template='$hash_template', hash_data='$hash_data', target_ids='$target_ids', dateline='$dateline'");
+ return $this->db->insert_id();
+ }
+
+ function ondelete()
+ {
+ $start = $this->input('start');
+ $limit = $this->input('limit');
+ $end = $start + $limit;
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "feeds WHERE feedid>'$start' AND feedid<'$end'");
+ }
+
+ function onget()
+ {
+ $this->load('misc');
+ $limit = intval($this->input('limit'));
+ $delete = $this->input('delete');
+ $feedlist = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "feeds ORDER BY feedid DESC LIMIT $limit");
+ if ($feedlist)
+ {
+ $maxfeedid = $feedlist[0]['feedid'];
+ foreach ($feedlist as $key => $feed)
+ {
+ $feed['body_data'] = $_ENV['misc']->string2array($feed['body_data']);
+ $feed['title_data'] = $_ENV['misc']->string2array($feed['title_data']);
+ $feedlist[$key] = $feed;
+ }
+ }
+ if (!empty($feedlist))
+ {
+ if (!isset($delete) || $delete)
+ {
+ $this->_delete(0, $maxfeedid);
+ }
+ }
+ return $feedlist;
+ }
+
+ function _delete($start, $end)
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "feeds WHERE feedid>='$start' AND feedid<='$end'");
+ }
+
+ function _parsetemplate($template)
+ {
+ $template = str_replace(array("\r", "\n"), '', $template);
+ $template = str_replace(array('
', '
', '
', '
'), "\n", $template);
+ $template = str_replace(array('', ''), '[B]', $template);
+ $template = str_replace(array('', ''), '[I]', $template);
+ $template = str_replace(array('', ''), '[U]', $template);
+ $template = str_replace(array('', ''), '[/B]', $template);
+ $template = str_replace(array('', ''), '[/I]', $template);
+ $template = str_replace(array('', ''), '[/U]', $template);
+ $template = dhtmlspecialchars($template);
+ $template = nl2br($template);
+ $template = str_replace(array('[B]', '[I]', '[U]', '[/B]', '[/I]', '[/U]'), array('', '', '', '', '', ''), $template);
+ return $template;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/friend.php b/extend/fast/ucenter/client/uc_client/control/friend.php
new file mode 100644
index 00000000..01768b54
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/friend.php
@@ -0,0 +1,64 @@
+friendcontrol();
+ }
+
+ function friendcontrol()
+ {
+ parent::__construct();
+ $this->init_input();
+ $this->load('friend');
+ }
+
+ function ondelete()
+ {
+ $uid = intval($this->input('uid'));
+ $friendids = $this->input('friendids');
+ $id = $_ENV['friend']->delete($uid, $friendids);
+ return $id;
+ }
+
+ function onadd()
+ {
+ $uid = intval($this->input('uid'));
+ $friendid = $this->input('friendid');
+ $comment = $this->input('comment');
+ $id = $_ENV['friend']->add($uid, $friendid, $comment);
+ return $id;
+ }
+
+ function ontotalnum()
+ {
+ $uid = intval($this->input('uid'));
+ $direction = intval($this->input('direction'));
+ $totalnum = $_ENV['friend']->get_totalnum_by_uid($uid, $direction);
+ return $totalnum;
+ }
+
+ function onls()
+ {
+ $uid = intval($this->input('uid'));
+ $page = intval($this->input('page'));
+ $pagesize = intval($this->input('pagesize'));
+ $totalnum = intval($this->input('totalnum'));
+ $direction = intval($this->input('direction'));
+ $pagesize = $pagesize ? $pagesize : UC_PPP;
+ $totalnum = $totalnum ? $totalnum : $_ENV['friend']->get_totalnum_by_uid($uid);
+ $data = $_ENV['friend']->get_list($uid, $page, $pagesize, $totalnum, $direction);
+ return $data;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/index.htm b/extend/fast/ucenter/client/uc_client/control/index.htm
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/index.htm
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/control/mail.php b/extend/fast/ucenter/client/uc_client/control/mail.php
new file mode 100644
index 00000000..28bdedda
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/mail.php
@@ -0,0 +1,42 @@
+mailcontrol();
+ }
+
+ function mailcontrol()
+ {
+ parent::__construct();
+ $this->init_input();
+ }
+
+ function onadd()
+ {
+ $this->load('mail');
+ $mail = array();
+ $mail['appid'] = UC_APPID;
+ $mail['uids'] = explode(',', $this->input('uids'));
+ $mail['emails'] = explode(',', $this->input('emails'));
+ $mail['subject'] = $this->input('subject');
+ $mail['message'] = $this->input('message');
+ $mail['charset'] = $this->input('charset');
+ $mail['htmlon'] = intval($this->input('htmlon'));
+ $mail['level'] = abs(intval($this->input('level')));
+ $mail['frommail'] = $this->input('frommail');
+ $mail['dateline'] = $this->time;
+ return $_ENV['mail']->add($mail);
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/pm.php b/extend/fast/ucenter/client/uc_client/control/pm.php
new file mode 100644
index 00000000..940d3987
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/pm.php
@@ -0,0 +1,463 @@
+pmcontrol();
+ }
+
+ function pmcontrol()
+ {
+ parent::__construct();
+ $this->load('user');
+ $this->load('pm');
+ }
+
+ function oncheck_newpm()
+ {
+ $this->init_input();
+ $uid = intval($this->input('uid'));
+ $more = intval($this->input('more'));
+ if (!$_ENV['pm']->isnewpm($uid) && !$more)
+ {
+ return 0;
+ }
+ $newprvpm = $_ENV['pm']->getpmnum($uid, 1, 1);
+ $newchatpm = $_ENV['pm']->getpmnum($uid, 2, 1);
+ $newpm = $newprvpm + $newchatpm;
+ if ($more == 0)
+ {
+ return $newpm;
+ }
+ elseif ($more == 1)
+ {
+ return array('newpm' => $newpm, 'newprivatepm' => $newprvpm);
+ }
+ elseif ($more == 2 || $more == 3)
+ {
+ if ($more == 2)
+ {
+ return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm);
+ }
+ else
+ {
+ $lastpm = $_ENV['pm']->lastpm($uid);
+ require_once UC_ROOT . 'lib/uccode.class.php';
+ $this->uccode = new uccode();
+ $lastpm['lastsummary'] = $this->uccode->complie($lastpm['lastsummary']);
+ return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm, 'lastdate' => $lastpm['lastdateline'], 'lastmsgfromid' => $lastpm['lastauthorid'], 'lastmsgfrom' => $lastpm['lastauthorusername'], 'lastmsg' => $lastpm['lastsummary']);
+ }
+ }
+ elseif ($more == 4)
+ {
+ return array('newpm' => $newpm, 'newprivatepm' => $newprvpm, 'newchatpm' => $newchatpm);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ function onsendpm()
+ {
+ $this->init_input();
+ $fromuid = $this->input('fromuid');
+ $msgto = $this->input('msgto');
+ $subject = $this->input('subject');
+ $message = $this->input('message');
+ $replypmid = $this->input('replypmid');
+ $isusername = $this->input('isusername');
+ $type = $this->input('type');
+
+ if (!$fromuid)
+ {
+ return 0;
+ }
+
+ $user = $_ENV['user']->get_user_by_uid($fromuid);
+ $user = daddslashes($user, 1);
+ if (!$user)
+ {
+ return 0;
+ }
+ $this->user['uid'] = $user['uid'];
+ $this->user['username'] = $user['username'];
+
+ if ($replypmid)
+ {
+ $isusername = 0;
+ $plid = $_ENV['pm']->getplidbypmid($replypmid);
+ $msgto = $_ENV['pm']->getuidbyplid($plid);
+ unset($msgto[$this->user['uid']]);
+ }
+ else
+ {
+ if (!empty($msgto))
+ {
+ $msgto = array_unique(explode(',', $msgto));
+ }
+ }
+
+ if ($isusername)
+ {
+ $msgto = $_ENV['user']->name2id($msgto);
+ }
+ $countmsgto = count($msgto);
+
+ if ($this->settings['pmsendregdays'])
+ {
+ if ($user['regdate'] > $this->time - $this->settings['pmsendregdays'] * 86400)
+ {
+ return PMSENDREGDAYS;
+ }
+ }
+ if ($this->settings['chatpmmemberlimit'])
+ {
+ if ($type == 1 && ($countmsgto > ($this->settings['chatpmmemberlimit'] - 1)))
+ {
+ return CHATPMMEMBERLIMIT_ERROR;
+ }
+ }
+ if ($this->settings['pmfloodctrl'])
+ {
+ if (!$_ENV['pm']->ispminterval($this->user['uid'], $this->settings['pmfloodctrl']))
+ {
+ return PMFLOODCTRL_ERROR;
+ }
+ }
+ if ($this->settings['privatepmthreadlimit'])
+ {
+ if (!$_ENV['pm']->isprivatepmthreadlimit($this->user['uid'], $this->settings['privatepmthreadlimit']))
+ {
+ return PRIVATEPMTHREADLIMIT_ERROR;
+ }
+ }
+ if ($this->settings['chatpmthreadlimit'])
+ {
+ if (!$_ENV['pm']->ischatpmthreadlimit($this->user['uid'], $this->settings['chatpmthreadlimit']))
+ {
+ return CHATPMTHREADLIMIT_ERROR;
+ }
+ }
+
+ $lastpmid = 0;
+ if ($replypmid)
+ {
+ $lastpmid = $_ENV['pm']->replypm($plid, $this->user['uid'], $this->user['username'], $message);
+ }
+ else
+ {
+ $lastpmid = $_ENV['pm']->sendpm($this->user['uid'], $this->user['username'], $msgto, $subject, $message, $type);
+ }
+ return $lastpmid;
+ }
+
+ function ondelete()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $pmids = $this->input('pmids');
+ if (empty($pmids))
+ {
+ return 0;
+ }
+ if (is_array($pmids))
+ {
+ $this->apps = $this->cache('apps');
+ if ($this->apps[$this->app['appid']]['type'] == 'UCHOME')
+ {
+ $id = $_ENV['pm']->deletepmbyplids($this->user['uid'], $this->input('pmids'));
+ }
+ else
+ {
+ $id = $_ENV['pm']->deletepmbypmids($this->user['uid'], $this->input('pmids'));
+ }
+ }
+ else
+ {
+ $id = $_ENV['pm']->deletepmbypmid($this->user['uid'], $this->input('pmids'));
+ }
+ return $id;
+ }
+
+ function ondeletechat()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $plids = $this->input('plids');
+ $type = intval($this->input('type'));
+ if ($type == 1)
+ {
+ return $_ENV['pm']->deletepmbyplids($this->user['uid'], $plids);
+ }
+ else
+ {
+ return $_ENV['pm']->quitchatpm($this->user['uid'], $plids);
+ }
+ }
+
+ function ondeleteuser()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $id = $_ENV['pm']->deletepmbyplids($this->user['uid'], $this->input('touids'), 1);
+ return $id;
+ }
+
+ function onreadstatus()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $_ENV['pm']->setpmstatus($this->user['uid'], $this->input('uids'), $this->input('plids'), $this->input('status'));
+ }
+
+ function onignore()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ return $_ENV['pm']->set_ignore($this->user['uid']);
+ }
+
+ function onls()
+ {
+ $this->init_input();
+ $pagesize = $this->input('pagesize');
+ $filter = $this->input('filter');
+ $page = $this->input('page');
+ $msglen = $this->input('msglen');
+ $this->user['uid'] = intval($this->input('uid'));
+
+ $filter = $filter ? (in_array($filter, array('newpm', 'privatepm')) ? $filter : '') : '';
+ if ($filter == 'newpm')
+ {
+ $type = 0;
+ $new = 1;
+ }
+ elseif ($filter == 'privatepm')
+ {
+ $type = 0;
+ $new = 0;
+ }
+ else
+ {
+ return array();
+ }
+ $pmnum = $_ENV['pm']->getpmnum($this->user['uid'], $type, $new);
+ $start = $this->page_get_start($page, $pagesize, $pmnum);
+
+ if ($pagesize > 0)
+ {
+ $pms = $_ENV['pm']->getpmlist($this->user['uid'], $filter, $start, $pagesize);
+ if (is_array($pms) && !empty($pms))
+ {
+ foreach ($pms as $key => $pm)
+ {
+ if ($msglen)
+ {
+ $pms[$key]['lastsummary'] = $_ENV['pm']->removecode($pms[$key]['lastsummary'], $msglen);
+ }
+ else
+ {
+ unset($pms[$key]['lastsummary']);
+ }
+ }
+ }
+ $result['data'] = $pms;
+ }
+ $result['count'] = $pmnum;
+ return $result;
+ }
+
+ function onview()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $pmid = $this->input('pmid');
+ $touid = $this->input('touid');
+ $daterange = $this->input('daterange');
+ $page = $this->input('page');
+ $pagesize = $this->input('pagesize');
+ $isplid = $this->input('isplid');
+ $type = $this->input('type');
+
+ $daterange = empty($daterange) ? 1 : $daterange;
+ $today = $this->time - ($this->time + $this->settings['timeoffset']) % 86400;
+ if ($daterange == 1)
+ {
+ $starttime = $today;
+ }
+ elseif ($daterange == 2)
+ {
+ $starttime = $today - 86400;
+ }
+ elseif ($daterange == 3)
+ {
+ $starttime = $today - 172800;
+ }
+ elseif ($daterange == 4)
+ {
+ $starttime = $today - 604800;
+ }
+ elseif ($daterange == 5)
+ {
+ $starttime = 0;
+ }
+ $endtime = $this->time;
+
+ if (!$isplid)
+ {
+ $plid = $_ENV['pm']->getplidbytouid($this->user['uid'], $touid);
+ }
+ else
+ {
+ $plid = $touid;
+ }
+ if ($page)
+ {
+ $pmnum = $_ENV['pm']->getpmnumbyplid($this->user['uid'], $plid);
+ $start = $this->page_get_start($page, $pagesize, $pmnum);
+ $ppp = $pagesize;
+ }
+ else
+ {
+ $pmnum = 0;
+ $start = 0;
+ $ppp = 0;
+ }
+
+ if ($pmid)
+ {
+ $pms = $_ENV['pm']->getpmbypmid($this->user['uid'], $pmid);
+ }
+ else
+ {
+ $pms = $_ENV['pm']->getpmbyplid($this->user['uid'], $plid, $starttime, $endtime, $start, $ppp, $type);
+ }
+
+ require_once UC_ROOT . 'lib/uccode.class.php';
+ $this->uccode = new uccode();
+ if ($pms)
+ {
+ foreach ($pms as $key => $pm)
+ {
+ $pms[$key]['message'] = $this->uccode->complie($pms[$key]['message']);
+ }
+ }
+ return $pms;
+ }
+
+ function onviewnum()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $touid = $this->input('touid');
+ $isplid = $this->input('isplid');
+ if (!$isplid)
+ {
+ $plid = $_ENV['pm']->getplidbytouid($this->user['uid'], $touid);
+ }
+ else
+ {
+ $plid = $touid;
+ }
+ $pmnum = $_ENV['pm']->getpmnumbyplid($this->user['uid'], $plid);
+ return $pmnum;
+ }
+
+ function onviewnode()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $type = $this->input('type');
+ $pmid = $this->input('pmid');
+ $type = 0;
+ $pms = $_ENV['pm']->getpmbypmid($this->user['uid'], $pmid);
+
+ require_once UC_ROOT . 'lib/uccode.class.php';
+ $this->uccode = new uccode();
+ if ($pms)
+ {
+ foreach ($pms as $key => $pm)
+ {
+ $pms[$key]['message'] = $this->uccode->complie($pms[$key]['message']);
+ }
+ }
+ $pms = $pms[0];
+ return $pms;
+ }
+
+ function onchatpmmemberlist()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $plid = intval($this->input('plid'));
+ return $_ENV['pm']->chatpmmemberlist($this->user['uid'], $plid);
+ }
+
+ function onkickchatpm()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $plid = intval($this->input('plid'));
+ $touid = intval($this->input('touid'));
+ return $_ENV['pm']->kickchatpm($plid, $this->user['uid'], $touid);
+ }
+
+ function onappendchatpm()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $plid = intval($this->input('plid'));
+ $touid = intval($this->input('touid'));
+ return $_ENV['pm']->appendchatpm($plid, $this->user['uid'], $touid);
+ }
+
+ function onblackls_get()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ return $_ENV['pm']->get_blackls($this->user['uid']);
+ }
+
+ function onblackls_set()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $blackls = $this->input('blackls');
+ return $_ENV['pm']->set_blackls($this->user['uid'], $blackls);
+ }
+
+ function onblackls_add()
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $username = $this->input('username');
+ return $_ENV['pm']->update_blackls($this->user['uid'], $username, 1);
+ }
+
+ function onblackls_delete($arr)
+ {
+ $this->init_input();
+ $this->user['uid'] = intval($this->input('uid'));
+ $username = $this->input('username');
+ return $_ENV['pm']->update_blackls($this->user['uid'], $username, 2);
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/tag.php b/extend/fast/ucenter/client/uc_client/control/tag.php
new file mode 100644
index 00000000..8fc80aa2
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/tag.php
@@ -0,0 +1,102 @@
+tagcontrol();
+ }
+
+ function tagcontrol()
+ {
+ parent::__construct();
+ $this->init_input();
+ $this->load('tag');
+ $this->load('misc');
+ }
+
+ function ongettag()
+ {
+ $appid = $this->input('appid');
+ $tagname = $this->input('tagname');
+ $nums = $this->input('nums');
+ if (empty($tagname))
+ {
+ return NULL;
+ }
+ $return = $apparray = $appadd = array();
+
+ if ($nums && is_array($nums))
+ {
+ foreach ($nums as $k => $num)
+ {
+ $apparray[$k] = $k;
+ }
+ }
+
+ $data = $_ENV['tag']->get_tag_by_name($tagname);
+ if ($data)
+ {
+ $apparraynew = array();
+ foreach ($data as $tagdata)
+ {
+ $row = $r = array();
+ $tmp = explode("\t", $tagdata['data']);
+ $type = $tmp[0];
+ array_shift($tmp);
+ foreach ($tmp as $tmp1)
+ {
+ $tmp1 != '' && $r[] = $_ENV['misc']->string2array($tmp1);
+ }
+ if (in_array($tagdata['appid'], $apparray))
+ {
+ if ($tagdata['expiration'] > 0 && $this->time - $tagdata['expiration'] > 3600)
+ {
+ $appadd[] = $tagdata['appid'];
+ $_ENV['tag']->formatcache($tagdata['appid'], $tagname);
+ }
+ else
+ {
+ $apparraynew[] = $tagdata['appid'];
+ }
+ $datakey = array();
+ $count = 0;
+ foreach ($r as $data)
+ {
+ $return[$tagdata['appid']]['data'][] = $data;
+ $return[$tagdata['appid']]['type'] = $type;
+ $count++;
+ if ($count >= $nums[$tagdata['appid']])
+ {
+ break;
+ }
+ }
+ }
+ }
+ $apparray = array_diff($apparray, $apparraynew);
+ }
+ else
+ {
+ foreach ($apparray as $appid)
+ {
+ $_ENV['tag']->formatcache($appid, $tagname);
+ }
+ }
+ if ($apparray)
+ {
+ $this->load('note');
+ $_ENV['note']->add('gettag', "id=$tagname", '', $appadd, -1);
+ }
+ return $return;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/control/user.php b/extend/fast/ucenter/client/uc_client/control/user.php
new file mode 100644
index 00000000..42d0b4e8
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/control/user.php
@@ -0,0 +1,443 @@
+usercontrol();
+ }
+
+ function usercontrol()
+ {
+ parent::__construct();
+ $this->load('user');
+ $this->app = $this->cache['apps'][UC_APPID];
+ }
+
+ // 同步注册
+ function onsynregister()
+ {
+ $this->init_input();
+ $uid = $this->input('uid');
+ $password = $this->input('password');
+ if ($this->app['synlogin'])
+ {
+ if ($this->user = $_ENV['user']->get_user_by_uid($uid))
+ {
+ $params = 'action=synregister' .
+ '&username=' . $this->user['username'] .
+ '&uid=' . $this->user['uid'] .
+ '&password=' . $password .
+ '&email=' . $this->user['email'] .
+ '&mobile=' . $this->user['mobile'] .
+ '&time=' . $this->time;
+ $synstr = '';
+ foreach ($this->cache['apps'] as $appid => $app)
+ {
+ if ($app['synlogin'] && $app['appid'] != $this->app['appid'])
+ {
+ $synstr .= '';
+ }
+ }
+ return $synstr;
+ }
+ }
+ return '';
+ }
+
+ // 同步登录
+ function onsynlogin()
+ {
+ $this->init_input();
+ $uid = $this->input('uid');
+ if ($this->app['synlogin'])
+ {
+ if ($this->user = $_ENV['user']->get_user_by_uid($uid))
+ {
+ $params = 'action=synlogin' .
+ '&username=' . $this->user['username'] .
+ '&uid=' . $this->user['uid'] .
+ '&password=' . $this->user['password'] .
+ '&time=' . $this->time;
+ $synstr = '';
+ foreach ($this->cache['apps'] as $appid => $app)
+ {
+ if ($app['synlogin'] && $app['appid'] != $this->app['appid'])
+ {
+ $synstr .= '';
+ }
+ }
+ return $synstr;
+ }
+ }
+ return '';
+ }
+
+ // 同步退出
+ function onsynlogout()
+ {
+ $this->init_input();
+ if ($this->app['synlogin'])
+ {
+ $synstr = '';
+ foreach ($this->cache['apps'] as $appid => $app)
+ {
+ if ($app['synlogin'] && $app['appid'] != $this->app['appid'])
+ {
+ $synstr .= '';
+ }
+ }
+ return $synstr;
+ }
+ return '';
+ }
+
+ // 同步注册
+ function onregister()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $password = $this->input('password');
+ $email = $this->input('email');
+ $mobile = $this->input('mobile');
+ $extend = $this->input('extend');
+ $extend = $extend ? $extend : [];
+ if (($status = $this->_check_username($username)) < 0)
+ {
+ return $status;
+ }
+ if ($email && ($status = $this->_check_email($email)) < 0)
+ {
+ return $status;
+ }
+ if ($mobile && ($status = $this->_check_mobile($mobile)) < 0)
+ {
+ return $status;
+ }
+ $uid = $_ENV['user']->add_user($username, $password, $email, $mobile, 0, $extend);
+ return $uid;
+ }
+
+ // 编辑ucenter中信息
+ function onedit()
+ {
+ $this->init_input();
+ $uid = intval($this->input('uid'));
+ $username = $this->input('username');
+ $password = $this->input('password');
+ $email = $this->input('email');
+ $mobile = $this->input('mobile');
+ $extend = $this->input('extend');
+ $extend = $extend ? $extend : [];
+
+ $status = $_ENV['user']->edit_user($username, $password, $email, $mobile, $uid, $extend);
+
+ if ($status > 0)
+ {
+ if (@include UC_ROOT . './data/cache/apps.php')
+ {
+ if (count($_CACHE['apps']) > 1)
+ {
+ //手动调用一次同步到所有应用
+ uc_api_post('user', 'edit', $this->input);
+ }
+ }
+ return $status;
+ $this->load('note');
+ $_ENV['note']->add('updateinfo', http_build_query($this->input));
+ }
+ return $status;
+ }
+
+ // 登录ucenter账号
+ function onlogin()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $password = $this->input('password');
+ $isuid = $this->input('isuid'); //0用户名 1UID 2邮箱 3手机
+
+ if ($isuid == 1)
+ {
+ $user = $_ENV['user']->get_user_by_uid($username);
+ }
+ elseif ($isuid == 2)
+ {
+ $user = $_ENV['user']->get_user_by_email($username);
+ }
+ elseif ($isuid == 3)
+ {
+ $user = $_ENV['user']->get_user_by_mobile($username);
+ }
+ else
+ {
+ $user = $_ENV['user']->get_user_by_username($username);
+ }
+
+ $passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password);
+ if (empty($user))
+ {
+ $status = -1;
+ }
+ elseif ($user['password'] != md5($passwordmd5 . $user['salt']))
+ {
+ $status = -2;
+ }
+ else
+ {
+ $status = $user['uid'];
+ }
+ $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;
+ return [
+ 'status' => $status,
+ 'uid' => isset($user['uid']) ? $user['uid'] : 0,
+ 'username' => isset($user['username']) ? $user['username'] : '',
+ 'password' => $password,
+ 'email' => isset($user['email']) ? $user['email'] : '',
+ 'mobile' => isset($user['mobile']) ? $user['mobile'] : '',
+ 'merge' => $merge
+ ];
+ }
+
+ function onlogincheck()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $ip = $this->input('ip');
+ return $_ENV['user']->can_do_login($username, $ip);
+ }
+
+ function oncheck_email()
+ {
+ $this->init_input();
+ $email = $this->input('email');
+ return $this->_check_email($email);
+ }
+
+ function oncheck_username()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ if (($status = $this->_check_username($username)) < 0)
+ {
+ return $status;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ function onget_user()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $isuid = $this->input('isuid'); //0用户名 1UID 2邮箱 3手机
+ if ($isuid == 1)
+ {
+ $member = $_ENV['user']->get_user_by_uid($username);
+ }
+ else if ($isuid == 2)
+ {
+ $member = $_ENV['user']->get_user_by_email($username);
+ }
+ else if ($isuid == 3)
+ {
+ $member = $_ENV['user']->get_user_by_mobile($username);
+ }
+ else
+ {
+ $member = $_ENV['user']->get_user_by_username($username);
+ }
+ if ($member)
+ {
+ // 加载扩展表
+ $memberfields = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='{$member['uid']}'");
+
+ $memberfields = $memberfields ? $memberfields : [];
+ $member = [
+ 'uid' => $member['uid'],
+ 'username' => $member['username'],
+ 'email' => $member['email'],
+ 'mobile' => $member['mobile']
+ ];
+ return array_merge($member, $memberfields);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ function ongetprotected()
+ {
+ $this->init_input();
+ $protectedmembers = $this->db->fetch_all("SELECT uid,username FROM " . UC_DBTABLEPRE . "protectedmembers GROUP BY username");
+ return $protectedmembers;
+ }
+
+ function ondelete()
+ {
+ $this->init_input();
+ $uid = $this->input('uid');
+ return $_ENV['user']->delete_user($uid);
+ }
+
+ function onaddprotected()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $admin = $this->input('admin');
+ $appid = $this->app['appid'];
+ $usernames = (array) $username;
+ foreach ($usernames as $username)
+ {
+ $user = $_ENV['user']->get_user_by_username($username);
+ $uid = $user['uid'];
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "protectedmembers SET uid='$uid', username='$username', appid='$appid', dateline='{$this->time}', admin='$admin'", 'SILENT');
+ }
+ return $this->db->errno() ? -1 : 1;
+ }
+
+ function ondeleteprotected()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $appid = $this->app['appid'];
+ $usernames = (array) $username;
+ foreach ($usernames as $username)
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "protectedmembers WHERE username='$username' AND appid='$appid'");
+ }
+ return $this->db->errno() ? -1 : 1;
+ }
+
+ function onmerge()
+ {
+ $this->init_input();
+ $uid = $this->input('uid');
+ $oldusername = $this->input('oldusername');
+ $newusername = $this->input('newusername');
+ $password = $this->input('password');
+ $email = $this->input('email');
+ $mobile = $this->input('mobile');
+ $extend = $this->input('extend');
+ $extend = $extend ? $extend : [];
+ if (($status = $this->_check_username($newusername)) < 0)
+ {
+ return $status;
+ }
+ $uid = $_ENV['user']->add_user($newusername, $password, $email, $mobile, $uid, $extend);
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->app['appid'] . "' AND username='$oldusername'");
+ return $uid;
+ }
+
+ function onmerge_remove()
+ {
+ $this->init_input();
+ $username = $this->input('username');
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->app['appid'] . "' AND username='$username'");
+ return NULL;
+ }
+
+ function _check_username($username)
+ {
+ $username = addslashes(trim(stripslashes($username)));
+ if (!$_ENV['user']->check_username($username))
+ {
+ return UC_USER_CHECK_USERNAME_FAILED;
+ }
+ elseif (!$_ENV['user']->check_usernamecensor($username))
+ {
+ return UC_USER_USERNAME_BADWORD;
+ }
+ elseif ($_ENV['user']->check_usernameexists($username))
+ {
+ return UC_USER_USERNAME_EXISTS;
+ }
+ return 1;
+ }
+
+ function _check_email($email, $username = '')
+ {
+ if (empty($this->settings))
+ {
+ $this->settings = $this->cache('settings');
+ }
+ if (!$_ENV['user']->check_emailformat($email))
+ {
+ return UC_USER_EMAIL_FORMAT_ILLEGAL;
+ }
+ elseif (!$_ENV['user']->check_emailaccess($email))
+ {
+ return UC_USER_EMAIL_ACCESS_ILLEGAL;
+ }
+ elseif (!$this->settings['doublee'] && $_ENV['user']->check_emailexists($email, $username))
+ {
+ return UC_USER_EMAIL_EXISTS;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ function _check_mobile($mobile, $username = '')
+ {
+ if (empty($this->settings))
+ {
+ $this->settings = $this->cache('settings');
+ }
+ if (!$_ENV['user']->check_mobileformat($mobile))
+ {
+ return UC_USER_EMAIL_FORMAT_ILLEGAL;
+ }
+ elseif (!$_ENV['user']->check_mobileaccess($mobile))
+ {
+ return UC_USER_EMAIL_ACCESS_ILLEGAL;
+ }
+ elseif (!$this->settings['doublee'] && $_ENV['user']->check_mobileexists($mobile, $username))
+ {
+ return UC_USER_EMAIL_EXISTS;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ function onuploadavatar()
+ {
+
+ }
+
+ function onrectavatar()
+ {
+
+ }
+
+ function flashdata_decode($s)
+ {
+
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/data/cache/apps.php b/extend/fast/ucenter/client/uc_client/data/cache/apps.php
new file mode 100644
index 00000000..eddad2fa
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/data/cache/apps.php
@@ -0,0 +1,40 @@
+
+ array (
+ 'appid' => '1',
+ 'type' => 'OTHER',
+ 'name' => 'FastAdmin',
+ 'url' => 'http://www.tp.com/index/ucenter',
+ 'ip' => '',
+ 'viewprourl' => '',
+ 'apifilename' => 'index',
+ 'charset' => '',
+ 'synlogin' => '1',
+ 'extra' =>
+ array (
+ 'apppath' => '',
+ 'extraurl' => ' ',
+ ),
+ 'recvnote' => '1',
+ ),
+ 2 =>
+ array (
+ 'appid' => '2',
+ 'type' => 'DISCUZX',
+ 'name' => 'Discuz!',
+ 'url' => 'http://www.discuz.com',
+ 'ip' => '',
+ 'viewprourl' => '',
+ 'apifilename' => 'uc.php',
+ 'charset' => 'utf-8',
+ 'synlogin' => '1',
+ 'extra' =>
+ array (
+ 'apppath' => '',
+ 'extraurl' => ' ',
+ ),
+ 'recvnote' => '1',
+ ),
+ 'UC_API' => 'http://www.ucenter.com',
+);
diff --git a/extend/fast/ucenter/client/uc_client/data/cache/badwords.php b/extend/fast/ucenter/client/uc_client/data/cache/badwords.php
new file mode 100644
index 00000000..c3ca52b4
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/data/cache/badwords.php
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/data/cache/index.htm b/extend/fast/ucenter/client/uc_client/data/cache/index.htm
new file mode 100644
index 00000000..e69de29b
diff --git a/extend/fast/ucenter/client/uc_client/data/cache/settings.php b/extend/fast/ucenter/client/uc_client/data/cache/settings.php
new file mode 100644
index 00000000..069021ea
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/data/cache/settings.php
@@ -0,0 +1,32 @@
+ '',
+ 'censoremail' => '',
+ 'censorusername' => '',
+ 'dateformat' => 'y-n-j',
+ 'doublee' => '0',
+ 'nextnotetime' => '0',
+ 'timeoffset' => '28800',
+ 'privatepmthreadlimit' => '25',
+ 'chatpmthreadlimit' => '30',
+ 'chatpmmemberlimit' => '35',
+ 'pmfloodctrl' => '15',
+ 'pmcenter' => '1',
+ 'sendpmseccode' => '1',
+ 'pmsendregdays' => '0',
+ 'maildefault' => 'username@21cn.com',
+ 'mailsend' => '1',
+ 'mailserver' => 'smtp.21cn.com',
+ 'mailport' => '25',
+ 'mailauth' => '1',
+ 'mailfrom' => 'UCenter ',
+ 'mailauth_username' => 'username@21cn.com',
+ 'mailauth_password' => 'password',
+ 'maildelimiter' => '0',
+ 'mailusername' => '1',
+ 'mailsilent' => '1',
+ 'version' => '1.6.0',
+ 'credits' => 'N;',
+);
+
+?>
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/data/index.htm b/extend/fast/ucenter/client/uc_client/data/index.htm
new file mode 100644
index 00000000..e69de29b
diff --git a/extend/fast/ucenter/client/uc_client/index.htm b/extend/fast/ucenter/client/uc_client/index.htm
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/index.htm
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/lib/db.class.php b/extend/fast/ucenter/client/uc_client/lib/db.class.php
new file mode 100644
index 00000000..0c1f20bc
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/db.class.php
@@ -0,0 +1,210 @@
+dbhost = $dbhost;
+ $this->dbuser = $dbuser;
+ $this->dbpw = $dbpw;
+ $this->dbname = $dbname;
+ $this->dbcharset = $dbcharset;
+ $this->pconnect = $pconnect;
+ $this->tablepre = $tablepre;
+ $this->time = $time;
+
+ if ($pconnect)
+ {
+ if (!$this->link = mysql_pconnect($dbhost, $dbuser, $dbpw))
+ {
+ $this->halt('Can not connect to MySQL server');
+ }
+ }
+ else
+ {
+ if (!$this->link = mysql_connect($dbhost, $dbuser, $dbpw))
+ {
+ $this->halt('Can not connect to MySQL server');
+ }
+ }
+
+ if ($this->version() > '4.1')
+ {
+ if ($dbcharset)
+ {
+ mysql_query("SET character_set_connection=" . $dbcharset . ", character_set_results=" . $dbcharset . ", character_set_client=binary", $this->link);
+ }
+
+ if ($this->version() > '5.0.1')
+ {
+ mysql_query("SET sql_mode=''", $this->link);
+ }
+ }
+
+ if ($dbname)
+ {
+ mysql_select_db($dbname, $this->link);
+ }
+ }
+
+ function fetch_array($query, $result_type = MYSQL_ASSOC)
+ {
+ return mysql_fetch_array($query, $result_type);
+ }
+
+ function result_first($sql)
+ {
+ $query = $this->query($sql);
+ return $this->result($query, 0);
+ }
+
+ function fetch_first($sql)
+ {
+ $query = $this->query($sql);
+ return $this->fetch_array($query);
+ }
+
+ function fetch_all($sql, $id = '')
+ {
+ $arr = array();
+ $query = $this->query($sql);
+ while ($data = $this->fetch_array($query))
+ {
+ $id ? $arr[$data[$id]] = $data : $arr[] = $data;
+ }
+ return $arr;
+ }
+
+ function cache_gc()
+ {
+ $this->query("DELETE FROM {$this->tablepre}sqlcaches WHERE expiry<$this->time");
+ }
+
+ function query($sql, $type = '', $cachetime = FALSE)
+ {
+ $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ? 'mysql_unbuffered_query' : 'mysql_query';
+ if (!($query = $func($sql, $this->link)) && $type != 'SILENT')
+ {
+ $this->halt('MySQL Query Error', $sql);
+ }
+ $this->querynum++;
+ $this->histories[] = $sql;
+ return $query;
+ }
+
+ function affected_rows()
+ {
+ return mysql_affected_rows($this->link);
+ }
+
+ function error()
+ {
+ return (($this->link) ? mysql_error($this->link) : mysql_error());
+ }
+
+ function errno()
+ {
+ return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());
+ }
+
+ function result($query, $row)
+ {
+ $query = @mysql_result($query, $row);
+ return $query;
+ }
+
+ function num_rows($query)
+ {
+ $query = mysql_num_rows($query);
+ return $query;
+ }
+
+ function num_fields($query)
+ {
+ return mysql_num_fields($query);
+ }
+
+ function free_result($query)
+ {
+ return mysql_free_result($query);
+ }
+
+ function insert_id()
+ {
+ return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
+ }
+
+ function fetch_row($query)
+ {
+ $query = mysql_fetch_row($query);
+ return $query;
+ }
+
+ function fetch_fields($query)
+ {
+ return mysql_fetch_field($query);
+ }
+
+ function version()
+ {
+ return mysql_get_server_info($this->link);
+ }
+
+ function escape_string($str)
+ {
+ return mysql_escape_string($str);
+ }
+
+ function close()
+ {
+ return mysql_close($this->link);
+ }
+
+ function halt($message = '', $sql = '')
+ {
+ $error = mysql_error();
+ $errorno = mysql_errno();
+ if ($errorno == 2006 && $this->goneaway-- > 0)
+ {
+ $this->connect($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname, $this->dbcharset, $this->pconnect, $this->tablepre, $this->time);
+ $this->query($sql);
+ }
+ else
+ {
+ $s = '';
+ if ($message)
+ {
+ $s = "UCenter info: $message
";
+ }
+ if ($sql)
+ {
+ $s .= 'SQL:' . htmlspecialchars($sql) . '
';
+ }
+ $s .= 'Error:' . $error . '
';
+ $s .= 'Errno:' . $errorno . '
';
+ $s = str_replace(UC_DBTABLEPRE, '[Table]', $s);
+ exit($s);
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/lib/dbi.class.php b/extend/fast/ucenter/client/uc_client/lib/dbi.class.php
new file mode 100644
index 00000000..2972e92c
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/dbi.class.php
@@ -0,0 +1,200 @@
+dbhost = $dbhost;
+ $this->dbuser = $dbuser;
+ $this->dbpw = $dbpw;
+ $this->dbname = $dbname;
+ $this->dbcharset = $dbcharset;
+ $this->pconnect = $pconnect;
+ $this->tablepre = $tablepre;
+ $this->time = $time;
+
+ if (!$this->link = new mysqli($dbhost, $dbuser, $dbpw, $dbname))
+ {
+ $this->halt('Can not connect to MySQL server');
+ }
+
+ if ($this->version() > '4.1')
+ {
+ if ($dbcharset)
+ {
+ $this->link->set_charset($dbcharset);
+ }
+
+ if ($this->version() > '5.0.1')
+ {
+ $this->link->query("SET sql_mode=''");
+ }
+ }
+ }
+
+ function fetch_array($query, $result_type = MYSQLI_ASSOC)
+ {
+ return $query ? $query->fetch_array($result_type) : null;
+ }
+
+ function result_first($sql)
+ {
+ $query = $this->query($sql);
+ return $this->result($query, 0);
+ }
+
+ function fetch_first($sql)
+ {
+ $query = $this->query($sql);
+ return $this->fetch_array($query);
+ }
+
+ function fetch_all($sql, $id = '')
+ {
+ $arr = array();
+ $query = $this->query($sql);
+ while ($data = $this->fetch_array($query))
+ {
+ $id ? $arr[$data[$id]] = $data : $arr[] = $data;
+ }
+ return $arr;
+ }
+
+ function cache_gc()
+ {
+ $this->query("DELETE FROM {$this->tablepre}sqlcaches WHERE expiry<$this->time");
+ }
+
+ function query($sql, $type = '', $cachetime = FALSE)
+ {
+ $resultmode = $type == 'UNBUFFERED' ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT;
+ if (!($query = $this->link->query($sql, $resultmode)) && $type != 'SILENT')
+ {
+ $this->halt('MySQL Query Error', $sql);
+ }
+ $this->querynum++;
+ $this->histories[] = $sql;
+ return $query;
+ }
+
+ function affected_rows()
+ {
+ return $this->link->affected_rows;
+ }
+
+ function error()
+ {
+ return (($this->link) ? $this->link->error : mysqli_error());
+ }
+
+ function errno()
+ {
+ return intval(($this->link) ? $this->link->errno : mysqli_errno());
+ }
+
+ function result($query, $row)
+ {
+ if (!$query || $query->num_rows == 0)
+ {
+ return null;
+ }
+ $query->data_seek($row);
+ $assocs = $query->fetch_row();
+ return $assocs[0];
+ }
+
+ function num_rows($query)
+ {
+ $query = $query ? $query->num_rows : 0;
+ return $query;
+ }
+
+ function num_fields($query)
+ {
+ return $query ? $query->field_count : 0;
+ }
+
+ function free_result($query)
+ {
+ return $query ? $query->free() : false;
+ }
+
+ function insert_id()
+ {
+ return ($id = $this->link->insert_id) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
+ }
+
+ function fetch_row($query)
+ {
+ $query = $query ? $query->fetch_row() : null;
+ return $query;
+ }
+
+ function fetch_fields($query)
+ {
+ return $query ? $query->fetch_field() : null;
+ }
+
+ function version()
+ {
+ return $this->link->server_info;
+ }
+
+ function escape_string($str)
+ {
+ return $this->link->escape_string($str);
+ }
+
+ function close()
+ {
+ return $this->link->close();
+ }
+
+ function halt($message = '', $sql = '')
+ {
+ $error = $this->error();
+ $errorno = $this->errno();
+ if ($errorno == 2006 && $this->goneaway-- > 0)
+ {
+ $this->connect($this->dbhost, $this->dbuser, $this->dbpw, $this->dbname, $this->dbcharset, $this->pconnect, $this->tablepre, $this->time);
+ $this->query($sql);
+ }
+ else
+ {
+ $s = '';
+ if ($message)
+ {
+ $s = "UCenter info: $message
";
+ }
+ if ($sql)
+ {
+ $s .= 'SQL:' . htmlspecialchars($sql) . '
';
+ }
+ $s .= 'Error:' . $error . '
';
+ $s .= 'Errno:' . $errorno . '
';
+ $s = str_replace(UC_DBTABLEPRE, '[Table]', $s);
+ exit($s);
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/lib/index.htm b/extend/fast/ucenter/client/uc_client/lib/index.htm
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/index.htm
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php b/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php
new file mode 100644
index 00000000..dcc165da
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/sendmail.inc.php
@@ -0,0 +1,159 @@
+base->cache['apps'][$mail['appid']]['name'];
+$mail['subject'] = '=?' . $mail['charset'] . '?B?' . base64_encode(str_replace("\r", '', str_replace("\n", '', '[' . $appname . '] ' . $mail['subject']))) . '?=';
+$mail['message'] = chunk_split(base64_encode(str_replace("\r\n.", " \r\n..", str_replace("\n", "\r\n", str_replace("\r", "\n", str_replace("\r\n", "\n", str_replace("\n\r", "\r", $mail['message'])))))));
+
+$email_from = $mail['frommail'] == '' ? '=?' . $mail['charset'] . '?B?' . base64_encode($appname) . "?= <$mail_setting[maildefault]>" : (preg_match('/^(.+?) \<(.+?)\>$/', $email_from, $from) ? '=?' . $mail['charset'] . '?B?' . base64_encode($from[1]) . "?= <$from[2]>" : $mail['frommail']);
+
+foreach (explode(',', $mail['email_to']) as $touser)
+{
+ $tousers[] = preg_match('/^(.+?) \<(.+?)\>$/', $touser, $to) ? ($mailusername ? '=?' . $mail['charset'] . '?B?' . base64_encode($to[1]) . "?= <$to[2]>" : $to[2]) : $touser;
+}
+
+$mail['email_to'] = implode(',', $tousers);
+
+$headers = "From: $email_from{$maildelimiter}X-Priority: 3{$maildelimiter}X-Mailer: Discuz! $version{$maildelimiter}MIME-Version: 1.0{$maildelimiter}Content-type: text/" . ($mail['htmlon'] ? 'html' : 'plain') . "; charset=$mail[charset]{$maildelimiter}Content-Transfer-Encoding: base64{$maildelimiter}";
+
+$mail_setting['mailport'] = $mail_setting['mailport'] ? $mail_setting['mailport'] : 25;
+
+if ($mail_setting['mailsend'] == 1 && function_exists('mail'))
+{
+
+ return @mail($mail['email_to'], $mail['subject'], $mail['message'], $headers);
+}
+elseif ($mail_setting['mailsend'] == 2)
+{
+
+ if (!$fp = fsocketopen($mail_setting['mailserver'], $mail_setting['mailport'], $errno, $errstr, 30))
+ {
+ return false;
+ }
+
+ stream_set_blocking($fp, true);
+
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != '220')
+ {
+ return false;
+ }
+
+ fputs($fp, ($mail_setting['mailauth'] ? 'EHLO' : 'HELO') . " discuz\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250)
+ {
+ return false;
+ }
+
+ while (1)
+ {
+ if (substr($lastmessage, 3, 1) != '-' || empty($lastmessage))
+ {
+ break;
+ }
+ $lastmessage = fgets($fp, 512);
+ }
+
+ if ($mail_setting['mailauth'])
+ {
+ fputs($fp, "AUTH LOGIN\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 334)
+ {
+ return false;
+ }
+
+ fputs($fp, base64_encode($mail_setting['mailauth_username']) . "\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 334)
+ {
+ return false;
+ }
+
+ fputs($fp, base64_encode($mail_setting['mailauth_password']) . "\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 235)
+ {
+ return false;
+ }
+
+ $email_from = $mail_setting['mailfrom'];
+ }
+
+ fputs($fp, "MAIL FROM: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from) . ">\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 250)
+ {
+ fputs($fp, "MAIL FROM: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from) . ">\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 250)
+ {
+ return false;
+ }
+ }
+
+ $email_tos = array();
+ foreach (explode(',', $mail['email_to']) as $touser)
+ {
+ $touser = trim($touser);
+ if ($touser)
+ {
+ fputs($fp, "RCPT TO: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser) . ">\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 250)
+ {
+ fputs($fp, "RCPT TO: <" . preg_replace("/.*\<(.+?)\>.*/", "\\1", $touser) . ">\r\n");
+ $lastmessage = fgets($fp, 512);
+ return false;
+ }
+ }
+ }
+
+ fputs($fp, "DATA\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 354)
+ {
+ return false;
+ }
+
+ $headers .= 'Message-ID: <' . gmdate('YmdHs') . '.' . substr(md5($mail['message'] . microtime()), 0, 6) . rand(100000, 999999) . '@' . $_SERVER['HTTP_HOST'] . ">{$maildelimiter}";
+
+ fputs($fp, "Date: " . gmdate('r') . "\r\n");
+ fputs($fp, "To: " . $mail['email_to'] . "\r\n");
+ fputs($fp, "Subject: " . $mail['subject'] . "\r\n");
+ fputs($fp, $headers . "\r\n");
+ fputs($fp, "\r\n\r\n");
+ fputs($fp, "$mail[message]\r\n.\r\n");
+ $lastmessage = fgets($fp, 512);
+ if (substr($lastmessage, 0, 3) != 250)
+ {
+ return false;
+ }
+
+ fputs($fp, "QUIT\r\n");
+ return true;
+}
+elseif ($mail_setting['mailsend'] == 3)
+{
+
+ ini_set('SMTP', $mail_setting['mailserver']);
+ ini_set('smtp_port', $mail_setting['mailport']);
+ ini_set('sendmail_from', $email_from);
+
+ return @mail($mail['email_to'], $mail['subject'], $mail['message'], $headers);
+}
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/lib/uccode.class.php b/extend/fast/ucenter/client/uc_client/lib/uccode.class.php
new file mode 100644
index 00000000..47150b54
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/uccode.class.php
@@ -0,0 +1,174 @@
+uccode();
+ }
+
+ function uccode()
+ {
+ $this->uccode = array(
+ 'pcodecount' => -1,
+ 'codecount' => 0,
+ 'codehtml' => ''
+ );
+ }
+
+ function codedisp($code)
+ {
+ $this->uccode['pcodecount'] ++;
+ $code = str_replace('\\"', '"', preg_replace("/^[\n\r]*(.+?)[\n\r]*$/is", "\\1", $code));
+ $this->uccode['codehtml'][$this->uccode['pcodecount']] = $this->tpl_codedisp($code);
+ $this->uccode['codecount'] ++;
+ return "[\tUCENTER_CODE_" . $this->uccode[pcodecount] . "\t]";
+ }
+
+ function complie($message)
+ {
+ $message = dhtmlspecialchars($message);
+ if (strpos($message, '[/code]') !== FALSE)
+ {
+ $message = preg_replace("/\s*\[code\](.+?)\[\/code\]\s*/ies", "\$this->codedisp('\\1')", $message);
+ }
+ if (strpos($message, '[/url]') !== FALSE)
+ {
+ $message = preg_replace("/\[url(=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\/\/|www\.)([^\[\"']+?))?\](.+?)\[\/url\]/ies", "\$this->parseurl('\\1', '\\5')", $message);
+ }
+ if (strpos($message, '[/email]') !== FALSE)
+ {
+ $message = preg_replace("/\[email(=([a-z0-9\-_.+]+)@([a-z0-9\-_]+[.][a-z0-9\-_.]+))?\](.+?)\[\/email\]/ies", "\$this->parseemail('\\1', '\\4')", $message);
+ }
+ $message = str_replace(array(
+ '[/color]', '[/size]', '[/font]', '[/align]', '[b]', '[/b]',
+ '[i]', '[/i]', '[u]', '[/u]', '[list]', '[list=1]', '[list=a]',
+ '[list=A]', '[*]', '[/list]', '[indent]', '[/indent]', '[/float]'
+ ), array(
+ '', '', '', '
', '', '', '',
+ '', '', '', '', '', '',
+ '', '', '
', ''
+ ), preg_replace(array(
+ "/\[color=([#\w]+?)\]/i",
+ "/\[size=(\d+?)\]/i",
+ "/\[size=(\d+(\.\d+)?(px|pt|in|cm|mm|pc|em|ex|%)+?)\]/i",
+ "/\[font=([^\[\<]+?)\]/i",
+ "/\[align=(left|center|right)\]/i",
+ "/\[float=(left|right)\]/i"
+ ), array(
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ), $message));
+ if (strpos($message, '[/quote]') !== FALSE)
+ {
+ $message = preg_replace("/\s*\[quote\][\n\r]*(.+?)[\n\r]*\[\/quote\]\s*/is", $this->tpl_quote(), $message);
+ }
+ if (strpos($message, '[/img]') !== FALSE)
+ {
+ $message = preg_replace(array(
+ "/\[img\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ies",
+ "/\[img=(\d{1,4})[x|\,](\d{1,4})\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ies"
+ ), array(
+ "\$this->bbcodeurl('\\1', '
')",
+ "\$this->bbcodeurl('\\3', '
')"
+ ), $message);
+ }
+ for ($i = 0; $i <= $this->uccode['pcodecount']; $i++)
+ {
+ $message = str_replace("[\tUCENTER_CODE_$i\t]", $this->uccode['codehtml'][$i], $message);
+ }
+ return nl2br(str_replace(array("\t", ' ', ' '), array(' ', ' ', ' '), $message));
+ }
+
+ function parseurl($url, $text)
+ {
+ if (!$url && preg_match("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\/\/|www\.)[^\[\"']+/i", trim($text), $matches))
+ {
+ $url = $matches[0];
+ $length = 65;
+ if (strlen($url) > $length)
+ {
+ $text = substr($url, 0, intval($length * 0.5)) . ' ... ' . substr($url, - intval($length * 0.3));
+ }
+ return '' . $text . '';
+ }
+ else
+ {
+ $url = substr($url, 1);
+ if (substr(strtolower($url), 0, 4) == 'www.')
+ {
+ $url = 'http://' . $url;
+ }
+ return '' . $text . '';
+ }
+ }
+
+ function parseemail($email, $text)
+ {
+ $text = str_replace('\"', '"', $text);
+ if (!$email && preg_match("/\s*([a-z0-9\-_.+]+)@([a-z0-9\-_]+[.][a-z0-9\-_.]+)\s*/i", $text, $matches))
+ {
+ $email = trim($matches[0]);
+ return '' . $email . '';
+ }
+ else
+ {
+ return '' . $text . '';
+ }
+ }
+
+ function bbcodeurl($url, $tags)
+ {
+ if (!preg_match("/<.+?>/s", $url))
+ {
+ if (!in_array(strtolower(substr($url, 0, 6)), array('http:/', 'https:', 'ftp://', 'rtsp:/', 'mms://')))
+ {
+ $url = 'http://' . $url;
+ }
+ return str_replace(array('submit', 'logging.php'), array('', ''), sprintf($tags, $url, addslashes($url)));
+ }
+ else
+ {
+ return ' ' . $url;
+ }
+ }
+
+ function tpl_codedisp($code)
+ {
+ return '' . $code . '
';
+ }
+
+ function tpl_quote()
+ {
+ return '';
+ }
+
+}
+
+/*
+
+Usage:
+$str = <<uccode = new uccode();
+echo $this->uccode->complie($str);
+
+*/
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/lib/xml.class.php b/extend/fast/ucenter/client/uc_client/lib/xml.class.php
new file mode 100644
index 00000000..73c528bb
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/lib/xml.class.php
@@ -0,0 +1,129 @@
+parse($xml);
+ $xml_parser->destruct();
+ return $data;
+}
+
+function xml_serialize($arr, $htmlon = FALSE, $isnormal = FALSE, $level = 1)
+{
+ $s = $level == 1 ? "\r\n\r\n" : '';
+ $space = str_repeat("\t", $level);
+ foreach ($arr as $k => $v)
+ {
+ if (!is_array($v))
+ {
+ $s .= $space . "- " . ($htmlon ? '' : '') . "
\r\n";
+ }
+ else
+ {
+ $s .= $space . "- \r\n" . xml_serialize($v, $htmlon, $isnormal, $level + 1) . $space . "
\r\n";
+ }
+ }
+ $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
+ return $level == 1 ? $s . "" : $s;
+}
+
+class XML
+{
+
+ var $parser;
+ var $document;
+ var $stack;
+ var $data;
+ var $last_opened_tag;
+ var $isnormal;
+ var $attrs = array();
+ var $failed = FALSE;
+
+ function __construct($isnormal)
+ {
+ $this->XML($isnormal);
+ }
+
+ function XML($isnormal)
+ {
+ $this->isnormal = $isnormal;
+ $this->parser = xml_parser_create('ISO-8859-1');
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_object($this->parser, $this);
+ xml_set_element_handler($this->parser, 'open', 'close');
+ xml_set_character_data_handler($this->parser, 'data');
+ }
+
+ function destruct()
+ {
+ xml_parser_free($this->parser);
+ }
+
+ function parse(&$data)
+ {
+ $this->document = array();
+ $this->stack = array();
+ return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : '';
+ }
+
+ function open(&$parser, $tag, $attributes)
+ {
+ $this->data = '';
+ $this->failed = FALSE;
+ if (!$this->isnormal)
+ {
+ if (isset($attributes['id']) && !is_string($this->document[$attributes['id']]))
+ {
+ $this->document = &$this->document[$attributes['id']];
+ }
+ else
+ {
+ $this->failed = TRUE;
+ }
+ }
+ else
+ {
+ if (!isset($this->document[$tag]) || !is_string($this->document[$tag]))
+ {
+ $this->document = &$this->document[$tag];
+ }
+ else
+ {
+ $this->failed = TRUE;
+ }
+ }
+ $this->stack[] = &$this->document;
+ $this->last_opened_tag = $tag;
+ $this->attrs = $attributes;
+ }
+
+ function data(&$parser, $data)
+ {
+ if ($this->last_opened_tag != NULL)
+ {
+ $this->data .= $data;
+ }
+ }
+
+ function close(&$parser, $tag)
+ {
+ if ($this->last_opened_tag == $tag)
+ {
+ $this->document = $this->data;
+ $this->last_opened_tag = NULL;
+ }
+ array_pop($this->stack);
+ if ($this->stack)
+ {
+ $this->document = &$this->stack[count($this->stack) - 1];
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/app.php b/extend/fast/ucenter/client/uc_client/model/app.php
new file mode 100644
index 00000000..a3fdac59
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/app.php
@@ -0,0 +1,40 @@
+appmodel($base);
+ }
+
+ function appmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function get_apps($col = '*', $where = '')
+ {
+ $arr = $this->db->fetch_all("SELECT $col FROM " . UC_DBTABLEPRE . "applications" . ($where ? ' WHERE ' . $where : ''), 'appid');
+ foreach ($arr as $k => $v)
+ {
+ isset($v['extra']) && !empty($v['extra']) && $v['extra'] = unserialize($v['extra']);
+ unset($v['authkey']);
+ $arr[$k] = $v;
+ }
+ return $arr;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/base.php b/extend/fast/ucenter/client/uc_client/model/base.php
new file mode 100644
index 00000000..32dcf161
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/base.php
@@ -0,0 +1,347 @@
+base();
+ }
+
+ function base()
+ {
+ $this->init_var();
+ $this->init_db();
+ $this->init_cache();
+ $this->init_note();
+ $this->init_mail();
+ }
+
+ function init_var()
+ {
+ $this->time = time();
+ $cip = getenv('HTTP_CLIENT_IP');
+ $xip = getenv('HTTP_X_FORWARDED_FOR');
+ $rip = getenv('REMOTE_ADDR');
+ $srip = $_SERVER['REMOTE_ADDR'];
+ if ($cip && strcasecmp($cip, 'unknown'))
+ {
+ $this->onlineip = $cip;
+ }
+ elseif ($xip && strcasecmp($xip, 'unknown'))
+ {
+ $this->onlineip = $xip;
+ }
+ elseif ($rip && strcasecmp($rip, 'unknown'))
+ {
+ $this->onlineip = $rip;
+ }
+ elseif ($srip && strcasecmp($srip, 'unknown'))
+ {
+ $this->onlineip = $srip;
+ }
+ preg_match("/[\d\.]{7,15}/", $this->onlineip, $match);
+ $this->onlineip = $match[0] ? $match[0] : 'unknown';
+ $this->app['appid'] = UC_APPID;
+ }
+
+ function init_input()
+ {
+
+ }
+
+ function init_db()
+ {
+ if (function_exists("mysqli_connect"))
+ {
+ require_once UC_ROOT . 'lib/dbi.class.php';
+ }
+ else
+ {
+ require_once UC_ROOT . 'lib/db.class.php';
+ }
+ $this->db = new ucclient_db();
+ $this->db->connect(UC_DBHOST, UC_DBUSER, UC_DBPW, '', UC_DBCHARSET, UC_DBCONNECT, UC_DBTABLEPRE);
+ }
+
+ function load($model, $base = NULL)
+ {
+ $base = $base ? $base : $this;
+ if (empty($_ENV[$model]))
+ {
+ require_once UC_ROOT . "./model/{$model}.php";
+ $classname = $model . 'model';
+ $_ENV[$model] = new $classname($base);
+ }
+ return $_ENV[$model];
+ }
+
+ function date($time, $type = 3)
+ {
+ if (!$this->settings)
+ {
+ $this->settings = $this->cache('settings');
+ }
+ $format[] = $type & 2 ? (!empty($this->settings['dateformat']) ? $this->settings['dateformat'] : 'Y-n-j') : '';
+ $format[] = $type & 1 ? (!empty($this->settings['timeformat']) ? $this->settings['timeformat'] : 'H:i') : '';
+ return gmdate(implode(' ', $format), $time + $this->settings['timeoffset']);
+ }
+
+ function page_get_start($page, $ppp, $totalnum)
+ {
+ $totalpage = ceil($totalnum / $ppp);
+ $page = max(1, min($totalpage, intval($page)));
+ return ($page - 1) * $ppp;
+ }
+
+ function implode($arr)
+ {
+ return "'" . implode("','", (array) $arr) . "'";
+ }
+
+ function &cache($cachefile)
+ {
+ static $_CACHE = array();
+ if (!isset($_CACHE[$cachefile]))
+ {
+ $cachepath = UC_DATADIR . './cache/' . $cachefile . '.php';
+ if (!file_exists($cachepath))
+ {
+ $this->load('cache');
+ $_ENV['cache']->updatedata($cachefile);
+ }
+ else
+ {
+ include_once $cachepath;
+ }
+ }
+ return $_CACHE[$cachefile];
+ }
+
+ function get_setting($k = array(), $decode = FALSE)
+ {
+ $return = array();
+ $sqladd = $k ? "WHERE k IN (" . $this->implode($k) . ")" : '';
+ $settings = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "settings $sqladd");
+ if (is_array($settings))
+ {
+ foreach ($settings as $arr)
+ {
+ $return[$arr['k']] = $decode ? unserialize($arr['v']) : $arr['v'];
+ }
+ }
+ return $return;
+ }
+
+ function init_cache()
+ {
+ $this->settings = $this->cache('settings');
+ $this->cache['apps'] = $this->cache('apps');
+
+ if (PHP_VERSION > '5.1')
+ {
+ $timeoffset = intval($this->settings['timeoffset'] / 3600);
+ @date_default_timezone_set('Etc/GMT' . ($timeoffset > 0 ? '-' : '+') . (abs($timeoffset)));
+ }
+ }
+
+ function cutstr($string, $length, $dot = ' ...')
+ {
+ if (strlen($string) <= $length)
+ {
+ return $string;
+ }
+
+ $string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
+
+ $strcut = '';
+ if (strtolower(UC_CHARSET) == 'utf-8')
+ {
+
+ $n = $tn = $noc = 0;
+ while ($n < strlen($string))
+ {
+
+ $t = ord($string[$n]);
+ if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126))
+ {
+ $tn = 1;
+ $n++;
+ $noc++;
+ }
+ elseif (194 <= $t && $t <= 223)
+ {
+ $tn = 2;
+ $n += 2;
+ $noc += 2;
+ }
+ elseif (224 <= $t && $t < 239)
+ {
+ $tn = 3;
+ $n += 3;
+ $noc += 2;
+ }
+ elseif (240 <= $t && $t <= 247)
+ {
+ $tn = 4;
+ $n += 4;
+ $noc += 2;
+ }
+ elseif (248 <= $t && $t <= 251)
+ {
+ $tn = 5;
+ $n += 5;
+ $noc += 2;
+ }
+ elseif ($t == 252 || $t == 253)
+ {
+ $tn = 6;
+ $n += 6;
+ $noc += 2;
+ }
+ else
+ {
+ $n++;
+ }
+
+ if ($noc >= $length)
+ {
+ break;
+ }
+ }
+ if ($noc > $length)
+ {
+ $n -= $tn;
+ }
+
+ $strcut = substr($string, 0, $n);
+ }
+ else
+ {
+ for ($i = 0; $i < $length; $i++)
+ {
+ $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
+ }
+ }
+
+ $strcut = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $strcut);
+
+ return $strcut . $dot;
+ }
+
+ function init_note()
+ {
+ if ($this->note_exists())
+ {
+ $this->load('note');
+ $_ENV['note']->send();
+ }
+ }
+
+ function note_exists()
+ {
+ $noteexists = $this->db->result_first("SELECT value FROM " . UC_DBTABLEPRE . "vars WHERE name='noteexists" . UC_APPID . "'");
+ if (empty($noteexists))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ function init_mail()
+ {
+ if ($this->mail_exists() && !getgpc('inajax'))
+ {
+ $this->load('mail');
+ $_ENV['mail']->send();
+ }
+ }
+
+ function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
+ {
+ return uc_authcode($string, $operation, $key, $expiry);
+ }
+
+ function unserialize($s)
+ {
+ return uc_unserialize($s);
+ }
+
+ function input($k)
+ {
+ return isset($this->input[$k]) ? (is_array($this->input[$k]) ? $this->input[$k] : trim($this->input[$k])) : NULL;
+ }
+
+ function mail_exists()
+ {
+ $mailexists = $this->db->result_first("SELECT value FROM " . UC_DBTABLEPRE . "vars WHERE name='mailexists'");
+ if (empty($mailexists))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ function dstripslashes($string)
+ {
+ if (is_array($string))
+ {
+ foreach ($string as $key => $val)
+ {
+ $string[$key] = $this->dstripslashes($val);
+ }
+ }
+ else
+ {
+ $string = stripslashes($string);
+ }
+ return $string;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/cache.php b/extend/fast/ucenter/client/uc_client/model/cache.php
new file mode 100644
index 00000000..d0851ede
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/cache.php
@@ -0,0 +1,119 @@
+cachemodel($base);
+ }
+
+ function cachemodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ $this->map = array(
+ 'settings' => array('settings'),
+ 'badwords' => array('badwords'),
+ 'apps' => array('apps')
+ );
+ }
+
+ function updatedata($cachefile = '')
+ {
+ if ($cachefile)
+ {
+ foreach ((array) $this->map[$cachefile] as $modules)
+ {
+ $s = "$method(), TRUE) . ";\r\n";
+ }
+ $s .= "\r\n?>";
+ @file_put_contents(UC_DATADIR . "./cache/$cachefile.php", $s);
+ }
+ }
+ else
+ {
+ foreach ((array) $this->map as $file => $modules)
+ {
+ $s = "$method(), TRUE) . ";\r\n";
+ }
+ $s .= "\r\n?>";
+ @file_put_contents(UC_DATADIR . "./cache/$file.php", $s);
+ }
+ }
+ }
+
+ function updatetpl()
+ {
+
+ }
+
+ function _get_badwords()
+ {
+ $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "badwords");
+ $return = array();
+ if (is_array($data))
+ {
+ foreach ($data as $k => $v)
+ {
+ $return['findpattern'][$k] = $v['findpattern'];
+ $return['replace'][$k] = $v['replacement'];
+ }
+ }
+ return $return;
+ }
+
+ function _get_apps()
+ {
+ $this->base->load('app');
+ $apps = $_ENV['app']->get_apps();
+ $apps2 = array();
+ if (is_array($apps))
+ {
+ foreach ($apps as $v)
+ {
+ $v['extra'] = unserialize($v['extra']);
+ $apps2[$v['appid']] = $v;
+ }
+ }
+ return $apps2;
+ }
+
+ function _get_settings()
+ {
+ return $this->base->get_setting();
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/domain.php b/extend/fast/ucenter/client/uc_client/model/domain.php
new file mode 100644
index 00000000..6fc966fe
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/domain.php
@@ -0,0 +1,63 @@
+domainmodel($base);
+ }
+
+ function domainmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function add_domain($domain, $ip)
+ {
+ if ($domain)
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "domains SET domain='$domain', ip='$ip'");
+ }
+ return $this->db->insert_id();
+ }
+
+ function get_total_num()
+ {
+ $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "domains");
+ return $data;
+ }
+
+ function get_list($page, $ppp, $totalnum)
+ {
+ $start = $this->base->page_get_start($page, $ppp, $totalnum);
+ $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "domains LIMIT $start, $ppp");
+ return $data;
+ }
+
+ function delete_domain($arr)
+ {
+ $domainids = $this->base->implode($arr);
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "domains WHERE id IN ($domainids)");
+ return $this->db->affected_rows();
+ }
+
+ function update_domain($domain, $ip, $id)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "domains SET domain='$domain', ip='$ip' WHERE id='$id'");
+ return $this->db->affected_rows();
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/friend.php b/extend/fast/ucenter/client/uc_client/model/friend.php
new file mode 100644
index 00000000..58c641aa
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/friend.php
@@ -0,0 +1,148 @@
+friendmodel($base);
+ }
+
+ function friendmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function add($uid, $friendid, $comment = '')
+ {
+ $direction = $this->db->result_first("SELECT direction FROM " . UC_DBTABLEPRE . "friends WHERE uid='$friendid' AND friendid='$uid' LIMIT 1");
+ if ($direction == 1)
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "friends SET uid='$uid', friendid='$friendid', comment='$comment', direction='3'", 'SILENT');
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "friends SET direction='3' WHERE uid='$friendid' AND friendid='$uid'");
+ return 1;
+ }
+ elseif ($direction == 2)
+ {
+ return 1;
+ }
+ elseif ($direction == 3)
+ {
+ return -1;
+ }
+ else
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "friends SET uid='$uid', friendid='$friendid', comment='$comment', direction='1'", 'SILENT');
+ return $this->db->insert_id();
+ }
+ }
+
+ function delete($uid, $friendids)
+ {
+ $friendids = $this->base->implode($friendids);
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "friends WHERE uid='$uid' AND friendid IN ($friendids)");
+ $affectedrows = $this->db->affected_rows();
+ if ($affectedrows > 0)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "friends SET direction=1 WHERE uid IN ($friendids) AND friendid='$uid' AND direction='3'");
+ }
+ return $affectedrows;
+ }
+
+ function get_totalnum_by_uid($uid, $direction = 0)
+ {
+ $sqladd = '';
+ if ($direction == 0)
+ {
+ $sqladd = "uid='$uid'";
+ }
+ elseif ($direction == 1)
+ {
+ $sqladd = "uid='$uid' AND direction='1'";
+ }
+ elseif ($direction == 2)
+ {
+ $sqladd = "friendid='$uid' AND direction='1'";
+ }
+ elseif ($direction == 3)
+ {
+ $sqladd = "uid='$uid' AND direction='3'";
+ }
+ $totalnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "friends WHERE $sqladd");
+ return $totalnum;
+ }
+
+ function get_list($uid, $page, $pagesize, $totalnum, $direction = 0)
+ {
+ $start = $this->base->page_get_start($page, $pagesize, $totalnum);
+ $sqladd = '';
+ if ($direction == 0)
+ {
+ $sqladd = "f.uid='$uid'";
+ }
+ elseif ($direction == 1)
+ {
+ $sqladd = "f.uid='$uid' AND f.direction='1'";
+ }
+ elseif ($direction == 2)
+ {
+ $sqladd = "f.friendid='$uid' AND f.direction='1'";
+ }
+ elseif ($direction == 3)
+ {
+ $sqladd = "f.uid='$uid' AND f.direction='3'";
+ }
+ if ($sqladd)
+ {
+ $data = $this->db->fetch_all("SELECT f.*, m.username FROM " . UC_DBTABLEPRE . "friends f LEFT JOIN " . UC_DBTABLEPRE . "members m ON f.friendid=m.uid WHERE $sqladd LIMIT $start, $pagesize");
+ return $data;
+ }
+ else
+ {
+ return array();
+ }
+ }
+
+ function is_friend($uid, $friendids, $direction = 0)
+ {
+ $friendid_str = implode("', '", $friendids);
+ $sqladd = '';
+ if ($direction == 0)
+ {
+ $sqladd = "uid='$uid'";
+ }
+ elseif ($direction == 1)
+ {
+ $sqladd = "uid='$uid' AND friendid IN ('$friendid_str') AND direction='1'";
+ }
+ elseif ($direction == 2)
+ {
+ $sqladd = "friendid='$uid' AND uid IN ('$friendid_str') AND direction='1'";
+ }
+ elseif ($direction == 3)
+ {
+ $sqladd = "uid='$uid' AND friendid IN ('$friendid_str') AND direction='3'";
+ }
+ if ($this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "friends WHERE $sqladd") == count($friendids))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/index.htm b/extend/fast/ucenter/client/uc_client/model/index.htm
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/index.htm
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extend/fast/ucenter/client/uc_client/model/mail.php b/extend/fast/ucenter/client/uc_client/model/mail.php
new file mode 100644
index 00000000..46e9983d
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/mail.php
@@ -0,0 +1,181 @@
+mailmodel($base);
+ }
+
+ function mailmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ $this->apps = &$this->base->cache['apps'];
+ }
+
+ function get_total_num()
+ {
+ $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "mailqueue");
+ return $data;
+ }
+
+ function get_list($page, $ppp, $totalnum)
+ {
+ $start = $this->base->page_get_start($page, $ppp, $totalnum);
+ $data = $this->db->fetch_all("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid ORDER BY dateline DESC LIMIT $start, $ppp");
+ foreach ((array) $data as $k => $v)
+ {
+ $data[$k]['subject'] = dhtmlspecialchars($v['subject']);
+ $data[$k]['tomail'] = empty($v['tomail']) ? $v['email'] : $v['tomail'];
+ $data[$k]['dateline'] = $v['dateline'] ? $this->base->date($data[$k]['dateline']) : '';
+ $data[$k]['appname'] = $this->base->cache['apps'][$v['appid']]['name'];
+ }
+ return $data;
+ }
+
+ function delete_mail($ids)
+ {
+ $ids = $this->base->implode($ids);
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mailqueue WHERE mailid IN ($ids)");
+ return $this->db->affected_rows();
+ }
+
+ function add($mail)
+ {
+ if ($mail['level'])
+ {
+ $sql = "INSERT INTO " . UC_DBTABLEPRE . "mailqueue (touid, tomail, subject, message, frommail, charset, htmlon, level, dateline, failures, appid) VALUES ";
+ $values_arr = array();
+ foreach ($mail['uids'] as $uid)
+ {
+ if (empty($uid))
+ continue;
+ $values_arr[] = "('$uid', '', '$mail[subject]', '$mail[message]', '$mail[frommail]', '$mail[charset]', '$mail[htmlon]', '$mail[level]', '$mail[dateline]', '0', '$mail[appid]')";
+ }
+ foreach ($mail['emails'] as $email)
+ {
+ if (empty($email))
+ continue;
+ $values_arr[] = "('', '$email', '$mail[subject]', '$mail[message]', '$mail[frommail]', '$mail[charset]', '$mail[htmlon]', '$mail[level]', '$mail[dateline]', '0', '$mail[appid]')";
+ }
+ $sql .= implode(',', $values_arr);
+ $this->db->query($sql);
+ $insert_id = $this->db->insert_id();
+ $insert_id && $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='mailexists', value='1'");
+ return $insert_id;
+ } else
+ {
+ $mail['email_to'] = array();
+ $uids = 0;
+ foreach ($mail['uids'] as $uid)
+ {
+ if (empty($uid))
+ continue;
+ $uids .= ',' . $uid;
+ }
+ $users = $this->db->fetch_all("SELECT uid, username, email FROM " . UC_DBTABLEPRE . "members WHERE uid IN ($uids)");
+ foreach ($users as $v)
+ {
+ $mail['email_to'][] = $v['username'] . '<' . $v['email'] . '>';
+ }
+ foreach ($mail['emails'] as $email)
+ {
+ if (empty($email))
+ continue;
+ $mail['email_to'][] = $email;
+ }
+ $mail['message'] = str_replace('\"', '"', $mail['message']);
+ $mail['email_to'] = implode(',', $mail['email_to']);
+ return $this->send_one_mail($mail);
+ }
+ }
+
+ function send()
+ {
+ register_shutdown_function(array($this, '_send'));
+ }
+
+ function _send()
+ {
+
+ $mail = $this->_get_mail();
+ if (empty($mail))
+ {
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='mailexists', value='0'");
+ return NULL;
+ }
+ else
+ {
+ $mail['email_to'] = $mail['tomail'] ? $mail['tomail'] : $mail['username'] . '<' . $mail['email'] . '>';
+ if ($this->send_one_mail($mail))
+ {
+ $this->_delete_one_mail($mail['mailid']);
+ return true;
+ }
+ else
+ {
+ $this->_update_failures($mail['mailid']);
+ return false;
+ }
+ }
+ }
+
+ function send_by_id($mailid)
+ {
+ if ($this->send_one_mail($this->_get_mail_by_id($mailid)))
+ {
+ $this->_delete_one_mail($mailid);
+ return true;
+ }
+ }
+
+ function send_one_mail($mail)
+ {
+ if (empty($mail))
+ return;
+ $mail['email_to'] = $mail['email_to'] ? $mail['email_to'] : $mail['username'] . '<' . $mail['email'] . '>';
+ $mail_setting = $this->base->settings;
+ return include UC_ROOT . 'lib/sendmail.inc.php';
+ }
+
+ function _get_mail()
+ {
+ $data = $this->db->fetch_first("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid WHERE failures<'" . UC_MAIL_REPEAT . "' ORDER BY level DESC, mailid ASC LIMIT 1");
+ return $data;
+ }
+
+ function _get_mail_by_id($mailid)
+ {
+ $data = $this->db->fetch_first("SELECT m.*, u.username, u.email FROM " . UC_DBTABLEPRE . "mailqueue m LEFT JOIN " . UC_DBTABLEPRE . "members u ON m.touid=u.uid WHERE mailid='$mailid'");
+ return $data;
+ }
+
+ function _delete_one_mail($mailid)
+ {
+ $mailid = intval($mailid);
+ return $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "mailqueue WHERE mailid='$mailid'");
+ }
+
+ function _update_failures($mailid)
+ {
+ $mailid = intval($mailid);
+ return $this->db->query("UPDATE " . UC_DBTABLEPRE . "mailqueue SET failures=failures+1 WHERE mailid='$mailid'");
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/misc.php b/extend/fast/ucenter/client/uc_client/model/misc.php
new file mode 100644
index 00000000..bb83ab50
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/misc.php
@@ -0,0 +1,198 @@
+miscmodel($base);
+ }
+
+ function miscmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function get_apps($col = '*', $where = '')
+ {
+ $arr = $this->db->fetch_all("SELECT $col FROM " . UC_DBTABLEPRE . "applications" . ($where ? ' WHERE ' . $where : ''));
+ return $arr;
+ }
+
+ function delete_apps($appids)
+ {
+
+ }
+
+ function update_app($appid, $name, $url, $authkey, $charset, $dbcharset)
+ {
+
+ }
+
+ function alter_app_table($appid, $operation = 'ADD')
+ {
+
+ }
+
+ function get_host_by_url($url)
+ {
+
+ }
+
+ function check_url($url)
+ {
+
+ }
+
+ function check_ip($url)
+ {
+
+ }
+
+ function test_api($url, $ip = '')
+ {
+
+ }
+
+ function dfopen2($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype = 'URLENCODE')
+ {
+ $__times__ = isset($_GET['__times__']) ? intval($_GET['__times__']) + 1 : 1;
+ if ($__times__ > 2)
+ {
+ return '';
+ }
+ $url .= (strpos($url, '?') === FALSE ? '?' : '&') . "__times__=$__times__";
+ return $this->dfopen($url, $limit, $post, $cookie, $bysocket, $ip, $timeout, $block, $encodetype);
+ }
+
+ function dfopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype = 'URLENCODE')
+ {
+ $return = '';
+ $matches = parse_url($url);
+ $scheme = $matches['scheme'];
+ $host = $matches['host'];
+ $path = $matches['path'] ? $matches['path'] . ($matches['query'] ? '?' . $matches['query'] : '') : '/';
+ $port = !empty($matches['port']) ? $matches['port'] : 80;
+
+ if ($post)
+ {
+ $out = "POST $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $boundary = $encodetype == 'URLENCODE' ? '' : ';' . substr($post, 0, trim(strpos($post, "\n")));
+ $header .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n";
+ $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
+ $header .= "Host: $host:$port\r\n";
+ $header .= 'Content-Length: ' . strlen($post) . "\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cache-Control: no-cache\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header . $post;
+ }
+ else
+ {
+ $out = "GET $path HTTP/1.0\r\n";
+ $header = "Accept: */*\r\n";
+ $header .= "Accept-Language: zh-cn\r\n";
+ $header .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
+ $header .= "Host: $host:$port\r\n";
+ $header .= "Connection: Close\r\n";
+ $header .= "Cookie: $cookie\r\n\r\n";
+ $out .= $header;
+ }
+
+ $fpflag = 0;
+ if (!$fp = @fsocketopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout))
+ {
+ $context = array(
+ 'http' => array(
+ 'method' => $post ? 'POST' : 'GET',
+ 'header' => $header,
+ 'content' => $post,
+ 'timeout' => $timeout,
+ ),
+ );
+ $context = stream_context_create($context);
+ $fp = @fopen($scheme . '://' . ($ip ? $ip : $host) . ':' . $port . $path, 'b', false, $context);
+ $fpflag = 1;
+ }
+
+ if (!$fp)
+ {
+ return '';
+ }
+ else
+ {
+ stream_set_blocking($fp, $block);
+ stream_set_timeout($fp, $timeout);
+ @fwrite($fp, $out);
+ $status = stream_get_meta_data($fp);
+ if (!$status['timed_out'])
+ {
+ while (!feof($fp) && !$fpflag)
+ {
+ if (($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n"))
+ {
+ break;
+ }
+ }
+
+ $stop = false;
+ while (!feof($fp) && !$stop)
+ {
+ $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
+ $return .= $data;
+ if ($limit)
+ {
+ $limit -= strlen($data);
+ $stop = $limit <= 0;
+ }
+ }
+ }
+ @fclose($fp);
+ return $return;
+ }
+ }
+
+ function array2string($arr)
+ {
+ $s = $sep = '';
+ if ($arr && is_array($arr))
+ {
+ foreach ($arr as $k => $v)
+ {
+ $s .= $sep . addslashes($k) . UC_ARRAY_SEP_1 . $v;
+ $sep = UC_ARRAY_SEP_2;
+ }
+ }
+ return $s;
+ }
+
+ function string2array($s)
+ {
+ $arr = explode(UC_ARRAY_SEP_2, $s);
+ $arr2 = array();
+ foreach ($arr as $k => $v)
+ {
+ list($key, $val) = explode(UC_ARRAY_SEP_1, $v);
+ $arr2[$key] = $val;
+ }
+ return $arr2;
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/note.php b/extend/fast/ucenter/client/uc_client/model/note.php
new file mode 100644
index 00000000..0ca5141e
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/note.php
@@ -0,0 +1,230 @@
+notemodel($base);
+ }
+
+ function notemodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ $this->apps = $this->base->cache('apps');
+ $this->operations = array(
+ 'test' => array('', 'action=test'),
+ 'deleteuser' => array('', 'action=deleteuser'),
+ 'deletefriend' => array('', 'action=deletefriend'),
+ 'gettag' => array('', 'action=gettag', 'tag', 'updatedata'),
+ 'getcreditsettings' => array('', 'action=getcreditsettings'),
+ 'getcredit' => array('', 'action=getcredit'),
+ 'updatecreditsettings' => array('', 'action=updatecreditsettings'),
+ 'updateclient' => array('', 'action=updateclient'),
+ 'updatepw' => array('', 'action=updatepw'),
+ 'updateinfo' => array('', 'action=updateinfo'),
+ 'updatebadwords' => array('', 'action=updatebadwords'),
+ 'updatehosts' => array('', 'action=updatehosts'),
+ 'updateapps' => array('', 'action=updateapps'),
+ 'updatecredit' => array('', 'action=updatecredit'),
+ );
+ }
+
+ function get_total_num($all = TRUE)
+ {
+
+ }
+
+ function get_list($page, $ppp, $totalnum, $all = TRUE)
+ {
+
+ }
+
+ function delete_note($ids)
+ {
+
+ }
+
+ function add($operation, $getdata = '', $postdata = '', $appids = array(), $pri = 0)
+ {
+ $extra = $varextra = '';
+ $appadd = $varadd = array();
+ foreach ((array) $this->apps as $appid => $app)
+ {
+ $appid = $app['appid'];
+ if ($appid == intval($appid))
+ {
+ if ($appids && !in_array($appid, $appids))
+ {
+ $appadd[] = 'app' . $appid . "='1'";
+ }
+ else
+ {
+ $varadd[] = "('noteexists{$appid}', '1')";
+ }
+ }
+ }
+ if ($appadd)
+ {
+ $extra = implode(',', $appadd);
+ $extra = $extra ? ', ' . $extra : '';
+ }
+ if ($varadd)
+ {
+ $varextra = implode(', ', $varadd);
+ $varextra = $varextra ? ', ' . $varextra : '';
+ }
+
+ $getdata = addslashes($getdata);
+ $postdata = addslashes($postdata);
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "notelist SET getdata='$getdata', operation='$operation', pri='$pri', postdata='$postdata'$extra");
+ $insert_id = $this->db->insert_id();
+ $insert_id && $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars (name, value) VALUES ('noteexists', '1')$varextra");
+ $this->noteid = $insert_id;
+ return $insert_id;
+ }
+
+ function send()
+ {
+ register_shutdown_function(array($this, '_send'));
+ }
+
+ function _send()
+ {
+ $note = $this->_get_note();
+ if (empty($note))
+ {
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "vars SET name='noteexists" . UC_APPID . "', value='0'");
+ return NULL;
+ }
+ $this->sendone(UC_APPID, 0, $note);
+ $this->_gc();
+ }
+
+ function sendone($appid, $noteid = 0, $note = '')
+ {
+ require_once UC_ROOT . './lib/xml.class.php';
+ $return = FALSE;
+ $app = $this->apps[$appid];
+ if ($noteid)
+ {
+ $note = $this->_get_note_by_id($noteid);
+ }
+ $this->base->load('misc');
+ $apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php';
+ if ($app['extra']['apppath'] && @include $app['extra']['apppath'] . './api/' . $apifilename)
+ {
+ $uc_note = new uc_note();
+ $method = $note['operation'];
+ if (is_string($method) && !empty($method))
+ {
+ parse_str($note['getdata'], $note['getdata']);
+ if (get_magic_quotes_gpc())
+ {
+ $note['getdata'] = $this->base->dstripslashes($note['getdata']);
+ }
+ $note['postdata'] = @xml_unserialize($note['postdata']);
+ $response = $uc_note->$method($note['getdata'], $note['postdata']);
+ }
+ unset($uc_note);
+ }
+ else
+ {
+ $url = $this->get_url_code($note['operation'], $note['getdata'], $appid);
+ $note['postdata'] = str_replace(array("\n", "\r"), '', $note['postdata']);
+ $response = trim($_ENV['misc']->dfopen2($url, 0, $note['postdata'], '', 1, $app['ip'], UC_NOTE_TIMEOUT, TRUE));
+ }
+
+ $returnsucceed = $response != '' && ($response == 1 || is_array(@xml_unserialize($response)));
+
+ $closedsqladd = $this->_close_note($note, $this->apps, $returnsucceed, $appid) ? ",closed='1'" : '';
+
+ if ($returnsucceed)
+ {
+ if ($this->operations[$note['operation']][2])
+ {
+ $this->base->load($this->operations[$note['operation']][2]);
+ $func = $this->operations[$note['operation']][3];
+ $_ENV[$this->operations[$note['operation']][2]]->$func($appid, $response);
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "notelist SET app$appid='1', totalnum=totalnum+1, succeednum=succeednum+1, dateline='{$this->base->time}' $closedsqladd WHERE noteid='$note[noteid]'", 'SILENT');
+ $return = TRUE;
+ }
+ else
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "notelist SET app$appid = app$appid-'1', totalnum=totalnum+1, dateline='{$this->base->time}' $closedsqladd WHERE noteid='$note[noteid]'", 'SILENT');
+ $return = FALSE;
+ }
+ return $return;
+ }
+
+ function _get_note()
+ {
+ $app_field = 'app' . UC_APPID;
+ $data = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "notelist WHERE closed='0' AND $app_field<'1' AND $app_field>'-" . UC_NOTE_REPEAT . "' LIMIT 1");
+ return $data;
+ }
+
+ function _gc()
+ {
+ rand(0, UC_NOTE_GC) == 0 && $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "notelist WHERE closed='1'");
+ }
+
+ function _close_note($note, $apps, $returnsucceed, $appid)
+ {
+ $note['app' . $appid] = $returnsucceed ? 1 : $note['app' . $appid] - 1;
+ $appcount = count($apps);
+ foreach ($apps as $key => $app)
+ {
+ $appstatus = $note['app' . $app['appid']];
+ if (!$app['recvnote'] || $appstatus == 1 || $appstatus <= -UC_NOTE_REPEAT)
+ {
+ $appcount--;
+ }
+ }
+ if ($appcount < 1)
+ {
+ return TRUE;
+ }
+ }
+
+ function _get_note_by_id($noteid)
+ {
+ $data = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "notelist WHERE noteid='$noteid'");
+ return $data;
+ }
+
+ function get_url_code($operation, $getdata, $appid)
+ {
+ $app = $this->apps[$appid];
+ $authkey = UC_KEY;
+ $url = $app['url'];
+ $apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php';
+ $action = $this->operations[$operation][1];
+ $code = urlencode($this->base->authcode("$action&" . ($getdata ? "$getdata&" : '') . "time=" . $this->base->time, 'ENCODE', $authkey));
+ return $url . "/api/$apifilename?code=$code";
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/pm.php b/extend/fast/ucenter/client/uc_client/model/pm.php
new file mode 100644
index 00000000..672ec0f8
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/pm.php
@@ -0,0 +1,1261 @@
+pmmodel($base);
+ }
+
+ function pmmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function pmintval($pmid)
+ {
+ return @is_numeric($pmid) ? $pmid : 0;
+ }
+
+ function getpmbypmid($uid, $pmid)
+ {
+ if (!$pmid)
+ {
+ return array();
+ }
+ $arr = array();
+ $pm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_indexes i LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=i.plid WHERE i.pmid='$pmid'");
+ if ($this->isprivilege($pm['plid'], $uid))
+ {
+ $pms = $this->db->fetch_all("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($pm['plid']) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=p.plid WHERE p.pmid='$pm[pmid]'");
+ $arr = $this->getpostlist($pms);
+ }
+ return $arr;
+ }
+
+ function isprivilege($plid, $uid)
+ {
+ if (!$plid || !$uid)
+ {
+ return true;
+ }
+ $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$uid'");
+ if ($this->db->fetch_array($query))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ function getpmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp, $type = 0)
+ {
+ if (!$type)
+ {
+ $pm = $this->getprivatepmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp);
+ }
+ else
+ {
+ $pm = $this->getchatpmbyplid($uid, $plid, $starttime, $endtime, $start, $ppp);
+ }
+ return $this->getpostlist($pm);
+ }
+
+ function getpostlist($list)
+ {
+ if (empty($list))
+ {
+ return array();
+ }
+ $authoridarr = $authorarr = array();
+ foreach ($list as $key => $value)
+ {
+ $authoridarr[$value['authorid']] = $value['authorid'];
+ }
+ if ($authoridarr)
+ {
+ $this->base->load('user');
+ $authorarr = $_ENV['user']->id2name($authoridarr);
+ }
+ foreach ($list as $key => $value)
+ {
+ if ($value['pmtype'] == 1)
+ {
+ $users = explode('_', $value['min_max']);
+ if ($value['authorid'] == $users[0])
+ {
+ $value['touid'] = $users[1];
+ }
+ else
+ {
+ $value['touid'] = $users[0];
+ }
+ }
+ else
+ {
+ $value['touid'] = 0;
+ }
+ $value['author'] = $authorarr[$value['authorid']];
+
+ $value['msgfromid'] = $value['authorid'];
+ $value['msgfrom'] = $value['author'];
+ $value['msgtoid'] = $value['touid'];
+
+ unset($value['min_max']);
+ unset($value['delstatus']);
+ unset($value['lastmessage']);
+ $list[$key] = $value;
+ }
+ return $list;
+ }
+
+ function setpmstatus($uid, $touids, $plids, $status = 0)
+ {
+ if (!$uid)
+ {
+ return false;
+ }
+ if (!$status)
+ {
+ $oldstatus = 1;
+ $newstatus = 0;
+ }
+ else
+ {
+ $oldstatus = 0;
+ $newstatus = 1;
+ }
+ if ($touids)
+ {
+ foreach ($touids as $key => $value)
+ {
+ if ($uid == $value || !$value)
+ {
+ return false;
+ }
+ $relastionship[] = $this->relationship($uid, $value);
+ }
+ $plid = $plidpostarr = array();
+ $query = $this->db->query("SELECT plid FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max IN (" . $this->base->implode($relationship) . ")");
+ while ($thread = $this->db->fetch_array($query))
+ {
+ $plidarr[] = $thread['plid'];
+ }
+ if ($plidarr)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew='$newstatus' WHERE plid IN (" . $this->base->implode($plidarr) . ") AND uid='$uid' AND isnew='$oldstatus'");
+ }
+ }
+ if ($plids)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew='$newstatus' WHERE plid IN (" . $this->base->implode($plids) . ") AND uid='$uid' AND isnew='$oldstatus'");
+ }
+ return true;
+ }
+
+ function set_ignore($uid)
+ {
+ return $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'");
+ }
+
+ function isnewpm($uid)
+ {
+ return $this->db->result_first("SELECT uid FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'");
+ }
+
+ function lastpm($uid)
+ {
+ $lastpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE m.uid='$uid' ORDER BY m.lastdateline DESC LIMIT 1");
+ $lastmessage = unserialize($lastpm['lastmessage']);
+ if ($lastmessage['lastauthorid'])
+ {
+ $lastpm['lastauthorid'] = $lastmessage['lastauthorid'];
+ $lastpm['lastauthor'] = $lastmessage['lastauthor'];
+ $lastpm['lastsummary'] = $lastmessage['lastsummary'];
+ }
+ else
+ {
+ $lastpm['lastauthorid'] = $lastmessage['firstauthorid'];
+ $lastpm['lastauthor'] = $lastmessage['firstauthor'];
+ $lastpm['lastsummary'] = $lastmessage['firstsummary'];
+ }
+ return $lastpm;
+ }
+
+ function getpmnum($uid, $type = 0, $isnew = 0)
+ {
+ $newsql = '';
+ $newnum = 0;
+
+ if ($isnew)
+ {
+ $newsql = 'AND m.isnew=1';
+ }
+ if (!$type)
+ {
+ $newnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m WHERE m.uid='$uid' $newsql");
+ }
+ else
+ {
+ $newnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=m.plid WHERE m.uid='$uid' $newsql AND t.pmtype='$type'");
+ }
+ return $newnum;
+ }
+
+ function getpmnumbyplid($uid, $plid)
+ {
+ return $this->db->result_first("SELECT pmnum FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$uid'");
+ }
+
+ function sendpm($fromuid, $fromusername, $touids, $subject, $message, $type = 0)
+ {
+ if (!$fromuid || !$fromusername || !$touids || !$message)
+ {
+ return 0;
+ }
+ $touids = array_unique($touids);
+ $relationship = $existplid = $pm_member_insertsql = array();
+ $this->base->load('user');
+ $tmptouidarr = $touids;
+ $blackls = $this->get_blackls($fromuid, $touids);
+
+ foreach ($tmptouidarr as $key => $value)
+ {
+ if ($fromuid == $value || !$value)
+ {
+ return PMSENDSELF_ERROR;
+ }
+
+ if (in_array('{ALL}', $blackls[$value]))
+ {
+ unset($touids[$key]);
+ continue;
+ }
+ $blackls[$value] = $_ENV['user']->name2id($blackls[$value]);
+ if (!(isset($blackls[$value]) && !in_array($fromuid, $blackls[$value])))
+ {
+ unset($touids[$key]);
+ }
+ else
+ {
+ $relationship[$value] = $this->relationship($fromuid, $value);
+ }
+ }
+ if (empty($touids))
+ {
+ return PMSENDNONE_ERROR;
+ }
+ if ($type == 1 && count($touids) < 2)
+ {
+ return PMSENDCHATNUM_ERROR;
+ }
+
+ $_CACHE['badwords'] = $this->base->cache('badwords');
+ if ($_CACHE['badwords']['findpattern'])
+ {
+ $subject = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $subject);
+ $message = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $message);
+ }
+ if (!$subject)
+ {
+ $subject = $this->removecode(trim($message), 80);
+ }
+ else
+ {
+ $subject = dhtmlspecialchars($subject);
+ }
+ $lastsummary = $this->removecode(trim(stripslashes($message)), 150);
+
+ if (!$type)
+ {
+ $query = $this->db->query("SELECT plid, min_max FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max IN (" . $this->base->implode($relationship) . ")");
+ while ($thread = $this->db->fetch_array($query))
+ {
+ $existplid[$thread['min_max']] = $thread['plid'];
+ }
+ $lastmessage = array('lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary);
+ $lastmessage = addslashes(serialize($lastmessage));
+ foreach ($relationship as $key => $value)
+ {
+ if (!isset($existplid[$value]))
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_lists(authorid, pmtype, subject, members, min_max, dateline, lastmessage) VALUES('$fromuid', '1', '$subject', 2, '$value', '" . $this->base->time . "', '$lastmessage')");
+ $plid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')");
+ $pmid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)");
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$key', '1', '1', '0', '" . $this->base->time . "')");
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')");
+ }
+ else
+ {
+ $plid = $existplid[$value];
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')");
+ $pmid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)");
+ $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$key', '1', '1', '0', '" . $this->base->time . "')", 'SILENT');
+ if (!$result)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$key'");
+ }
+ $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')", 'SILENT');
+ if (!$result)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, pmnum=pmnum+1, lastupdate='" . $this->base->time . "', lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'");
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET lastmessage='$lastmessage' WHERE plid='$plid'");
+ }
+ }
+ }
+ else
+ {
+ $lastmessage = array('firstauthorid' => $fromuid, 'firstauthor' => $fromusername, 'firstsummary' => $lastsummary);
+ $lastmessage = addslashes(serialize($lastmessage));
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_lists(authorid, pmtype, subject, members, min_max, dateline, lastmessage) VALUES('$fromuid', '2', '$subject', '" . (count($touids) + 1) . "', '', '" . $this->base->time . "', '$lastmessage')");
+ $plid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')");
+ $pmid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)");
+ $pm_member_insertsql[] = "('$plid', '$fromuid', '0', '1', '" . $this->base->time . "', '" . $this->base->time . "')";
+ foreach ($touids as $key => $value)
+ {
+ $pm_member_insertsql[] = "('$plid', '$value', '1', '1', '0', '" . $this->base->time . "')";
+ }
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES " . implode(',', $pm_member_insertsql));
+ }
+
+ $newpm = array();
+ foreach ($touids as $key => $value)
+ {
+ $newpm[] = "('$value')";
+ }
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "newpm(uid) VALUES " . implode(',', $newpm));
+ return $pmid;
+ }
+
+ function replypm($plid, $fromuid, $fromusername, $message)
+ {
+ if (!$plid || !$fromuid || !$fromusername || !$message)
+ {
+ return 0;
+ }
+
+ $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'");
+ if (empty($threadpm))
+ {
+ return PMTHREADNONE_ERROR;
+ }
+
+ if ($threadpm['pmtype'] == 1)
+ {
+ $users = explode('_', $threadpm['min_max']);
+ if ($users[0] == $fromuid)
+ {
+ $touid = $users[1];
+ }
+ elseif ($users[1] == $fromuid)
+ {
+ $touid = $users[0];
+ }
+ else
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+
+ $blackls = $this->get_blackls($fromuid, $touid);
+ if (in_array('{ALL}', $blackls[$touid]))
+ {
+ return PMINBALCKLIST_ERROR;
+ }
+ $this->base->load('user');
+ $blackls[$touid] = $_ENV['user']->name2id($blackls[$touid]);
+ if (!(isset($blackls[$touid]) && !in_array($fromuid, $blackls[$touid])))
+ {
+ return PMINBALCKLIST_ERROR;
+ }
+ }
+
+ $memberuid = array();
+ $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'");
+ while ($member = $this->db->fetch_array($query))
+ {
+ $memberuid[$member['uid']] = "('$member[uid]')";
+ }
+ if (!isset($memberuid[$fromuid]))
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+
+ $_CACHE['badwords'] = $this->base->cache('badwords');
+ if ($_CACHE['badwords']['findpattern'])
+ {
+ $message = @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $message);
+ }
+ $lastsummary = $this->removecode(trim(stripslashes($message)), 150);
+
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_indexes(plid) VALUES('$plid')");
+ $pmid = $this->db->insert_id();
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . $this->getposttablename($plid) . "(pmid, plid, authorid, message, dateline, delstatus) VALUES('$pmid', '$plid', '$fromuid', '$message', '" . $this->base->time . "', 0)");
+ if ($threadpm['pmtype'] == 1)
+ {
+ $lastmessage = array('lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary);
+ $lastmessage = addslashes(serialize($lastmessage));
+ $result = $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$touid', '1', '1', '0', '" . $this->base->time . "')", 'SILENT');
+ if (!$result)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$touid'");
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, pmnum=pmnum+1, lastupdate='" . $this->base->time . "', lastdateline='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'");
+ }
+ else
+ {
+ $lastmessage = unserialize($threadpm['lastmessage']);
+ $lastmessage = array('firstauthorid' => $lastmessage['firstauthorid'], 'firstauthor' => $lastmessage['firstauthor'], 'firstsummary' => $lastmessage['firstsummary'], 'lastauthorid' => $fromuid, 'lastauthor' => $fromusername, 'lastsummary' => $lastsummary);
+ $lastmessage = addslashes(serialize($lastmessage));
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=1, pmnum=pmnum+1, lastdateline='" . $this->base->time . "' WHERE plid='$plid'");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0, lastupdate='" . $this->base->time . "' WHERE plid='$plid' AND uid='$fromuid'");
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET lastmessage='$lastmessage' WHERE plid='$plid'");
+
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "newpm(uid) VALUES " . implode(',', $memberuid) . "");
+
+ return $pmid;
+ }
+
+ function appendchatpm($plid, $uid, $touid)
+ {
+ if (!$plid || !$uid || !$touid)
+ {
+ return 0;
+ }
+ $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'");
+ if (empty($threadpm))
+ {
+ return PMTHREADNONE_ERROR;
+ }
+ if ($threadpm['pmtype'] != 2)
+ {
+ return PMCHATTYPE_ERROR;
+ }
+ if ($threadpm['authorid'] != $uid)
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+
+ $blackls = $this->get_blackls($uid, $touid);
+ if (in_array('{ALL}', $blackls[$touid]))
+ {
+ return PMINBALCKLIST_ERROR;
+ }
+ $this->base->load('user');
+ $blackls[$touid] = $_ENV['user']->name2id($blackls[$touid]);
+ if (!(isset($blackls[$touid]) && !in_array($uid, $blackls[$touid])))
+ {
+ return PMINBALCKLIST_ERROR;
+ }
+
+ $pmnum = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " WHERE plid='$plid'");
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "pm_members(plid, uid, isnew, pmnum, lastupdate, lastdateline) VALUES('$plid', '$touid', '1', '$pmnum', '0', '0')", 'SILENT');
+ $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members='$num' WHERE plid='$plid'");
+
+ return 1;
+ }
+
+ function kickchatpm($plid, $uid, $touid)
+ {
+ if (!$uid || !$touid || !$plid || $uid == $touid)
+ {
+ return 0;
+ }
+ $threadpm = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'");
+ if ($threadpm['pmtype'] != 2)
+ {
+ return PMCHATTYPE_ERROR;
+ }
+ if ($threadpm['authorid'] != $uid)
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid' AND uid='$touid'");
+ $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members='$num' WHERE plid='$plid'");
+ return 1;
+ }
+
+ function quitchatpm($uid, $plids)
+ {
+ if (!$uid || !$plids)
+ {
+ return 0;
+ }
+ $list = array();
+ $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE m.plid IN (" . $this->base->implode($plids) . ") AND m.uid='$uid'");
+ while ($threadpm = $this->db->fetch_array($query))
+ {
+ if ($threadpm['pmtype'] != 2)
+ {
+ return PMCHATTYPE_ERROR;
+ }
+ if ($threadpm['authorid'] == $uid)
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ $list[] = $threadpm['plid'];
+ }
+
+ if ($list)
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid IN (" . $this->base->implode($list) . ") AND uid='$uid'");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_lists SET members=members-1 WHERE plid IN (" . $this->base->implode($list) . ")");
+ }
+
+ return 1;
+ }
+
+ function deletepmbypmid($uid, $pmid)
+ {
+ if (!$uid || !$pmid)
+ {
+ return 0;
+ }
+ $index = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_indexes i LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON i.plid=t.plid WHERE i.pmid='$pmid'");
+ if ($index['pmtype'] != 1)
+ {
+ return PMUIDTYPE_ERROR;
+ }
+ $users = explode('_', $index['min_max']);
+ if (!in_array($uid, $users))
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ if ($index['authorid'] != $uid)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " SET delstatus=2 WHERE pmid='$pmid' AND delstatus=0");
+ $updatenum = $this->db->affected_rows();
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE pmid='$pmid' AND delstatus=1");
+ $deletenum = $this->db->affected_rows();
+ }
+ else
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " SET delstatus=1 WHERE pmid='$pmid' AND delstatus=0");
+ $updatenum = $this->db->affected_rows();
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE pmid='$pmid' AND delstatus=2");
+ $deletenum = $this->db->affected_rows();
+ }
+
+ if (!$this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($index['plid']) . " WHERE plid='$index[plid]'"))
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$index[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$index[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$index[plid]'");
+ }
+ else
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET pmnum=pmnum-" . ($updatenum + $deletenum) . " WHERE plid='" . $index['plid'] . "' AND uid='$uid'");
+ }
+ return 1;
+ }
+
+ function deletepmbypmids($uid, $pmids)
+ {
+ if ($pmids)
+ {
+ foreach ($pmids as $key => $pmid)
+ {
+ $this->deletepmbypmid($uid, $pmid);
+ }
+ }
+ return 1;
+ }
+
+ /*
+ function deletepmbypmids($uid, $pmids) {
+ if(!$uid || !$pmids) {
+ return 0;
+ }
+ $pmplid = $delstatus1pm = $delstatus2pm = $pmplidpost = array();
+ $existplid = array();
+ $query = $this->db->query("SELECT * FROM ".UC_DBTABLEPRE."pm_indexes i LEFT JOIN ".UC_DBTABLEPRE."pm_lists t ON i.plid=t.plid WHERE i.pmid IN (".$this->base->implode($pmids).") AND t.pmtype=1");
+ while($index = $this->db->fetch_array($query)) {
+ $users = explode('_', $index['min_max']);
+ if(!in_array($uid, $users)) {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ if($index['authorid'] == $uid) {
+ $delstatus1pm[$this->getposttablename($index['plid'])][] = $index['pmid'];
+ } else {
+ $delstatus2pm[$this->getposttablename($index['plid'])][] = $index['pmid'];
+ }
+ $pmplidpost[$this->getposttablename($index['plid'])][] = $index['plid'];
+ $pmplid[$index['plid']] = $index['plid'];
+ }
+ if(empty($pmplidpost)) {
+ return 0;
+ }
+
+ if($delstatus1pm) {
+ foreach($delstatus1pm as $key => $value) {
+ $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=1 WHERE pmid IN (".$this->base->implode($value).") AND delstatus=0");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE pmid IN (".$this->base->implode($value).") AND delstatus=2");
+ }
+ }
+
+ if($delstatus2pm) {
+ foreach($delstatus2pm as $key => $value) {
+ $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=2 WHERE pmid IN (".$this->base->implode($value).") AND delstatus=0");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE pmid IN (".$this->base->implode($value).") AND delstatus=1");
+ }
+ }
+
+ foreach($pmplidpost as $key => $value) {
+ $query = $this->db->query("SELECT DISTINCT plid FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")");
+ while($pmpostarr = $this->db->fetch_array($query)) {
+ $existplid[] = $pmpostarr['plid'];
+ }
+ }
+ $pmplid = array_diff($pmplid, $existplid);
+ if($pmplid) {
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($pmplid).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($pmplid).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($pmplid).")");
+ }
+ return 1;
+ }
+ */
+
+ function deletepmbyplid($uid, $plid, $isuser = 0)
+ {
+ if (!$uid || !$plid)
+ {
+ return 0;
+ }
+
+ if ($isuser)
+ {
+ $relationship = $this->relationship($uid, $plid);
+ $sql = "SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max='$relationship'";
+ }
+ else
+ {
+ $sql = "SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'";
+ }
+
+ $query = $this->db->query($sql);
+ if ($list = $this->db->fetch_array($query))
+ {
+ if ($list['pmtype'] == 1)
+ {
+ $user = explode('_', $list['min_max']);
+ if (!in_array($uid, $user))
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ }
+ else
+ {
+ if ($uid != $list['authorid'])
+ {
+ return PMPRIVILEGENONE_ERROR;
+ }
+ }
+ }
+ else
+ {
+ return PMTHREADNONE_ERROR;
+ }
+
+ if ($list['pmtype'] == 1)
+ {
+ if ($uid == $list['authorid'])
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]' AND delstatus=2");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " SET delstatus=1 WHERE plid='$list[plid]' AND delstatus=0");
+ }
+ else
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]' AND delstatus=1");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " SET delstatus=2 WHERE plid='$list[plid]' AND delstatus=0");
+ }
+ $count = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]'");
+ if (!$count)
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$list[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$list[plid]'");
+ }
+ else
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]' AND uid='$uid'");
+ }
+ }
+ else
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . $this->getposttablename($list['plid']) . " WHERE plid='$list[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$list[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$list[plid]'");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "pm_indexes WHERE plid='$list[plid]'");
+ }
+ return 1;
+ }
+
+ function deletepmbyplids($uid, $plids, $isuser = 0)
+ {
+ if ($plids)
+ {
+ foreach ($plids as $key => $plid)
+ {
+ $this->deletepmbyplid($uid, $plid, $isuser);
+ }
+ }
+ return 1;
+ }
+
+ /*
+ function deletepmbyplid($uid, $plids, $isuser = 0) {
+ if(!$uid || !$plids) {
+ return 0;
+ }
+
+ $privatepm = $chatpm = array();
+ $privatepmauthorpost = $privatepmpost = $privatepmpostall = array();
+ $existplid = array();
+ if($isuser) {
+ $relationship = array();
+ foreach($plids as $key => $value) {
+ if($uid == $value || !$value) {
+ return PMDATA_ERROR;
+ }
+ $relationship[] = $this->relationship($uid, $value);
+ }
+ $sql = "SELECT * FROM ".UC_DBTABLEPRE."pm_lists WHERE min_max IN (".$this->base->implode($relationship).")";
+ } else {
+ $sql = "SELECT * FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($plids).")";
+ }
+ $query = $this->db->query($sql);
+ while($threadpm = $this->db->fetch_array($query)) {
+ if($threadpm['pmtype'] == 1) {
+ $users = explode('_', $threadpm['min_max']);
+ if($users[0] == $uid) {
+ $touid = $users[1];
+ } elseif($users[1] == $uid) {
+ $touid = $users[0];
+ } else {
+ continue;
+ }
+
+ if($threadpm['authorid'] == $uid) {
+ $privatepmauthorpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid'];
+ } else {
+ $privatepmpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid'];
+ }
+ $privatepmpostall[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid'];
+ $privatepm[] = $threadpm['plid'];
+ } else {
+ if($uid != $threadpm['authorid']) {
+ continue;
+ }
+ $chatpm[] = $threadpm['plid'];
+ $chatpmpost[$this->getposttablename($threadpm['plid'])][] = $threadpm['plid'];
+ }
+ }
+
+ if($privatepmauthorpost) {
+ foreach($privatepmauthorpost as $key => $value) {
+ $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=1 WHERE plid IN (".$this->base->implode($value).") AND delstatus=0");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).") AND delstatus=2");
+ }
+ }
+
+ if($privatepmpost) {
+ foreach($privatepmpost as $key => $value) {
+ $this->db->query("UPDATE ".UC_DBTABLEPRE."$key SET delstatus=2 WHERE plid IN (".$this->base->implode($value).") AND delstatus=0");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).") AND delstatus=1");
+ }
+ }
+ if($privatepmpostall) {
+ foreach($privatepmpostall as $key => $value) {
+ $query = $this->db->query("SELECT DISTINCT plid FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")");
+ while($postpm = $this->db->fetch_array($query)) {
+ $existplid[] = $postpm['plid'];
+ }
+ }
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($privatepm).") AND uid='$uid'");
+ $privatepm = array_diff($privatepm, $existplid);
+ if(!empty($privatepm)) {
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($privatepm).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($privatepm).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($privatepm).")");
+ }
+ }
+ if($chatpmpost) {
+ foreach($chatpmpost as $key => $value) {
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."$key WHERE plid IN (".$this->base->implode($value).")");
+ }
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_lists WHERE plid IN (".$this->base->implode($chatpm).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_members WHERE plid IN (".$this->base->implode($chatpm).")");
+ $this->db->query("DELETE FROM ".UC_DBTABLEPRE."pm_indexes WHERE plid IN (".$this->base->implode($chatpm).")");
+ }
+ return 1;
+ }
+ */
+
+ function getprivatepmbyplid($uid, $plid, $starttime = 0, $endtime = 0, $start = 0, $ppp = 0)
+ {
+ if (!$uid || !$plid)
+ {
+ return 0;
+ }
+ if (!$this->isprivilege($plid, $uid))
+ {
+ return 0;
+ }
+ $thread = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'");
+ if ($thread['pmtype'] != 1)
+ {
+ return 0;
+ }
+ $pms = $addsql = array();
+ $addsql[] = "p.plid='$plid'";
+ if ($thread['authorid'] == $uid)
+ {
+ $addsql[] = 'p.delstatus IN (0,2)';
+ }
+ else
+ {
+ $addsql[] = 'p.delstatus IN (0,1)';
+ }
+ if ($starttime)
+ {
+ $addsql[] = "p.dateline>'$starttime'";
+ }
+ if ($endtime)
+ {
+ $addsql[] = "p.dateline<'$endtime'";
+ }
+ if ($addsql)
+ {
+ $addsql = implode(' AND ', $addsql);
+ }
+ else
+ {
+ $addsql = '';
+ }
+ if ($ppp)
+ {
+ $limitsql = 'LIMIT ' . intval($start) . ', ' . intval($ppp);
+ }
+ else
+ {
+ $limitsql = '';
+ }
+ $pms = $this->db->fetch_all("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON p.plid=t.plid WHERE $addsql ORDER BY p.dateline DESC $limitsql");
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0 WHERE plid='$plid' AND uid='$uid' AND isnew=1");
+ return array_reverse($pms);
+ }
+
+ function getchatpmbyplid($uid, $plid, $starttime = 0, $endtime = 0, $start = 0, $ppp = 0)
+ {
+ if (!$uid || !$plid)
+ {
+ return 0;
+ }
+ if (!$this->isprivilege($plid, $uid))
+ {
+ return 0;
+ }
+ $pms = $addsql = array();
+ $addsql[] = "p.plid='$plid'";
+ if ($starttime)
+ {
+ $addsql[] = "p.dateline>'$starttime'";
+ }
+ if ($endtime)
+ {
+ $addsql[] = "p.dateline<'$endtime'";
+ }
+ if ($addsql)
+ {
+ $addsql = implode(' AND ', $addsql);
+ }
+ else
+ {
+ $addsql = '';
+ }
+ if ($ppp)
+ {
+ $limitsql = 'LIMIT ' . intval($start) . ', ' . intval($ppp);
+ }
+ else
+ {
+ $limitsql = '';
+ }
+ $query = $this->db->query("SELECT t.*, p.*, t.authorid as founderuid, t.dateline as founddateline FROM " . UC_DBTABLEPRE . $this->getposttablename($plid) . " p LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON p.plid=t.plid WHERE $addsql ORDER BY p.dateline DESC $limitsql");
+ while ($pm = $this->db->fetch_array($query))
+ {
+ if ($pm['pmtype'] != 2)
+ {
+ return 0;
+ }
+ $pms[] = $pm;
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "pm_members SET isnew=0 WHERE plid='$plid' AND uid='$uid' AND isnew=1");
+ return array_reverse($pms);
+ }
+
+ function getpmlist($uid, $filter, $start, $ppp = 10)
+ {
+ if (!$uid)
+ {
+ return 0;
+ }
+ $members = $touidarr = $tousernamearr = array();
+
+ if ($filter == 'newpm')
+ {
+ $addsql = 'm.isnew=1 AND ';
+ }
+ else
+ {
+ $addsql = '';
+ }
+ $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON t.plid=m.plid WHERE $addsql m.uid='$uid' ORDER BY m.lastdateline DESC LIMIT $start, $ppp");
+ while ($member = $this->db->fetch_array($query))
+ {
+ if ($member['pmtype'] == 1)
+ {
+ $users = explode('_', $member['min_max']);
+ $member['touid'] = $users[0] == $uid ? $users[1] : $users[0];
+ }
+ else
+ {
+ $member['touid'] = 0;
+ }
+ $touidarr[$member['touid']] = $member['touid'];
+ $members[] = $member;
+ }
+
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "newpm WHERE uid='$uid'");
+
+ $array = array();
+ if ($members)
+ {
+ $today = $this->base->time - $this->base->time % 86400;
+ $this->base->load('user');
+ $tousernamearr = $_ENV['user']->id2name($touidarr);
+ foreach ($members as $key => $data)
+ {
+
+ $daterange = 5;
+ $data['founddateline'] = $data['dateline'];
+ $data['dateline'] = $data['lastdateline'];
+ $data['pmid'] = $data['plid'];
+ $lastmessage = unserialize($data['lastmessage']);
+ if ($lastmessage['firstauthorid'])
+ {
+ $data['firstauthorid'] = $lastmessage['firstauthorid'];
+ $data['firstauthor'] = $lastmessage['firstauthor'];
+ $data['firstsummary'] = $lastmessage['firstsummary'];
+ }
+ if ($lastmessage['lastauthorid'])
+ {
+ $data['lastauthorid'] = $lastmessage['lastauthorid'];
+ $data['lastauthor'] = $lastmessage['lastauthor'];
+ $data['lastsummary'] = $lastmessage['lastsummary'];
+ }
+ $data['msgfromid'] = $lastmessage['lastauthorid'];
+ $data['msgfrom'] = $lastmessage['lastauthor'];
+ $data['message'] = $lastmessage['lastsummary'];
+
+ $data['new'] = $data['isnew'];
+
+ $data['msgtoid'] = $data['touid'];
+ if ($data['lastdateline'] >= $today)
+ {
+ $daterange = 1;
+ }
+ elseif ($data['lastdateline'] >= $today - 86400)
+ {
+ $daterange = 2;
+ }
+ elseif ($data['lastdateline'] >= $today - 172800)
+ {
+ $daterange = 3;
+ }
+ elseif ($data['lastdateline'] >= $today - 604800)
+ {
+ $daterange = 4;
+ }
+ $data['daterange'] = $daterange;
+
+ $data['tousername'] = $tousernamearr[$data['touid']];
+ unset($data['min_max']);
+ $array[] = $data;
+ }
+ }
+ return $array;
+ }
+
+ function getplidbypmid($pmid)
+ {
+ if (!$pmid)
+ {
+ return false;
+ }
+ return $this->db->result_first("SELECT plid FROM " . UC_DBTABLEPRE . "pm_indexes WHERE pmid='$pmid'");
+ }
+
+ function getplidbytouid($uid, $touid)
+ {
+ if (!$uid || !$touid)
+ {
+ return 0;
+ }
+ return $this->db->result_first("SELECT plid FROM " . UC_DBTABLEPRE . "pm_lists WHERE min_max='" . $this->relationship($uid, $touid) . "'");
+ }
+
+ function getuidbyplid($plid)
+ {
+ if (!$plid)
+ {
+ return array();
+ }
+ $uidarr = array();
+ $query = $this->db->query("SELECT uid FROM " . UC_DBTABLEPRE . "pm_members WHERE plid='$plid'");
+ while ($uid = $this->db->fetch_array($query))
+ {
+ $uidarr[$uid['uid']] = $uid['uid'];
+ }
+ return $uidarr;
+ }
+
+ function chatpmmemberlist($uid, $plid)
+ {
+ if (!$uid || !$plid)
+ {
+ return 0;
+ }
+ $uidarr = $this->getuidbyplid($plid);
+ if (empty($uidarr))
+ {
+ return 0;
+ }
+ if (!isset($uidarr[$uid]))
+ {
+ return 0;
+ }
+ $authorid = $this->db->result_first("SELECT authorid FROM " . UC_DBTABLEPRE . "pm_lists WHERE plid='$plid'");
+ return array('author' => $authorid, 'member' => $uidarr);
+ }
+
+ function relationship($fromuid, $touid)
+ {
+ if ($fromuid < $touid)
+ {
+ return $fromuid . '_' . $touid;
+ }
+ elseif ($fromuid > $touid)
+ {
+ return $touid . '_' . $fromuid;
+ }
+ else
+ {
+ return '';
+ }
+ }
+
+ function getposttablename($plid)
+ {
+ $id = substr((string) $plid, -1, 1);
+ return 'pm_messages_' . intval($id);
+ }
+
+ function get_blackls($uid, $uids = array())
+ {
+ if (!$uids)
+ {
+ $blackls = $this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'");
+ }
+ else
+ {
+ $uids = $this->base->implode($uids);
+ $blackls = array();
+ $query = $this->db->query("SELECT uid, blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid IN ($uids)");
+ while ($data = $this->db->fetch_array($query))
+ {
+ $blackls[$data['uid']] = explode(',', $data['blacklist']);
+ }
+ }
+ return $blackls;
+ }
+
+ function set_blackls($uid, $blackls)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET blacklist='$blackls' WHERE uid='$uid'");
+ return $this->db->affected_rows();
+ }
+
+ function update_blackls($uid, $username, $action = 1)
+ {
+ $username = !is_array($username) ? array($username) : $username;
+ if ($action == 1)
+ {
+ if (!in_array('{ALL}', $username))
+ {
+ $usernames = $this->base->implode($username);
+ $query = $this->db->query("SELECT username FROM " . UC_DBTABLEPRE . "members WHERE username IN ($usernames)");
+ $usernames = array();
+ while ($data = $this->db->fetch_array($query))
+ {
+ $usernames[addslashes($data['username'])] = addslashes($data['username']);
+ }
+ if (!$usernames)
+ {
+ return 0;
+ }
+ $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'"));
+ if ($blackls)
+ {
+ $list = explode(',', $blackls);
+ foreach ($list as $k => $v)
+ {
+ if (in_array($v, $usernames))
+ {
+ unset($usernames[$v]);
+ }
+ }
+ }
+ if (!$usernames)
+ {
+ return 1;
+ }
+ $listnew = implode(',', $usernames);
+ $blackls .= $blackls !== '' ? ',' . $listnew : $listnew;
+ }
+ else
+ {
+ $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'"));
+ $blackls .= ',{ALL}';
+ }
+ }
+ else
+ {
+ $blackls = addslashes($this->db->result_first("SELECT blacklist FROM " . UC_DBTABLEPRE . "memberfields WHERE uid='$uid'"));
+ $list = $blackls = explode(',', $blackls);
+ foreach ($list as $k => $v)
+ {
+ if (in_array($v, $username))
+ {
+ unset($blackls[$k]);
+ }
+ }
+ $blackls = implode(',', $blackls);
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET blacklist='$blackls' WHERE uid='$uid'");
+ return 1;
+ }
+
+ function removecode($str, $length)
+ {
+ static $uccode = null;
+ if ($uccode === null)
+ {
+ require_once UC_ROOT . 'lib/uccode.class.php';
+ $uccode = new uccode();
+ }
+ $str = $uccode->complie($str);
+ return trim($this->base->cutstr(strip_tags($str), $length));
+ }
+
+ function ispminterval($uid, $interval = 0)
+ {
+ if (!$uid)
+ {
+ return 0;
+ }
+ $interval = intval($interval);
+ if (!$interval)
+ {
+ return 1;
+ }
+ $lastupdate = $this->db->result_first("SELECT lastupdate FROM " . UC_DBTABLEPRE . "pm_members WHERE uid='$uid' ORDER BY lastupdate DESC LIMIT 1");
+ if (($this->base->time - $lastupdate) > $interval)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ function isprivatepmthreadlimit($uid, $maxnum = 0)
+ {
+ if (!$uid)
+ {
+ return 0;
+ }
+ $maxnum = intval($maxnum);
+ if (!$maxnum)
+ {
+ return 1;
+ }
+ $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_members m LEFT JOIN " . UC_DBTABLEPRE . "pm_lists t ON m.plid=t.plid WHERE uid='$uid' AND lastupdate>'" . ($this->base->time - 86400) . "' AND t.pmtype=1");
+ if ($maxnum - $num < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ function ischatpmthreadlimit($uid, $maxnum = 0)
+ {
+ if (!$uid)
+ {
+ return 0;
+ }
+ $maxnum = intval($maxnum);
+ if (!$maxnum)
+ {
+ return 1;
+ }
+ $num = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "pm_lists WHERE authorid='$uid' AND dateline>'" . ($this->base->time - 86400) . "'");
+ if ($maxnum - $num < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/tag.php b/extend/fast/ucenter/client/uc_client/model/tag.php
new file mode 100644
index 00000000..4a8261f8
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/tag.php
@@ -0,0 +1,84 @@
+tagmodel($base);
+ }
+
+ function tagmodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function get_tag_by_name($tagname)
+ {
+ $arr = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$tagname'");
+ return $arr;
+ }
+
+ function get_template($appid)
+ {
+ $result = $this->db->result_first("SELECT tagtemplates FROM " . UC_DBTABLEPRE . "applications WHERE appid='$appid'");
+ return $result;
+ }
+
+ function updatedata($appid, $data)
+ {
+ $appid = intval($appid);
+ include_once UC_ROOT . 'lib/xml.class.php';
+ $data = @xml_unserialize($data);
+ $this->base->load('app');
+ $data[0] = addslashes($data[0]);
+ $datanew = array();
+ if (is_array($data[1]))
+ {
+ foreach ($data[1] as $r)
+ {
+ $datanew[] = $_ENV['misc']->array2string($r);
+ }
+ }
+ $tmp = $_ENV['app']->get_apps('type', "appid='$appid'");
+ $datanew = addslashes($tmp[0]['type'] . "\t" . implode("\t", $datanew));
+ if (!empty($data[0]))
+ {
+ $return = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$data[0]' AND appid='$appid'");
+ if ($return)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "tags SET data='$datanew', expiration='" . $this->base->time . "' WHERE tagname='$data[0]' AND appid='$appid'");
+ }
+ else
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "tags (tagname, appid, data, expiration) VALUES ('$data[0]', '$appid', '$datanew', '" . $this->base->time . "')");
+ }
+ }
+ }
+
+ function formatcache($appid, $tagname)
+ {
+ $return = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "tags WHERE tagname='$tagname' AND appid='$appid'");
+ if ($return)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "tags SET expiration='0' WHERE tagname='$tagname' AND appid='$appid'");
+ }
+ else
+ {
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "tags (tagname, appid, expiration) VALUES ('$tagname', '$appid', '0')");
+ }
+ }
+
+}
diff --git a/extend/fast/ucenter/client/uc_client/model/user.php b/extend/fast/ucenter/client/uc_client/model/user.php
new file mode 100644
index 00000000..07662270
--- /dev/null
+++ b/extend/fast/ucenter/client/uc_client/model/user.php
@@ -0,0 +1,439 @@
+usermodel($base);
+ }
+
+ function usermodel(&$base)
+ {
+ $this->base = $base;
+ $this->db = $base->db;
+ }
+
+ function get_user_by_uid($uid)
+ {
+ $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'");
+ return $arr;
+ }
+
+ function get_user_by_username($username)
+ {
+ $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE username='$username'");
+ return $arr;
+ }
+
+ function get_user_by_email($email)
+ {
+ $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE email='$email'");
+ return $arr;
+ }
+
+ function get_user_by_mobile($mobile)
+ {
+ $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile'");
+ return $arr;
+ }
+
+ function check_username($username)
+ {
+ $guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
+ $len = $this->dstrlen($username);
+ if ($len > 15 || $len < 3 || preg_match("/\s+|^c:\\con\\con|[%,\*\"\s\<\>\&]|$guestexp/is", $username))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ function dstrlen($str)
+ {
+ if (strtolower(UC_CHARSET) != 'utf-8')
+ {
+ return strlen($str);
+ }
+ $count = 0;
+ for ($i = 0; $i < strlen($str); $i++)
+ {
+ $value = ord($str[$i]);
+ if ($value > 127)
+ {
+ $count++;
+ if ($value >= 192 && $value <= 223)
+ $i++;
+ elseif ($value >= 224 && $value <= 239)
+ $i = $i + 2;
+ elseif ($value >= 240 && $value <= 247)
+ $i = $i + 3;
+ }
+ $count++;
+ }
+ return $count;
+ }
+
+ function check_mergeuser($username)
+ {
+ $data = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->base->app['appid'] . "' AND username='$username'");
+ return $data;
+ }
+
+ function check_usernamecensor($username)
+ {
+ $_CACHE['badwords'] = $this->base->cache('badwords');
+ $censorusername = $this->base->get_setting('censorusername');
+ $censorusername = $censorusername['censorusername'];
+ $censorexp = '/^(' . str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censorusername = trim($censorusername)), '/')) . ')$/i';
+ $usernamereplaced = isset($_CACHE['badwords']['findpattern']) && !empty($_CACHE['badwords']['findpattern']) ? @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username) : $username;
+ return !(($usernamereplaced != $username) || ($censorusername && preg_match($censorexp, $username)));
+ }
+
+ function check_usernameexists($username)
+ {
+ $data = $this->db->result_first("SELECT username FROM " . UC_DBTABLEPRE . "members WHERE username='$username'");
+ return $data;
+ }
+
+ function check_emailformat($email)
+ {
+ return strlen($email) > 6 && strlen($email) <= 32 && preg_match("/^([a-z0-9\-_.+]+)@([a-z0-9\-]+[.][a-z0-9\-.]+)$/", $email);
+ }
+
+ function check_emailaccess($email)
+ {
+ $setting = $this->base->get_setting(array('accessemail', 'censoremail'));
+ $accessemail = $setting['accessemail'];
+ $censoremail = $setting['censoremail'];
+ $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessemail), '/')) . ')$/i';
+ $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censoremail), '/')) . ')$/i';
+ if ($accessemail || $censoremail)
+ {
+ return !(($accessemail && !preg_match($accessexp, $email)) || ($censoremail && preg_match($censorexp, $email)));
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ function check_emailexists($email, $username = '')
+ {
+ $sqladd = $username !== '' ? "AND username<>'$username'" : '';
+ $email = $this->db->result_first("SELECT email FROM " . UC_DBTABLEPRE . "members WHERE email='$email' $sqladd");
+ return $email;
+ }
+
+ function check_mobileformat($mobile)
+ {
+ return strlen($mobile) >= 11 && preg_match("/^1[34578]\d{9}$/", $mobile);
+ }
+
+ function check_mobileaccess($mobile)
+ {
+ $setting = $this->base->get_setting(array('accessmobile', 'censormobile'));
+ $accessmobile = $setting['accessmobile'];
+ $censormobile = $setting['censormobile'];
+ $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessmobile), '/')) . ')$/i';
+ $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censormobile), '/')) . ')$/i';
+ if ($accessmobile || $censormobile)
+ {
+ return !(($accessmobile && !preg_match($accessexp, $mobile)) || ($censormobile && preg_match($censorexp, $mobile)));
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ function check_mobileexists($mobile, $username = '')
+ {
+ $sqladd = $username !== '' ? "AND username<>'$username'" : '';
+ $mobile = $this->db->result_first("SELECT mobile FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile' $sqladd");
+ return $mobile;
+ }
+
+ /**
+ * 检测是否登录
+ * @param string $username
+ * @param string $password
+ * @param array $user
+ * @return int
+ */
+ function check_login($username, $password, &$user)
+ {
+ $user = $this->get_user_by_username($username);
+ if (empty($user['username']))
+ {
+ return -1;
+ }
+ elseif ($user['password'] != md5(md5($password) . $user['salt']))
+ {
+ return -2;
+ }
+ return $user['uid'];
+ }
+
+ /**
+ * 在Ucenter中添加一个账号
+ * @param string $username
+ * @param string $password
+ * @param string $email
+ * @param string $mobile
+ * @param int $uid
+ * @param array $extend
+ * @return int
+ */
+ function add_user($username, $password, $email = '', $mobile = '', $uid = 0, $extend = [])
+ {
+ $regip = $this->base->onlineip;
+ $salt = substr(uniqid(rand()), -6);
+ $password = md5(md5($password) . $salt);
+
+ $values = $uid ? "uid='" . intval($uid) . "'," : '';
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "members SET $values username='$username', password='$password', email='$email', regip='$regip', regdate='" . $this->base->time . "', salt='$salt'");
+ $uid = $this->db->insert_id();
+ $extendfields = [];
+ foreach ($extend as $k => $v)
+ {
+ $extendfields[] = "{$k} = '{$v}'";
+ }
+ $extendfields = $extendfields ? ',' . implode(',', $extendfields) : '';
+ $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "memberfields SET uid='$uid' {$extendfields}");
+ return $uid;
+ }
+
+ /**
+ * 编辑Ucenter中的账号
+ * @param string $username
+ * @param string $password
+ * @param string $email
+ * @param string $mobile
+ * @return int
+ */
+ function edit_user($username, $password = '', $email = '', $mobile = '', $uid = 0, $extend = [])
+ {
+ $uid = intval($uid);
+ $data = $this->db->fetch_first("SELECT username, uid, password, salt FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'");
+ if (!$data)
+ {
+ return -7;
+ }
+ $isprotected = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid = '{$data['uid']}'");
+ if ($isprotected)
+ {
+ return -8;
+ }
+ $fields = [];
+ if ($username)
+ $fields[] = "username = '{$username}'";
+ if ($email)
+ $fields[] = "email = '{$email}'";
+ if ($mobile)
+ $fields[] = "mobile = '{$mobile}'";
+ if ($password)
+ $fields[] = "password = '" . md5(md5($password) . $data['salt']) . "'";
+ $values = implode(',', $fields);
+ if ($values || $extend)
+ {
+ if ($values)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "members SET $values WHERE uid='{$data['uid']}'");
+ }
+ $extendfields = [];
+ foreach ($extend as $k => $v)
+ {
+ $extendfields[] = "{$k} = '{$v}'";
+ }
+ $extendfields = $extendfields ? implode(',', $extendfields) : '';
+ if ($extendfields)
+ {
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET {$extendfields} WHERE uid='{$data['uid']}'");
+ }
+ return 1;
+ }
+ else
+ {
+ return -7;
+ }
+ }
+
+ /**
+ * 删除一个账号
+ * @param array $uidsarr
+ * @return int
+ */
+ function delete_user($uidsarr)
+ {
+ $uidsarr = (array) $uidsarr;
+ if (!$uidsarr)
+ {
+ return 0;
+ }
+ $uids = $this->base->implode($uidsarr);
+ $arr = $this->db->fetch_all("SELECT uid FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid IN ($uids)");
+ $puids = array();
+ foreach ((array) $arr as $member)
+ {
+ $puids[] = $member['uid'];
+ }
+ $uids = $this->base->implode(array_diff($uidsarr, $puids));
+ if ($uids)
+ {
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "members WHERE uid IN($uids)");
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "memberfields WHERE uid IN($uids)");
+ uc_user_deleteavatar($uidsarr);
+ $this->base->load('note');
+ $_ENV['note']->add('deleteuser', "ids=$uids");
+ return $this->db->affected_rows();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ function delete_useravatar($uidsarr)
+ {
+ $uidsarr = (array) $uidsarr;
+ foreach ((array) $uidsarr as $uid)
+ {
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big', 'real')) && unlink($avatar_file);
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle', 'real')) && unlink($avatar_file);
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small', 'real')) && unlink($avatar_file);
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big')) && unlink($avatar_file);
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle')) && unlink($avatar_file);
+ file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small')) && unlink($avatar_file);
+ }
+ }
+
+ /**
+ * 获取账号总数
+ * @param string $sqladd
+ * @return int
+ */
+ function get_total_num($sqladd = '')
+ {
+ $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "members $sqladd");
+ return $data;
+ }
+
+ /**
+ * 获取列表
+ * @param int $page
+ * @param int $ppp
+ * @param int $totalnum
+ * @param string $sqladd
+ * @return array
+ */
+ function get_list($page, $ppp, $totalnum, $sqladd)
+ {
+ $start = $this->base->page_get_start($page, $ppp, $totalnum);
+ $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "members $sqladd LIMIT $start, $ppp");
+ return $data;
+ }
+
+ function name2id($usernamesarr)
+ {
+ $usernamesarr = uc_addslashes($usernamesarr, 1, TRUE);
+ $usernames = $this->base->implode($usernamesarr);
+ $query = $this->db->query("SELECT uid FROM " . UC_DBTABLEPRE . "members WHERE username IN($usernames)");
+ $arr = array();
+ while ($user = $this->db->fetch_array($query))
+ {
+ $arr[] = $user['uid'];
+ }
+ return $arr;
+ }
+
+ function id2name($uidarr)
+ {
+ $arr = array();
+ $query = $this->db->query("SELECT uid, username FROM " . UC_DBTABLEPRE . "members WHERE uid IN (" . $this->base->implode($uidarr) . ")");
+ while ($user = $this->db->fetch_array($query))
+ {
+ $arr[$user['uid']] = $user['username'];
+ }
+ return $arr;
+ }
+
+ function quescrypt($questionid, $answer)
+ {
+ return $questionid > 0 && $answer != '' ? substr(md5($answer . md5($questionid)), 16, 8) : '';
+ }
+
+ function can_do_login($username, $ip = '')
+ {
+
+ $check_times = $this->base->settings['login_failedtime'] < 1 ? 5 : $this->base->settings['login_failedtime'];
+
+ $username = substr(md5($username), 8, 15);
+ $expire = 15 * 60;
+ if (!$ip)
+ {
+ $ip = $this->base->onlineip;
+ }
+
+ $ip_check = $user_check = array();
+ $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "failedlogins WHERE ip='" . $ip . "' OR ip='$username'");
+ while ($row = $this->db->fetch_array($query))
+ {
+ if ($row['ip'] === $username)
+ {
+ $user_check = $row;
+ }
+ elseif ($row['ip'] === $ip)
+ {
+ $ip_check = $row;
+ }
+ }
+
+ if (empty($ip_check) || ($this->base->time - $ip_check['lastupdate'] > $expire))
+ {
+ $ip_check = array();
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$ip}', '0', '{$this->base->time}')");
+ }
+
+ if (empty($user_check) || ($this->base->time - $user_check['lastupdate'] > $expire))
+ {
+ $user_check = array();
+ $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$username}', '0', '{$this->base->time}')");
+ }
+
+ if ($ip_check || $user_check)
+ {
+ $time_left = min(($check_times - $ip_check['count']), ($check_times - $user_check['count']));
+ return $time_left;
+ }
+
+ $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "failedlogins WHERE lastupdate<" . ($this->base->time - ($expire + 1)), 'UNBUFFERED');
+
+ return $check_times;
+ }
+
+ function loginfailed($username, $ip = '')
+ {
+ $username = substr(md5($username), 8, 15);
+ if (!$ip)
+ {
+ $ip = $this->base->onlineip;
+ }
+ $this->db->query("UPDATE " . UC_DBTABLEPRE . "failedlogins SET count=count+1, lastupdate='" . $this->base->time . "' WHERE ip='" . $ip . "' OR ip='$username'");
+ }
+
+}
diff --git a/extend/fast/ucenter/common/Functions.php b/extend/fast/ucenter/common/Functions.php
new file mode 100644
index 00000000..9f9df9d7
--- /dev/null
+++ b/extend/fast/ucenter/common/Functions.php
@@ -0,0 +1,98 @@
+ 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16))
+ {
+ return substr($result, 26);
+ }
+ else
+ {
+ return '';
+ }
+ }
+ else
+ {
+ return $keyc . str_replace('=', '', base64_encode($result));
+ }
+}
+
+function _uc_stripslashes($string)
+{
+ if (is_array($string))
+ {
+ foreach ($string as $key => $val)
+ {
+ $string[$key] = _stripslashes($val);
+ }
+ }
+ else
+ {
+ $string = stripslashes($string);
+ }
+ return $string;
+}
+
+/**
+ * 字符串命名风格转换
+ * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
+ * @param string $name 字符串
+ * @param integer $type 转换类型
+ * @return string
+ */
+function parse_name($name, $type = 0)
+{
+ if ($type)
+ {
+ return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match)
+ {
+ return strtoupper($match[1]);
+ }, $name));
+ }
+ else
+ {
+ return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
+ }
+}
diff --git a/extend/fast/ucenter/common/XML.php b/extend/fast/ucenter/common/XML.php
new file mode 100644
index 00000000..938fbd59
--- /dev/null
+++ b/extend/fast/ucenter/common/XML.php
@@ -0,0 +1,129 @@
+parse($xml);
+ $xml_parser->destruct();
+ return $data;
+}
+
+function xml_serialize($arr, $htmlon = FALSE, $isnormal = FALSE, $level = 1)
+{
+ $s = $level == 1 ? "\r\n\r\n" : '';
+ $space = str_repeat("\t", $level);
+ foreach ($arr as $k => $v)
+ {
+ if (!is_array($v))
+ {
+ $s .= $space . "- " . ($htmlon ? '' : '') . "
\r\n";
+ }
+ else
+ {
+ $s .= $space . "- \r\n" . xml_serialize($v, $htmlon, $isnormal, $level + 1) . $space . "
\r\n";
+ }
+ }
+ $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
+ return $level == 1 ? $s . "" : $s;
+}
+
+class XML
+{
+
+ var $parser;
+ var $document;
+ var $stack;
+ var $data;
+ var $last_opened_tag;
+ var $isnormal;
+ var $attrs = array();
+ var $failed = FALSE;
+
+ function __construct($isnormal)
+ {
+ $this->XML($isnormal);
+ }
+
+ function XML($isnormal)
+ {
+ $this->isnormal = $isnormal;
+ $this->parser = xml_parser_create('ISO-8859-1');
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_object($this->parser, $this);
+ xml_set_element_handler($this->parser, 'open', 'close');
+ xml_set_character_data_handler($this->parser, 'data');
+ }
+
+ function destruct()
+ {
+ xml_parser_free($this->parser);
+ }
+
+ function parse(&$data)
+ {
+ $this->document = array();
+ $this->stack = array();
+ return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : '';
+ }
+
+ function open(&$parser, $tag, $attributes)
+ {
+ $this->data = '';
+ $this->failed = FALSE;
+ if (!$this->isnormal)
+ {
+ if (isset($attributes['id']) && !is_string($this->document[$attributes['id']]))
+ {
+ $this->document = &$this->document[$attributes['id']];
+ }
+ else
+ {
+ $this->failed = TRUE;
+ }
+ }
+ else
+ {
+ if (!isset($this->document[$tag]) || !is_string($this->document[$tag]))
+ {
+ $this->document = &$this->document[$tag];
+ }
+ else
+ {
+ $this->failed = TRUE;
+ }
+ }
+ $this->stack[] = &$this->document;
+ $this->last_opened_tag = $tag;
+ $this->attrs = $attributes;
+ }
+
+ function data(&$parser, $data)
+ {
+ if ($this->last_opened_tag != NULL)
+ {
+ $this->data .= $data;
+ }
+ }
+
+ function close(&$parser, $tag)
+ {
+ if ($this->last_opened_tag == $tag)
+ {
+ $this->document = $this->data;
+ $this->last_opened_tag = NULL;
+ }
+ array_pop($this->stack);
+ if ($this->stack)
+ {
+ $this->document = &$this->stack[count($this->stack) - 1];
+ }
+ }
+
+}