15 |
16 |
17 |
18 | 添加/更新微博账号
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
40 |
48 |
49 |
50 | 正在加载 .
51 |
52 |
53 |
54 |
55 |
跳转微博客户端登录 我已完成登录
56 |
57 |
58 |
59 |
60 |
73 |
74 |
75 | 使用QQ手机版扫描二维码 .
76 |
77 |
80 |
跳转QQ快捷登录 我已完成登录
81 |
82 |
返回账号列表
83 |
84 |
85 |
86 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/admin/ajax.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
4 | $act=isset($_GET['act'])?daddslashes($_GET['act']):null;
5 |
6 | if(!checkRefererHost())exit('{"code":403}');
7 |
8 | @header('Content-Type: application/json; charset=UTF-8');
9 |
10 | switch($act){
11 | case 'set':
12 | if(isset($_POST['opentype'])){
13 | $_POST['opentype'] = implode(',',$_POST['opentype']);
14 | }
15 | foreach($_POST as $k=>$v){
16 | saveSetting($k, $v);
17 | }
18 | exit('{"code":0,"msg":"succ"}');
19 | break;
20 |
21 | case 'checkAccount':
22 | $id = intval($_POST['id']);
23 | try{
24 | $result = \lib\Logic::checkAccount($id);
25 | }catch(Exception $e){
26 | exit(json_encode(['code'=>-1, 'msg'=>$e->getMessage()]));
27 | }
28 | if($result == 2){
29 | exit(json_encode(['code'=>0, 'msg'=>'账号COOKIE更新成功!']));
30 | }elseif($result == 1){
31 | exit(json_encode(['code'=>0, 'msg'=>'账号状态检测正常!']));
32 | }else{
33 | exit(json_encode(['code'=>-1, 'msg'=>'账号状态已失效,请点击更新按钮进行登录']));
34 | }
35 | break;
36 |
37 | case 'deleteAccount':
38 | $id = intval($_POST['id']);
39 | $row = $DB->find('account', '*', ['id'=>$id]);
40 | if(!$row)exit('{"code":-1,"msg":"账号不存在"}');
41 | $DB->delete('account', ['id'=>$id]);
42 | $DB->delete('log', ['aid'=>$id]);
43 | exit(json_encode(['code'=>0]));
44 | break;
45 |
46 | case 'weiboLogin':
47 | $login=new \lib\WeiboLogin();
48 | if($_GET['do']=='getqrcode'){
49 | $array=$login->getqrcode();
50 | }
51 | if($_GET['do']=='qrlogin'){
52 | $array=$login->qrlogin($_POST['qrid']);
53 | if($array['code'] == 0){
54 | \lib\Logic::addAccount($array);
55 | }
56 | }
57 | if($_GET['do']=='getconfig'){
58 | $array=$login->getconfig();
59 | }
60 | if($_GET['do']=='login'){
61 | $array=$login->login($_POST['user'],$_POST['pwd'],$_POST['rsakv'],$_POST['cid'],$_POST['csrf_token']);
62 | if($array['code'] == 0){
63 | \lib\Logic::addAccount($array);
64 | }
65 | }
66 | if($_GET['do']=='verifycaptcha'){
67 | $array=$login->verifycaptcha($_POST['key'], $_POST['lot_number'], $_POST['captcha_output'], $_POST['pass_token'], $_POST['gen_time']);
68 | }
69 | if($_GET['do']=='sendcode'){
70 | $array=$login->sendcode($_POST['type'],$_POST['token'],$_POST['encrypt_mobile']);
71 | }
72 | if($_GET['do']=='confirmcode'){
73 | $array=$login->confirmcode($_POST['type'],$_POST['token'],$_POST['encrypt_mobile'],$_POST['code']);
74 | }
75 | if($_GET['do']=='sendsms'){
76 | $array=$login->sendsms($_POST['mobile'],$_POST['cid'],$_POST['csrf_token']);
77 | }
78 | if($_GET['do']=='smslogin'){
79 | $array=$login->smslogin($_POST['user'],$_POST['code'],$_POST['csrf_token']);
80 | if($array['code'] == 0){
81 | \lib\Logic::addAccount($array);
82 | }
83 | }
84 | if($_GET['do']=='qq_getqrcode'){
85 | $array=$login->qq_getqrcode();
86 | }
87 | if($_GET['do']=='qq_qrlogin'){
88 | $array=$login->qq_qrlogin($_GET['qrsig']);
89 | }
90 | if($_GET['do']=='qq_connect'){
91 | $array=$login->qq_connect($_POST['redirect_uri'],$_POST['crossidccode']);
92 | if($array['code'] == 0){
93 | \lib\Logic::addAccount($array);
94 | }
95 | }
96 | echo json_encode($array);
97 | break;
98 |
99 | case 'upload':
100 | if(!isset($_FILES['file']))exit('{"code":-1,"msg":"请选择文件"}');
101 | $file = $_FILES["file"]["tmp_name"];
102 | if($_FILES['file']['error']>0 || $file == ""){
103 | exit('{"code":-1,"msg":"文件损坏!"}');
104 | }
105 | if($_FILES['file']['size']>10*1024*1024){
106 | exit('{"code":-1,"msg":"文件最大10M"}');
107 | }
108 | $result = weibotool_call('upload', [$file]);
109 | echo json_encode($result);
110 | break;
111 |
112 | default:
113 | exit('{"code":-4,"msg":"No Act"}');
114 | break;
115 | }
--------------------------------------------------------------------------------
/admin/apidoc.md:
--------------------------------------------------------------------------------
1 | # 微博API接口文档
2 |
3 | - [微博API接口文档](#微博api接口文档)
4 | - [获取微博COOKIE](#获取微博COOKIE)
5 | - [获取微博热搜列表](#获取微博热搜列表)
6 | - [解析微博视频](#解析微博视频)
7 | - [获取微博用户信息](#获取微博用户信息)
8 |
9 |
10 | ## 获取微博COOKIE
11 |
12 | 请求URL:
13 |
14 | > /api.php?act=getcookie
15 |
16 | 请求方式:POST
17 |
18 | 请求参数:
19 |
20 | | 参数名 | 必填 | 类型 | 描述 |
21 | | ------ | ---- | ------ | -------------------- |
22 | | key | 是 | string | 获取COOKIE密钥 |
23 | | uid | 否 | string | 用户ID(留空为随机) |
24 |
25 | 返回示例:
26 |
27 | ```
28 | {
29 | "code":0,
30 | "uid":"123456",
31 | "nickname":"名称",
32 | "cookie":"SUB=..."
33 | }
34 | ```
35 |
36 | 异常返回示例:
37 |
38 | ```
39 | {
40 | "code":-1,
41 | "msg":"微博账号状态不正常"
42 | }
43 | ```
44 |
45 | 返回参数说明:
46 |
47 | | 参数名 | 类型 | 描述 |
48 | | -------- | ------ | -------------------- |
49 | | code | int | 0 是成功,其他是失败 |
50 | | msg | string | 失败原因 |
51 | | uid | string | 用户ID |
52 | | nickname | string | 用户昵称 |
53 | | cookie | string | COOKIE内容 |
54 |
55 | ## 获取微博热搜列表
56 |
57 | 请求URL:
58 |
59 | > /api.php?act=gethotsearch
60 |
61 | 请求方式:POST
62 |
63 | 请求参数:
64 |
65 | | 参数名 | 必填 | 类型 | 描述 |
66 | | ------ | ---- | ------ | ----------- |
67 | | key | 是 | string | API接口密钥 |
68 |
69 | 返回示例:
70 |
71 | ```
72 | {
73 | "code": 0,
74 | "data": [
75 | {
76 | "rank": 1,
77 | "category": "动漫,作品衍生",
78 | "content": "天官赐福第二季开播",
79 | "time": 1697631213,
80 | "num": 1052196,
81 | "label": "新",
82 | "mid": ""
83 | },
84 | {
85 | "rank": 2,
86 | "category": "电影",
87 | "content": "突然明白你好李焕英名字起的有多好",
88 | "time": 1697622338,
89 | "num": 1006787,
90 | "label": "热",
91 | "mid": "4957758824908712"
92 | },
93 | ......
94 | ]
95 | }
96 | ```
97 |
98 | 返回参数说明:
99 |
100 | | 参数名 | 类型 | 描述 |
101 | | --------------- | ------ | -------------------- |
102 | | code | int | 0 是成功,其他是失败 |
103 | | msg | string | 失败原因 |
104 | | data | array | 热搜列表 |
105 | | data[].rank | int | 热搜排名 |
106 | | data[].category | string | 热搜分类 |
107 | | data[].content | string | 热搜内容 |
108 | | data[].time | int | 创建时间 |
109 | | data[].num | int | 话题数量 |
110 | | data[].label | string | 标签文字 |
111 | | data[].mid | string | 唯一ID |
112 |
113 | ## 解析微博视频
114 |
115 | 请求URL:
116 |
117 | > /api.php?act=parsevideo
118 |
119 | 请求方式:POST
120 |
121 | 请求参数:
122 |
123 | | 参数名 | 必填 | 类型 | 描述 |
124 | | ------ | ---- | ------ | ----------- |
125 | | key | 是 | string | API接口密钥 |
126 | | oid | 是 | string | 视频ID |
127 |
128 | 返回示例:
129 |
130 | ```
131 | {
132 | "code": 0,
133 | "data": {
134 | "title": "中国空间站办起了国际画展",
135 | "author": "央视新闻",
136 | "author_id": 2656274875,
137 | "author_avatar": "//tvax3.sinaimg.cn/...",
138 | "urls": {
139 | "高清 1080P": "//f.video.weibocdn.com/...",
140 | "高清 720P": "//f.video.weibocdn.com/...",
141 | "标清 480P": "//f.video.weibocdn.com/...",
142 | "流畅 360P": "//f.video.weibocdn.com/..."
143 | },
144 | "cover": "//wx4.sinaimg.cn/...",
145 | "time": 1697550667,
146 | "duration": "6:43"
147 | }
148 | }
149 | ```
150 |
151 | 返回参数说明:
152 |
153 | | 参数名 | 类型 | 描述 |
154 | | ------------------ | ------ | -------------------- |
155 | | code | int | 0 是成功,其他是失败 |
156 | | msg | string | 失败原因 |
157 | | data.title | string | 视频标题 |
158 | | data.author | string | 视频作者 |
159 | | data.author_id | int | 视频作者ID |
160 | | data.author_avatar | string | 视频作者头像 |
161 | | data.urls | array | 视频播放链接 |
162 | | data.cover | string | 视频封面 |
163 | | data.time | int | 发表时间 |
164 | | data.duration | string | 视频长度 |
165 |
166 | ## 获取微博用户信息
167 |
168 | 请求URL:
169 |
170 | > /api.php?act=getuserinfo
171 |
172 | 请求方式:POST
173 |
174 | 请求参数:
175 |
176 | | 参数名 | 必填 | 类型 | 描述 |
177 | | ------ | ---- | ------ | ----------- |
178 | | key | 是 | string | API接口密钥 |
179 | | uid | 是 | string | 用户ID |
180 |
181 | 返回示例:
182 |
183 | ```
184 | {
185 | "code": 0,
186 | "data": {
187 | "uid": "2656274875",
188 | "name": "央视新闻",
189 | "avatar": "//tvax3.sinaimg.cn/...",
190 | "gender": "m",
191 | "location": "北京",
192 | "description": "“央视新闻”是中央广播电视总台...",
193 | "domain": "cctvxinwen",
194 | "friends_count": 2743,
195 | "followers_count": 131851188,
196 | "statuses_count": 170371,
197 | "verified": true,
198 | "verified_reason": "中央广播电视总台央视新闻官方账号",
199 | "verified_type": 3,
200 | "is_muteuser": false
201 | }
202 | }
203 | ```
204 |
205 | 返回参数说明:
206 |
207 | | 参数名 | 类型 | 描述 |
208 | | -------------------- | ------ | -------------------- |
209 | | code | int | 0 是成功,其他是失败 |
210 | | msg | string | 失败原因 |
211 | | data.uid | string | 用户ID |
212 | | data.name | string | 昵称 |
213 | | data.avatar | string | 头像 |
214 | | data.gender | string | 性别 |
215 | | data.location | string | 地址 |
216 | | data.description | string | 描述 |
217 | | data.domain | string | 自定义域名 |
218 | | data.friends_count | int | 关注数量 |
219 | | data.followers_count | int | 粉丝数量 |
220 | | data.statuses_count | int | 微博数量 |
221 | | data.verified | bool | 是否已认证 |
222 | | data.verified_reason | string | 认证身份 |
223 | | data.verified_type | int | 认证类型 |
224 | | data.is_muteuser | bool | 是否被禁言 |
225 |
226 |
--------------------------------------------------------------------------------
/admin/assets/js/login_pwd.js:
--------------------------------------------------------------------------------
1 | var comm_data = {
2 | servertime:'',
3 | nonce:'',
4 | rsakv:'',
5 | pubkey:'',
6 | cid:'',
7 | csrf_token:'',
8 | }
9 | var ajax={
10 | get: function(url, dataType, callback) {
11 | dataType = dataType || 'html';
12 | $.ajax({
13 | type: "GET",
14 | url: url,
15 | async: true,
16 | dataType: dataType,
17 | cache:false,
18 | success: function(data,status) {
19 | if (callback == null) {
20 | return;
21 | }
22 | callback(data);
23 | },
24 | error: function(error) {
25 | alert('创建连接失败');
26 | }
27 | });
28 | },
29 | post: function(url, parameter, dataType, callback) {
30 | dataType = dataType || 'html';
31 | $.ajax({
32 | type: "POST",
33 | url: url,
34 | async: true,
35 | dataType: dataType,
36 | data: parameter,
37 | cache:false,
38 | success: function(data,status) {
39 | if (callback == null) {
40 | return;
41 | }
42 | callback(data);
43 | },
44 | error: function(error) {
45 | alert('创建连接失败');
46 | }
47 | });
48 | }
49 | }
50 | function invokeSettime(obj){
51 | var countdown=60;
52 | settime(obj);
53 | function settime(obj) {
54 | if (countdown == 0) {
55 | $(obj).attr("data-lock", "false");
56 | $(obj).attr("disabled",false);
57 | $(obj).text("获取验证码");
58 | countdown = 60;
59 | return;
60 | } else {
61 | $(obj).attr("data-lock", "true");
62 | $(obj).attr("disabled",true);
63 | $(obj).text(countdown + "秒后重试");
64 | countdown--;
65 | }
66 | setTimeout(function() { settime(obj) } ,1000)
67 | }
68 | }
69 | function trim(str){ //去掉头尾空格
70 | return str.replace(/(^\s*)|(\s*$)/g, "");
71 | }
72 | function encryptpwd(pwd){
73 | return SinaEncrypt("".concat([comm_data.servertime,comm_data.nonce].join("\t"), "\n").concat(pwd), comm_data.pubkey);
74 | }
75 | function getconfig(){
76 | var ii = layer.load(2, {shade: [0.1,'#fff']});
77 | var getvcurl="ajax.php?act=weiboLogin&do=getconfig";
78 | ajax.get(getvcurl, 'json', function(d) {
79 | layer.close(ii);
80 | if(d.code ==0){
81 | var data = d.data;
82 | comm_data.servertime = data.servertime;
83 | comm_data.nonce = data.nonce;
84 | comm_data.rsakv = data.rsakv;
85 | comm_data.pubkey = data.pubkey;
86 | comm_data.csrf_token = d.csrf_token;
87 | }else{
88 | layer.alert(d.msg, {icon: 2});
89 | }
90 | });
91 | }
92 | function login(user,pwd){
93 | var ii = layer.msg('正在登录,请稍候...', {icon: 16,shade: 0.5,time: 15000});
94 | var encpwd = encryptpwd(pwd);
95 | var loginurl="ajax.php?act=weiboLogin&do=login&r="+Math.random(1);
96 | ajax.post(loginurl, {user:user, pwd:encpwd, rsakv:comm_data.rsakv, cid:comm_data.cid, csrf_token:comm_data.csrf_token}, 'json', function(d) {
97 | layer.close(ii);
98 | if(d.code ==0){
99 | $('#login').hide();
100 | $('#submit').hide();
101 | $('#security').hide();
102 | $('#submit2').hide();
103 | showresult(d);
104 | }else if(d.code ==1){
105 | comm_data.cid = '';
106 | $('#load').html("您已开启登录保护,请验证手机后登录:"+d.mobile);
107 | $('#load').show();
108 | $('#submit').hide();
109 | $('#code').val("");
110 | $('#security').show();
111 | $('#security').attr('type',d.type);
112 | $('#security').attr('token',d.token);
113 | $('#security').attr('encrypt_mobile',d.encrypt_mobile);
114 | }else if(d.code ==2){
115 | comm_data.cid = d.cid;
116 | initGeetest4({
117 | captchaId: '8b4a2bef633eb0264367b3ba9fa1dd3d',
118 | product: 'bind',
119 | hideSuccess: true
120 | },function (captcha) {
121 | captcha.onReady(function(){
122 | captcha.showCaptcha();
123 | }).onSuccess(function(){
124 | var result = captcha.getValidate();
125 | if (!result) {
126 | layer.closeAll();
127 | return alert('请先完成验证');
128 | }
129 | var verifyurl="ajax.php?act=weiboLogin&do=verifycaptcha&r="+Math.random(1);
130 | ajax.post(verifyurl, {key:comm_data.cid, lot_number:result.lot_number, captcha_output:result.captcha_output, pass_token:result.pass_token, gen_time:result.gen_time}, 'json', function(d) {
131 | if(d.code ==0){
132 | login(user,pwd)
133 | }else{
134 | layer.alert(d.msg, {icon: 2});
135 | }
136 | });
137 | }).onError(function(){
138 | alert('验证码加载失败,请刷新页面重试');
139 | })
140 | });
141 | }else{
142 | comm_data.cid = '';
143 | $('#load').html(d.msg);
144 | $('#load').show();
145 | $('#submit').attr('do','submit');
146 | $('#login').show();
147 | }
148 | });
149 | }
150 | function sendcode(type,token,encrypt_mobile){
151 | var ii = layer.load(2, {shade: [0.1,'#fff']});
152 | var loginurl="ajax.php?act=weiboLogin&do=sendcode&r="+Math.random(1);
153 | ajax.post(loginurl, {type:type, token:token, encrypt_mobile:encrypt_mobile}, 'json', function(d) {
154 | layer.close(ii);
155 | if(d.code ==0){
156 | $('#smscode').focus();
157 | invokeSettime("#sendcode");
158 | layer.alert('验证码发送成功,请查收', {icon: 1}, function(){ layer.closeAll();$('#smscode').focus() });
159 | }else{
160 | layer.alert(d.msg, {icon: 2});
161 | }
162 | });
163 | }
164 | function confirmcode(type,token,encrypt_mobile,code){
165 | var ii = layer.msg('正在验证,请稍等...', {icon: 16,shade: 0.5,time: 15000});
166 | var loginurl="ajax.php?act=weiboLogin&do=confirmcode&r="+Math.random(1);
167 | ajax.post(loginurl, {type:type, token:token, encrypt_mobile:encrypt_mobile, code:code}, 'json', function(d) {
168 | layer.close(ii);
169 | if(d.code ==0){
170 | $('#login').hide();
171 | $('#submit').hide();
172 | $('#security').hide();
173 | $('#submit2').hide();
174 | showresult(d);
175 | }else{
176 | layer.alert(d.msg, {icon: 2});
177 | $('#login').show();
178 | }
179 | });
180 | }
181 | function showresult(arr){
182 | $('#load').html('
微博账号添加成功!
'+decodeURIComponent(arr.nick)+'(UID:'+arr.uid+')');
183 | $('#load').show();
184 | }
185 | $(document).ready(function(){
186 | $('#submit').click(function(){
187 | var self=$(this);
188 | var user=trim($('#user').val()),
189 | pwd=trim($('#pwd').val());
190 | if(user==''||pwd=='') {
191 | alert("请确保每项不能为空!");
192 | return false;
193 | }
194 | if (self.attr("data-lock") === "true") return;
195 | else self.attr("data-lock", "true");
196 | login(user,pwd);
197 | self.attr("data-lock", "false");
198 | });
199 | $('#submit2').click(function(){
200 | var self=$(this);
201 | var code=trim($('#smscode').val());
202 | if(code=='') {
203 | alert("验证码不能为空!");
204 | return false;
205 | }
206 | if (self.attr("data-lock") === "true") return;
207 | else self.attr("data-lock", "true");
208 | var type=$('#security').attr('type'),
209 | token=$('#security').attr('token'),
210 | encrypt_mobile=$('#security').attr('encrypt_mobile');
211 | confirmcode(type,token,encrypt_mobile,code);
212 | self.attr("data-lock", "false");
213 | });
214 | $('#sendcode').click(function(){
215 | var self=$(this);
216 | if (self.attr("data-lock") === "true") return;
217 | else self.attr("data-lock", "true");
218 | var type=$('#security').attr('type'),
219 | token=$('#security').attr('token'),
220 | encrypt_mobile=$('#security').attr('encrypt_mobile');
221 | sendcode(type,token,encrypt_mobile);
222 | self.attr("data-lock", "false");
223 | });
224 | getconfig();
225 | });
--------------------------------------------------------------------------------
/admin/assets/js/login_qq.js:
--------------------------------------------------------------------------------
1 | var interval1,interval2;
2 | function showresult(arr){
3 | $('#login').html('
微博账号添加成功!
'+decodeURIComponent(arr.nick)+'(UID:'+arr.uid+')');
4 | }
5 | function getqrpic(){
6 | cleartime();
7 | var getvcurl='ajax.php?act=weiboLogin&do=qq_getqrcode&r='+Math.random(1);
8 | $.get(getvcurl, function(d) {
9 | if(d.code ==0){
10 | $('#qrimg').attr('qrsig',d.qrsig);
11 | $('#qrimg').attr('qrcode',d.qrcode);
12 | $('#qrcode').empty()
13 | $('#qrcode').qrcode({
14 | text: d.qrcode,
15 | width: 150,
16 | height: 150,
17 | foreground: "#000000",
18 | background: "#ffffff",
19 | typeNumber: -1
20 | });
21 | if( /Android|SymbianOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Phone|Midp/i.test(navigator.userAgent)) {
22 | $('#mobile').show();
23 | }
24 | interval1=setInterval(loginload,1000);
25 | interval2=setInterval(qrlogin,3000);
26 | }else{
27 | alert(d.msg);
28 | }
29 | }, 'json');
30 | }
31 | function qrlogin(){
32 | if ($('#login').attr("data-lock") === "true") return;
33 | var qrsig=$('#qrimg').attr('qrsig');
34 | var url = 'ajax.php?act=weiboLogin&do=qq_qrlogin&qrsig='+decodeURIComponent(qrsig)+'&r='+Math.random(1);
35 | $.get(url, function(d) {
36 | if(d.code ==0){
37 | $('#login').attr("data-lock", "true");
38 | $('#loginmsg').html('正在登录微博,请稍候...');
39 | cleartime();
40 | qqconnect(d.redirect_uri, d.crossidccode);
41 | }else if(d.code ==1){
42 | getqrpic();
43 | $('#loginmsg').html('请重新扫描二维码');
44 | }else if(d.code ==2){
45 | $('#loginmsg').html('使用QQ手机版扫描二维码');
46 | }else if(d.code ==3){
47 | $('#loginmsg').html('扫描成功,请在手机上确认授权登录');
48 | }else{
49 | cleartime();
50 | $('#loginmsg').html(d.msg);
51 | }
52 | }, 'json');
53 | }
54 | function qqconnect(redirect_uri, crossidccode){
55 | $.ajax({
56 | type : "POST",
57 | url : "ajax.php?act=weiboLogin&do=qq_connect",
58 | data : {redirect_uri:redirect_uri, crossidccode:crossidccode},
59 | dataType : 'json',
60 | success : function(data) {
61 | if(data.code == 0){
62 | showresult(data);
63 | $('#qrimg').hide();
64 | $('#mobile').hide();
65 | }else{
66 | $('#loginmsg').html(data.msg);
67 | }
68 | }
69 | });
70 | }
71 | function loginload(){
72 | if ($('#login').attr("data-lock") === "true") return;
73 | var load=document.getElementById('loginload').innerHTML;
74 | var len=load.length;
75 | if(len>2){
76 | load='.';
77 | }else{
78 | load+='.';
79 | }
80 | document.getElementById('loginload').innerHTML=load;
81 | }
82 | function cleartime(){
83 | clearInterval(interval1);
84 | clearInterval(interval2);
85 | }
86 | function mloginurl(){
87 | var qrurl = $('#qrimg').attr('qrcode');
88 | $('#loginmsg').html('跳转到QQ登录后请返回此页面');
89 | var ua = window.navigator.userAgent.toLowerCase();
90 | var is_ios = ua.indexOf('iphone')>-1 || ua.indexOf('ipad')>-1;
91 | var schemacallback = '';
92 | if(is_ios){
93 | schemacallback = 'weixin://';
94 | }else if(ua.indexOf('ucbrowser')>-1){
95 | schemacallback = 'ucweb://';
96 | }else if(ua.indexOf('meizu')>-1){
97 | schemacallback = 'mzbrowser://';
98 | }else if(ua.indexOf('liebaofast')>-1){
99 | schemacallback = 'lb://';
100 | }else if(ua.indexOf('baidubrowser')>-1){
101 | schemacallback = 'bdbrowser://';
102 | }else if(ua.indexOf('baiduboxapp')>-1){
103 | schemacallback = 'bdapp://';
104 | }else if(ua.indexOf('mqqbrowser')>-1){
105 | schemacallback = 'mqqbrowser://';
106 | }else if(ua.indexOf('qihoobrowser')>-1){
107 | schemacallback = 'qihoobrowser://';
108 | }else if(ua.indexOf('chrome')>-1){
109 | schemacallback = 'googlechrome://';
110 | }else if(ua.indexOf('sogoumobilebrowser')>-1){
111 | schemacallback = 'SogouMSE://';
112 | }else if(ua.indexOf('xiaomi')>-1){
113 | schemacallback = 'miuibrowser://';
114 | }else{
115 | schemacallback = 'googlechrome://';
116 | }
117 | if(is_ios){
118 | alert('跳转到QQ登录后请手动返回当前浏览器');
119 | window.location.href='wtloginmqq3://ptlogin/qlogin?qrcode='+encodeURIComponent(qrurl)+'&schemacallback='+encodeURIComponent(schemacallback);
120 | }else{
121 | window.location.href='wtloginmqq://ptlogin/qlogin?qrcode='+encodeURIComponent(qrurl)+'&schemacallback='+encodeURIComponent(schemacallback);
122 | }
123 | }
124 | $(document).ready(function(){
125 | getqrpic();
126 | });
--------------------------------------------------------------------------------
/admin/assets/js/login_scan.js:
--------------------------------------------------------------------------------
1 | var interval1,interval2;
2 | function getqrcode(){
3 | if($('#qrimg').attr('lock') === 'true') return;
4 | cleartime();
5 | var getvcurl='ajax.php?act=weiboLogin&do=getqrcode&r='+Math.random(1);
6 | $.get(getvcurl, function(d) {
7 | if(d.code ==0){
8 | $('#qrimg').attr('qrid',d.qrid);
9 | $('#qrimg').attr('link',d.link);
10 | $('#qrimg').html('
');
11 | $('#login').show();
12 | $('#loginmsg').html('请用最新版微博客户端扫码');
13 | if( /Android|SymbianOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Phone|Midp/i.test(navigator.userAgent)) {
14 | $('#mobile').show();
15 | }
16 | interval1=setInterval(loginload,1000);
17 | interval2=setInterval(qrlogin,3000);
18 | }else{
19 | alert(d.msg);
20 | }
21 | }, 'json');
22 | }
23 | function qrlogin(){
24 | var qrid=$('#qrimg').attr('qrid');
25 | if(qrid=='')return;
26 | var loginurl="ajax.php?act=weiboLogin&do=qrlogin";
27 | $.ajax({
28 | type: "POST",
29 | url: loginurl,
30 | async: true,
31 | dataType: 'json',
32 | timeout: 15000,
33 | data: {qrid : qrid},
34 | cache:false,
35 | success: function(data) {
36 | if(data.code ==0){
37 | cleartime();
38 | $('#qrimg').attr('lock','true');
39 | $('#login').hide();
40 | showresult(data)
41 | }else if(data.code ==1){
42 | $('#loginmsg').html('请用最新版微博客户端扫码');
43 | }else if(data.code ==2){
44 | $('#loginmsg').html('成功扫描,请在手机点击确认以登录');
45 | }else if(data.code ==3){
46 | $('#loginmsg').html('该二维码已过期,请重新扫描');
47 | getqrcode();
48 | }else{
49 | cleartime();
50 | $('#loginmsg').html(data.msg);
51 | alert(data.msg);
52 | }
53 | },
54 | error: function(){
55 | cleartime();
56 | alert('服务器错误');
57 | }
58 | });
59 | }
60 | function loginload(){
61 | var load=document.getElementById('loginload').innerHTML;
62 | var len=load.length;
63 | if(len>2){
64 | load='.';
65 | }else{
66 | load+='.';
67 | }
68 | document.getElementById('loginload').innerHTML=load;
69 | }
70 | function cleartime(){
71 | clearInterval(interval1);
72 | clearInterval(interval2);
73 | }
74 | function showresult(arr){
75 | $('#load').html('
微博账号添加成功!
'+decodeURIComponent(arr.nick)+'(UID:'+arr.uid+')');
76 | }
77 | function mloginurl(){
78 | var url = $('#qrimg').attr('link');
79 | window.location.href='sinaweibo://browser?url='+encodeURIComponent(url);
80 | }
81 | $(document).ready(function(){
82 | getqrcode();
83 | });
--------------------------------------------------------------------------------
/admin/assets/js/login_sms.js:
--------------------------------------------------------------------------------
1 | var comm_data = {
2 | servertime:'',
3 | nonce:'',
4 | rsakv:'',
5 | pubkey:'',
6 | cid:'',
7 | csrf_token:'',
8 | smstoken:''
9 | }
10 | var ajax={
11 | get: function(url, dataType, callback) {
12 | dataType = dataType || 'html';
13 | $.ajax({
14 | type: "GET",
15 | url: url,
16 | async: true,
17 | dataType: dataType,
18 | cache:false,
19 | success: function(data,status) {
20 | if (callback == null) {
21 | return;
22 | }
23 | callback(data);
24 | },
25 | error: function(error) {
26 | alert('创建连接失败');
27 | }
28 | });
29 | },
30 | post: function(url, parameter, dataType, callback) {
31 | dataType = dataType || 'html';
32 | $.ajax({
33 | type: "POST",
34 | url: url,
35 | async: true,
36 | dataType: dataType,
37 | data: parameter,
38 | cache:false,
39 | success: function(data,status) {
40 | if (callback == null) {
41 | return;
42 | }
43 | callback(data);
44 | },
45 | error: function(error) {
46 | alert('创建连接失败');
47 | }
48 | });
49 | }
50 | }
51 | function invokeSettime(obj){
52 | var countdown=60;
53 | settime(obj);
54 | function settime(obj) {
55 | if (countdown == 0) {
56 | $(obj).attr("data-lock", "false");
57 | $(obj).attr("disabled",false);
58 | $(obj).text("获取验证码");
59 | countdown = 60;
60 | return;
61 | } else {
62 | $(obj).attr("data-lock", "true");
63 | $(obj).attr("disabled",true);
64 | $(obj).text(countdown + "秒后重试");
65 | countdown--;
66 | }
67 | setTimeout(function() { settime(obj) } ,1000)
68 | }
69 | }
70 | function trim(str){ //去掉头尾空格
71 | return str.replace(/(^\s*)|(\s*$)/g, "");
72 | }
73 | function getconfig(){
74 | var ii = layer.load(2, {shade: [0.1,'#fff']});
75 | var getvcurl="ajax.php?act=weiboLogin&do=getconfig";
76 | ajax.get(getvcurl, 'json', function(d) {
77 | layer.close(ii);
78 | if(d.code ==0){
79 | var data = d.data;
80 | comm_data.servertime = data.servertime;
81 | comm_data.nonce = data.nonce;
82 | comm_data.rsakv = data.rsakv;
83 | comm_data.pubkey = data.pubkey;
84 | comm_data.csrf_token = d.csrf_token;
85 | }else{
86 | layer.alert(d.msg, {icon: 2});
87 | }
88 | });
89 | }
90 | function login(user,code){
91 | var ii = layer.msg('正在登录,请稍候...', {icon: 16,shade: 0.5,time: 15000});
92 | var loginurl="ajax.php?act=weiboLogin&do=smslogin&r="+Math.random(1);
93 | ajax.post(loginurl, {user:user, code:code, csrf_token:comm_data.csrf_token}, 'json', function(d) {
94 | layer.close(ii);
95 | if(d.code ==0){
96 | $('#login').hide();
97 | $('#submit').hide();
98 | showresult(d);
99 | }else{
100 | $('#load').html(d.msg);
101 | $('#load').show();
102 | $('#login').show();
103 | }
104 | });
105 | }
106 | function sendsms(mobile){
107 | var ii = layer.load(2, {shade: [0.1,'#fff']});
108 | var loginurl="ajax.php?act=weiboLogin&do=sendsms&r="+Math.random(1);
109 | ajax.post(loginurl, {mobile:mobile, cid:comm_data.cid, csrf_token:comm_data.csrf_token}, 'json', function(d) {
110 | layer.close(ii);
111 | if(d.code ==0){
112 | $('#sms').show();
113 | $('#submit').attr('do','smscode');
114 | invokeSettime("#sendcode");
115 | layer.alert('验证码发送成功,请查收', {icon: 1}, function(){ layer.closeAll();$('#sendcode').focus() });
116 | }else if(d.code ==2){
117 | comm_data.cid = d.cid;
118 | initGeetest4({
119 | captchaId: '8b4a2bef633eb0264367b3ba9fa1dd3d',
120 | product: 'bind',
121 | hideSuccess: true
122 | },function (captcha) {
123 | captcha.onReady(function(){
124 | captcha.showCaptcha();
125 | }).onSuccess(function(){
126 | var result = captcha.getValidate();
127 | if (!result) {
128 | layer.closeAll();
129 | return alert('请先完成验证');
130 | }
131 | $('#validate_data').val(window.btoa(JSON.stringify(result)));
132 | var verifyurl="ajax.php?act=weiboLogin&do=verifycaptcha&r="+Math.random(1);
133 | ajax.post(verifyurl, {key:comm_data.cid, lot_number:result.lot_number, captcha_output:result.captcha_output, pass_token:result.pass_token, gen_time:result.gen_time}, 'json', function(d) {
134 | if(d.code ==0){
135 | sendsms(mobile)
136 | }else{
137 | layer.alert(d.msg, {icon: 2});
138 | }
139 | });
140 | }).onError(function(){
141 | alert('验证码加载失败,请刷新页面重试');
142 | })
143 | });
144 | }else{
145 | layer.alert(d.msg, {icon: 2});
146 | }
147 | });
148 | }
149 | function showresult(arr){
150 | $('#load').html('
微博账号添加成功!
'+decodeURIComponent(arr.nick)+'(UID:'+arr.uid+')');
151 | $('#load').show();
152 | }
153 | $(document).ready(function(){
154 | $('#submit').click(function(){
155 | var self=$(this);
156 | var mobile=trim($('#mobile').val()),
157 | smscode=trim($('#smscode').val());
158 | if(mobile=='') {
159 | alert("手机号不能为空!");
160 | return false;
161 | }
162 | if (self.attr("data-lock") === "true") return;
163 | else self.attr("data-lock", "true");
164 | if(self.attr('do') == 'smscode'){
165 | if(smscode=='') {
166 | alert("验证码不能为空!");
167 | return false;
168 | }
169 | login(mobile,smscode);
170 | }else{
171 | sendsms(mobile);
172 | }
173 | self.attr("data-lock", "false");
174 | });
175 | $('#sendcode').click(function(){
176 | var self=$(this);
177 | var mobile=trim($('#mobile').val());
178 | if(mobile=='') {
179 | alert("手机号不能为空!");
180 | return false;
181 | }
182 | if (self.attr("data-lock") === "true") return;
183 | else self.attr("data-lock", "true");
184 | sendsms(mobile);
185 | self.attr("data-lock", "false");
186 | });
187 | getconfig();
188 | });
--------------------------------------------------------------------------------
/admin/download.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
4 |
5 | $mod=isset($_GET['mod'])?$_GET['mod']:null;
6 |
7 | if($mod == 'faceimg'){
8 | $uid = isset($_GET['uid'])?$_GET['uid']:null;
9 |
10 | $url = 'http://tp2.sinaimg.cn/'.$uid.'/180/'.time().'/1';
11 | $imgurl = get_redirect_url($url, 'https://weibo.com/');
12 | if($imgurl){
13 | ob_clean();
14 | $seconds_to_cache = 3600*24*7;
15 | header("Pragma: cache");
16 | header("Cache-Control: max-age=$seconds_to_cache");
17 | header("Content-Type: image/jpeg");
18 | echo get_curl($imgurl, 0, 'https://weibo.com/');
19 | }
20 | }
--------------------------------------------------------------------------------
/admin/head.php:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 |
73 |
74 |
--------------------------------------------------------------------------------
/admin/imghost.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
6 | ?>
7 |
19 |
20 |
21 |
22 |
23 | 微博图床
24 |
25 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/admin/index.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
6 |
7 | $count1 = $DB->getColumn("SELECT count(*) from weiboapi_account");
8 | $count2 = $DB->getColumn("SELECT count(*) from weiboapi_account WHERE status=1");
9 | $checktime = $conf['checktime'];
10 | if(!$checktime) $checktime = '未运行';
11 | $mysqlversion=$DB->getColumn("select VERSION()");
12 |
13 | ?>
14 |
15 |
16 |
17 |
后台管理首页
18 |
19 |
账号数量: 共有 个微博账号,其中正常的有 个
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
服务器信息
28 |
29 |
30 |
31 | PHP 版本:
32 |
33 |
34 | MySQL 版本:
35 |
36 |
37 | WEB 软件:
38 |
39 |
40 | 操作系统:
41 |
42 |
43 | 服务器时间:
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/admin/list.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
6 | ?>
7 |
15 |
16 |
17 | getColumn("SELECT count(*) from weiboapi_account WHERE{$sql}");
22 | $con='包含 '.$_GET['kw'].' 的共有
'.$numrows.' 个记录';
23 | $link='&my=search&kw='.$_GET['kw'];
24 | }else{
25 | $numrows=$DB->getColumn("SELECT count(*) from weiboapi_account WHERE 1");
26 | $sql=" 1";
27 | $con='本站共有
'.$numrows.' 个账号';
28 | }
29 |
30 | echo '
';
37 | echo $con;
38 | ?>
39 |
40 |
41 | ID 头像 UID 昵称 更新时间 上次使用 状态 操作
42 |
43 | query("SELECT * FROM weiboapi_account WHERE{$sql} order by id desc limit $offset,$pagesize");
50 | while($res = $rs->fetch())
51 | {
52 | $avatar = './download.php?mod=faceimg&uid='.$res['uid'];
53 | echo ''.$res['id'].' '.$res['uid'].' '.$res['nickname'].' '.$res['refreshtime'].' '.$res['usetime'].' '.($res['status']==1?'正常 ':'离线 ').' 更新 检测 日志 删除 ';
54 | }
55 | ?>
56 |
57 |
58 |
59 | ';
61 | $first=1;
62 | $prev=$page-1;
63 | $next=$page+1;
64 | $last=$pages;
65 | if ($page>1)
66 | {
67 | echo '
首页 ';
68 | echo '
« ';
69 | } else {
70 | echo '
首页 ';
71 | echo '
« ';
72 | }
73 | $start=$page-10>1?$page-10:1;
74 | $end=$page+10<$pages?$page+10:$pages;
75 | for ($i=$start;$i<$page;$i++)
76 | echo '
'.$i .' ';
77 | echo '
'.$page.' ';
78 | for ($i=$page+1;$i<=$end;$i++)
79 | echo '
'.$i .' ';
80 | echo '';
81 | if ($page<$pages)
82 | {
83 | echo '
» ';
84 | echo '
尾页 ';
85 | } else {
86 | echo '
» ';
87 | echo '
尾页 ';
88 | }
89 | echo '';
90 | ?>
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/admin/log.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
6 | ?>
7 |
8 |
9 | getColumn("SELECT count(*) from weiboapi_log A LEFT JOIN weiboapi_account B ON A.aid=B.id WHERE{$sql}");
18 |
19 | ?>
20 |
21 |
22 | ID UID 昵称 操作类型 时间
23 |
24 | query("SELECT A.*,B.uid,B.nickname FROM weiboapi_log A LEFT JOIN weiboapi_account B ON A.aid=B.id WHERE{$sql} order by A.id desc limit $offset,$pagesize");
31 | while($res = $rs->fetch())
32 | {
33 | echo ''.$res['id'].' '.$res['uid'].' '.$res['nickname'].' '.$res['action'].' '.$res['time'].' ';
34 | }
35 | ?>
36 |
37 |
38 |
39 | ';
41 | $first=1;
42 | $prev=$page-1;
43 | $next=$page+1;
44 | $last=$pages;
45 | if ($page>1)
46 | {
47 | echo '
首页 ';
48 | echo '
« ';
49 | } else {
50 | echo '
首页 ';
51 | echo '
« ';
52 | }
53 | $start=$page-10>1?$page-10:1;
54 | $end=$page+10<$pages?$page+10:$pages;
55 | for ($i=$start;$i<$page;$i++)
56 | echo '
'.$i .' ';
57 | echo '
'.$page.' ';
58 | for ($i=$page+1;$i<=$end;$i++)
59 | echo '
'.$i .' ';
60 | echo '';
61 | if ($page<$pages)
62 | {
63 | echo '
» ';
64 | echo '
尾页 ';
65 | } else {
66 | echo '
» ';
67 | echo '
尾页 ';
68 | }
69 | echo'';
70 | #分页
71 | ?>
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/admin/login.php:
--------------------------------------------------------------------------------
1 | alert('登陆后台管理成功!');window.location.href='./';");
15 | }else{
16 | @header('Content-Type: text/html; charset=UTF-8');
17 | exit("");
18 | }
19 | }elseif(isset($_GET['logout'])){
20 | setcookie("admin_token", "", time() - 604800);
21 | @header('Content-Type: text/html; charset=UTF-8');
22 | exit("");
23 | }elseif($islogin==1){
24 | exit("");
25 | }
26 | $title='用户登录';
27 | include './head.php';
28 | ?>
29 |
30 |
48 |
49 |
--------------------------------------------------------------------------------
/admin/set.php:
--------------------------------------------------------------------------------
1 | window.location.href='./login.php';");
9 | ?>
10 |
11 |
12 |
15 |
19 |
20 |
计划任务说明
21 |
22 |
定时执行计划任务可实现COOKIE检测与保活,避免频繁重复登录。
将以下命令添加到计划任务定时执行,频率:1分钟1次
23 |
php cron.php
24 |
25 |
26 |
29 |
60 |
来自:'.$siteurl);
65 | if($result==1)
66 | showmsg('邮件发送成功!',1);
67 | else
68 | showmsg('邮件发送失败!'.$result,3);
69 | }
70 | else
71 | showmsg('您还未设置邮箱!',3);
72 | }elseif($mod=='notice'){
73 | ?>
74 |
75 |
邮件提醒设置
76 |
128 |
132 |
133 |
144 |
161 |
162 |
管理员账号设置
163 |
187 |
188 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/api.php:
--------------------------------------------------------------------------------
1 | find('account', '*', ['uid'=>$uid]);
19 | if(!$account) exit('{"code":-1,"msg":"微博账号不存在"}');
20 | if($account['status']!=1) exit('{"code":-1,"msg":"微博账号状态不正常"}');
21 | $uid = $account['uid'];
22 | $nickname = $account['nickname'];
23 | $cookie = $account['cookie_weibo'];
24 | }else{
25 | $account = $DB->getRow("SELECT * FROM weiboapi_account WHERE `status`=1 ORDER BY usetime ASC LIMIT 1");
26 | if(!$account) exit('{"code":-1,"msg":"暂无可用的微博账号"}');
27 | $uid = $account['uid'];
28 | $nickname = $account['nickname'];
29 | $cookie = $account['cookie_weibo'];
30 | }
31 | exit(json_encode(['code'=>0, 'uid'=>$uid, 'nickname'=>$nickname, 'cookie'=>$cookie]));
32 | break;
33 | case 'gethotsearch': //获取热搜列表
34 | if($key !== $conf['apikey'])exit('{"code":-1,"msg":"密钥错误"}');
35 | $result = weibotool_call('hotline', [], 60);
36 | exit(json_encode($result));
37 | break;
38 | case 'parsevideo': //解析微博视频
39 | $oid = isset($_POST['oid'])?trim($_POST['oid']):exit('{"code":-1,"msg":"视频ID不能为空"}');
40 | if($key !== $conf['apikey'])exit('{"code":-1,"msg":"密钥错误"}');
41 | $result = weibotool_call('parseVideo', [$oid], 3600);
42 | exit(json_encode($result));
43 | break;
44 | case 'getuserinfo': //获取用户信息
45 | $uid = isset($_POST['uid'])?trim($_POST['uid']):exit('{"code":-1,"msg":"用户ID不能为空"}');
46 | if($key !== $conf['apikey'])exit('{"code":-1,"msg":"密钥错误"}');
47 | $result = weibotool_call('getUserInfo', [$uid], 3600);
48 | exit(json_encode($result));
49 | break;
50 | default:
51 | exit('{"code":-4,"msg":"No Act"}');
52 | break;
53 | }
--------------------------------------------------------------------------------
/config.php:
--------------------------------------------------------------------------------
1 | 'localhost', //数据库服务器
5 | 'port' => 3306, //数据库端口
6 | 'user' => '', //数据库用户名
7 | 'pwd' => '', //数据库密码
8 | 'dbname' => '', //数据库名
9 | 'prefix' => 'weiboapi_' //数据表前缀
10 | );
11 |
--------------------------------------------------------------------------------
/cron.php:
--------------------------------------------------------------------------------
1 | getAll("SELECT * FROM weiboapi_account WHERE status=1 AND (checktime<'$checktime' OR checktime IS NULL) ORDER BY checktime ASC");
11 | if(count($list) == 0) exit("[OK] 暂无需要更新的COOKIE\n");
12 | foreach($list as $row){
13 | $nickname = $row['nickname'];
14 | $rescode = \lib\Logic::checkAccount($row['id']);
15 | if($rescode == 2){
16 | echo "[OK] {$nickname} 账号COOKIE更新成功\n";
17 | }elseif($rescode == 1){
18 | echo "[OK] {$nickname} 账号状态检测正常\n";
19 | }else{
20 | echo "[Warn] {$nickname} 账号状态已失效\n";
21 | }
22 | }
23 |
24 | if($conf['cache_time'] > 0 && $conf['cache_clean']!=date('Ymd')){
25 | $DB->exec("TRUNCATE TABLE `weiboapi_cache`");
26 | saveSetting('cache_clean', date('Ymd'));
27 | echo '[OK] 清空查询缓存成功!'."\n";
28 | }
29 |
30 | saveSetting('checktime', date("Y-m-d H:i:s"));
31 |
32 | echo '[OK] '.date("Y-m-d H:i:s")."\n";
33 |
--------------------------------------------------------------------------------
/includes/autoloader.php:
--------------------------------------------------------------------------------
1 | 点此安装';
19 | exit();
20 | }
21 |
22 | include_once(SYSTEM_ROOT."autoloader.php");
23 | Autoloader::register();
24 |
25 | $DB = new \lib\PdoHelper($dbconfig);
26 |
27 | if($DB->query("select * from weiboapi_config where 1")==FALSE)
28 | {
29 | header('Content-type:text/html;charset=utf-8');
30 | echo '你还没安装!
点此安装 ';
31 | exit();
32 | }
33 |
34 | $conf = [];
35 | $result = $DB->getAll("SELECT * FROM weiboapi_config");
36 | foreach($result as $row){
37 | $conf[$row['k']] = $row['v'];
38 | }
39 | unset($result);
40 |
41 | define('SYS_KEY', $conf['syskey']);
42 | $password_hash='!@#%!s!0';
43 |
44 | include_once(SYSTEM_ROOT."functions.php");
45 |
46 | $scriptpath=str_replace('\\','/',$_SERVER['SCRIPT_NAME']);
47 | $sitepath = substr($scriptpath, 0, strrpos($scriptpath, '/'));
48 | $siteurl = (is_https() ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$sitepath.'/';
49 |
50 | $clientip=real_ip($conf['ip_type']?$conf['ip_type']:0);
51 | if(isset($_COOKIE["admin_token"]))
52 | {
53 | $token=authcode(daddslashes($_COOKIE['admin_token']), 'DECODE', SYS_KEY);
54 | if($token){
55 | list($user, $sid) = explode("\t", $token);
56 | $session=md5($conf['admin_user'].$conf['admin_pwd'].$password_hash);
57 | if($session===$sid) {
58 | $islogin=1;
59 | }
60 | }
61 | }
62 |
63 | if (!file_exists(ROOT.'install/install.lock') && file_exists(ROOT.'install/index.php')) {
64 | sysmsg('
检测到无 install.lock 文件 如果您尚未安装本程序,请前往安装 如果您已经安装本程序,请手动放置一个空的 install.lock 文件到 /install 文件夹下,为了您站点安全,在您完成它之前我们不会工作。 为什么必须建立 install.lock 文件? 它是安装保护文件,如果检测不到它,就会认为站点还没安装,此时任何人都可以安装/重装你的网站。
');exit;
65 | }
66 |
--------------------------------------------------------------------------------
/includes/functions.php:
--------------------------------------------------------------------------------
1 | =1 && isset($_SERVER['HTTP_CF_CONNECTING_IP']) && filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
44 | $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
45 | } elseif ($type>=1 && isset($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
46 | $ip = $_SERVER['HTTP_X_REAL_IP'];
47 | }
48 | return $ip;
49 | }
50 | function get_ip_city($ip)
51 | {
52 | $url = 'http://whois.pconline.com.cn/ipJson.jsp?json=true&ip=';
53 | $city = get_curl($url . $ip);
54 | $city = mb_convert_encoding($city, "UTF-8", "GB2312");
55 | $city = json_decode($city, true);
56 | if ($city['city']) {
57 | $location = $city['pro'].$city['city'];
58 | } else {
59 | $location = $city['pro'];
60 | }
61 | if($location){
62 | return $location;
63 | }else{
64 | return false;
65 | }
66 | }
67 | function daddslashes($string) {
68 | if(is_array($string)) {
69 | foreach($string as $key => $val) {
70 | $string[$key] = daddslashes($val);
71 | }
72 | } else {
73 | $string = addslashes($string);
74 | }
75 | return $string;
76 | }
77 |
78 | function strexists($string, $find) {
79 | return !(strpos($string, $find) === FALSE);
80 | }
81 |
82 | function dstrpos($string, $arr) {
83 | if(empty($string)) return false;
84 | foreach((array)$arr as $v) {
85 | if(strpos($string, $v) !== false) {
86 | return true;
87 | }
88 | }
89 | return false;
90 | }
91 |
92 | function checkmobile() {
93 | $useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
94 | $ualist = array('android', 'midp', 'nokia', 'mobile', 'iphone', 'ipod', 'blackberry', 'windows phone');
95 | if((dstrpos($useragent, $ualist) || strexists($_SERVER['HTTP_ACCEPT'], "VND.WAP") || strexists($_SERVER['HTTP_VIA'],"wap")))
96 | return true;
97 | else
98 | return false;
99 | }
100 | function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
101 | $ckey_length = 4;
102 | $key = md5($key);
103 | $keya = md5(substr($key, 0, 16));
104 | $keyb = md5(substr($key, 16, 16));
105 | $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
106 | $cryptkey = $keya.md5($keya.$keyc);
107 | $key_length = strlen($cryptkey);
108 | $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
109 | $string_length = strlen($string);
110 | $result = '';
111 | $box = range(0, 255);
112 | $rndkey = array();
113 | for($i = 0; $i <= 255; $i++) {
114 | $rndkey[$i] = ord($cryptkey[$i % $key_length]);
115 | }
116 | for($j = $i = 0; $i < 256; $i++) {
117 | $j = ($j + $box[$i] + $rndkey[$i]) % 256;
118 | $tmp = $box[$i];
119 | $box[$i] = $box[$j];
120 | $box[$j] = $tmp;
121 | }
122 | for($a = $j = $i = 0; $i < $string_length; $i++) {
123 | $a = ($a + 1) % 256;
124 | $j = ($j + $box[$a]) % 256;
125 | $tmp = $box[$a];
126 | $box[$a] = $box[$j];
127 | $box[$j] = $tmp;
128 | $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
129 | }
130 | if($operation == 'DECODE') {
131 | if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
132 | return substr($result, 26);
133 | } else {
134 | return '';
135 | }
136 | } else {
137 | return $keyc.str_replace('=', '', base64_encode($result));
138 | }
139 | }
140 |
141 | function random($length, $numeric = 0) {
142 | $seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
143 | $seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
144 | $hash = '';
145 | $max = strlen($seed) - 1;
146 | for($i = 0; $i < $length; $i++) {
147 | $hash .= $seed[mt_rand(0, $max)];
148 | }
149 | return $hash;
150 | }
151 | function showmsg($content = '未知的异常',$type = 4,$back = false)
152 | {
153 | switch($type)
154 | {
155 | case 1:
156 | $panel="success";
157 | break;
158 | case 2:
159 | $panel="info";
160 | break;
161 | case 3:
162 | $panel="warning";
163 | break;
164 | case 4:
165 | $panel="danger";
166 | break;
167 | }
168 |
169 | echo '
170 |
171 |
提示信息
172 |
173 |
';
174 | echo $content;
175 |
176 | if ($back) {
177 | echo '
<< 返回上一页 ';
178 | }
179 | else
180 | echo '
<< 返回上一页 ';
181 |
182 | echo '
183 |
';
184 | exit;
185 | }
186 | function sysmsg($msg = '未知的异常',$title = '站点提示信息') {
187 | ?>
188 |
189 |
190 |
191 |
192 |
193 |
194 |
197 |
198 |
199 | '.$title.'';
200 | echo $msg; ?>
201 |
202 |
203 | 0){
256 | return substr($str, $start, $right-$start);
257 | }else{
258 | return substr($str, $start);
259 | }
260 | }
261 |
262 | function send_mail($to, $sub, $msg) {
263 | global $conf;
264 | if($conf['mail_cloud']==1){
265 | $mail = new \lib\mail\Sendcloud($conf['mail_apiuser'], $conf['mail_apikey']);
266 | return $mail->send($to, $sub, $msg, $conf['mail_name2'], $conf['sitename']);
267 | }elseif($conf['mail_cloud']==2){
268 | try{
269 | $mail = new \lib\mail\Aliyun($conf['mail_apiuser'], $conf['mail_apikey']);
270 | return $mail->send($to, $sub, $msg, $conf['mail_name2'], $conf['sitename']);
271 | } catch (Exception $e) {
272 | return $e->getMessage();
273 | }
274 | }else{
275 | if(!$conf['mail_name'] || !$conf['mail_port'] || !$conf['mail_smtp'] || !$conf['mail_pwd'])return false;
276 | $port = intval($conf['mail_port']);
277 | $mail = new \lib\mail\PHPMailer\PHPMailer(true);
278 | try{
279 | $mail->SMTPDebug = 0;
280 | $mail->CharSet = 'UTF-8';
281 | $mail->Timeout = 5;
282 | $mail->isSMTP();
283 | $mail->Host = $conf['mail_smtp'];
284 | $mail->SMTPAuth = true;
285 | $mail->Username = $conf['mail_name'];
286 | $mail->Password = $conf['mail_pwd'];
287 | if($port == 587) $mail->SMTPSecure = 'tls';
288 | else if($port >= 465) $mail->SMTPSecure = 'ssl';
289 | else $mail->SMTPAutoTLS = false;
290 | $mail->Port = intval($conf['mail_port']);
291 | $mail->setFrom($conf['mail_name'], $conf['sitename']);
292 | $mail->addAddress($to);
293 | $mail->addReplyTo($conf['mail_name'], $conf['sitename']);
294 | $mail->isHTML(true);
295 | $mail->Subject = $sub;
296 | $mail->Body = $msg;
297 | $mail->send();
298 | return true;
299 | } catch (Exception $e) {
300 | return $mail->ErrorInfo;
301 | }
302 | }
303 | }
304 |
305 | function jsonp_decode($jsonp, $assoc = false)
306 | {
307 | $jsonp = trim($jsonp);
308 | if(isset($jsonp[0]) && $jsonp[0] !== '[' && $jsonp[0] !== '{') {
309 | $begin = strpos($jsonp, '(');
310 | if(false !== $begin)
311 | {
312 | $end = strrpos($jsonp, ')');
313 | if(false !== $end)
314 | {
315 | $jsonp = substr($jsonp, $begin + 1, $end - $begin - 1);
316 | }
317 | }
318 | }
319 | return json_decode($jsonp, $assoc);
320 | }
321 |
322 | function getSetting($k){
323 | global $DB;
324 | return $DB->getColumn("SELECT v FROM weiboapi_config WHERE k=:k LIMIT 1", [':k'=>$k]);
325 | }
326 | function saveSetting($k, $v){
327 | global $DB;
328 | return $DB->exec("REPLACE INTO weiboapi_config SET v=:v,k=:k", [':v'=>$v, ':k'=>$k]);
329 | }
330 |
331 | function weibotool_call_nocache($func, $args, $retry = 2){
332 | global $DB;
333 | $retry--;
334 | $row = $DB->getRow("SELECT * FROM weiboapi_account WHERE `status`=1 ORDER BY usetime ASC LIMIT 1");
335 | if($row){
336 | $DB->update('account', ['usetime'=>'NOW()'], ['id'=>$row['id']]);
337 | $tool = new \lib\WeiboTool($row['cookie_weibo']);
338 | $result = call_user_func_array([$tool, $func], $args);
339 | if($tool->cookiefail){
340 | \lib\Logic::checkAccount($row['id']);
341 | if($retry > 0){
342 | $result = weibotool_call_nocache($func, $args, $retry);
343 | }
344 | }
345 | }else{
346 | $result = ['code'=>-1, 'subcode'=>201, 'msg'=>'暂无可用的微博账号,请稍后再试'];
347 | }
348 | return $result;
349 | }
350 |
351 | function weibotool_call($func, $args, $cachetime = 0, $retry = 2){
352 | global $DB;
353 | if($cachetime > 0){
354 | $cache_key = md5($func.','.implode(',', $args));
355 | $cache = $DB->find('cache', '*', ['key'=>$cache_key]);
356 | if($cache && time() - $cache['time'] < $cachetime){
357 | $result = json_decode($cache['data'], true);
358 | $result['from'] = 'cache';
359 | return $result;
360 | }
361 | }
362 | $result = weibotool_call_nocache($func, $args, $retry);
363 | if(isset($result['code']) && $result['code'] == 0 && $cachetime > 0){
364 | $DB->exec("INSERT INTO `weiboapi_cache` (`key`,`data`,`time`) VALUES (:rkey, :rdata, :rtime) on duplicate key update `data`=:rdata,`time`=:rtime", [':rkey'=>$cache_key, ':rdata'=>json_encode($result), ':rtime'=>time()]);
365 | $result['from'] = 'online';
366 | }
367 | return $result;
368 | }
369 |
370 | function get_redirect_url($url, $referer = null){
371 | $url = $url;
372 | $ch=curl_init($url);
373 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
374 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
375 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
376 | curl_setopt($ch, CURLOPT_HEADER, false);
377 | if($referer){
378 | curl_setopt($ch, CURLOPT_REFERER, $referer);
379 | }
380 | curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36');
381 | curl_setopt($ch, CURLOPT_TIMEOUT, 4);
382 | curl_exec($ch);
383 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
384 | if($httpCode == 301 || $httpCode == 302){
385 | $redirect_url = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
386 | }
387 | curl_close($ch);
388 | return $redirect_url;
389 | }
--------------------------------------------------------------------------------
/includes/lib/Logic.php:
--------------------------------------------------------------------------------
1 | $v){
15 | $cookie_login .= $k.'='.$v.'; ';
16 | }
17 | $cookie_login = substr($cookie_login, 0, -2);
18 |
19 | $cookie_weibo = '';
20 | foreach($array['wbcookie'] as $k=>$v){
21 | $cookie_weibo .= $k.'='.$v.'; ';
22 | }
23 | $cookie_weibo = substr($cookie_weibo, 0, -2);
24 |
25 | $data = ['nickname'=>$array['nick'], 'cookie_login'=>$cookie_login, 'cookie_weibo'=>$cookie_weibo, 'refreshtime'=>'NOW()', 'status'=>'1'];
26 | if($_POST['user']){
27 | $data['loginname'] = $_POST['user'];
28 | }
29 |
30 | $aid = $DB->findColumn('account', 'id', ['uid'=>$array['uid']]);
31 |
32 | if($aid){
33 | $DB->update('account', $data, ['id'=>$aid]);
34 | $DB->insert('log', ['aid'=>$aid, 'action'=>'更新账号', 'time'=>'NOW()']);
35 | }else{
36 | $data['uid'] = $array['uid'];
37 | $data['addtime'] = 'NOW()';
38 | $aid = $DB->insert('account', $data);
39 | $DB->insert('log', ['aid'=>$aid, 'action'=>'添加账号', 'time'=>'NOW()']);
40 | }
41 | }
42 |
43 | //检测账号状态
44 | public static function checkAccount($id){
45 | global $DB,$conf;
46 | $row = $DB->find('account', '*', ['id'=>$id]);
47 | if(!$row) throw new Exception('账号不存在');
48 | if($row['status'] == 0) return 0;
49 |
50 | $DB->update('account', ['checktime'=>'NOW()'], ['id'=>$id]);
51 |
52 | $tool = new WeiboTool($row['cookie_weibo']);
53 | if($tool->checkCookie()){
54 | return 1;
55 | }else{
56 | $login = new WeiboLogin();
57 | $cookie=[];
58 | $rows = explode(';', $row['cookie_login']);
59 | foreach ($rows as $val) {
60 | $val = trim($val);
61 | if(empty($val)) continue;
62 | $key = substr($val, 0, strpos($val, '='));
63 | $cookie[$key]=substr($val, strpos($val, '=')+1);
64 | }
65 | $array = $login->cookielogin($cookie);
66 | if($array['code'] == 0){
67 | self::addAccount($array);
68 | return 2;
69 | }else{
70 | $DB->update('account', ['status'=>0], ['id'=>$id]);
71 | if($conf['mail_open'] == 1 && defined('IS_CRON')){
72 | self::noticeFail($row);
73 | }
74 | return 0;
75 | }
76 | }
77 | }
78 |
79 | //账号状态失效通知
80 | private static function noticeFail($account){
81 | global $DB,$conf;
82 | $mail_name = $conf['mail_recv']?$conf['mail_recv']:$conf['mail_name'];
83 | $mail_title = '微博账号:'.$account['nickname'].' 失效提醒';
84 | $mail_content = '你在'.$conf['sitename'].'添加的微博账号:'.$account['nickname'].'(UID:'.$account['uid'].')已失效,请及时更新!
'.date("Y-m-d H:i:s").'
';
85 | send_mail($mail_name,$mail_title,$mail_content);
86 | }
87 | }
--------------------------------------------------------------------------------
/includes/lib/PdoHelper.php:
--------------------------------------------------------------------------------
1 | prefix = $dbconfig['prefix'];
20 | try {
21 | $this->db = new \PDO("mysql:host={$dbconfig['host']};dbname={$dbconfig['dbname']};port={$dbconfig['port']}",$dbconfig['user'],$dbconfig['pwd']);
22 | } catch (\Exception $e) {
23 | exit('链接数据库失败:' . $e->getMessage());
24 | }
25 | $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT);
26 | $this->db->exec("set sql_mode = ''");
27 | $this->db->exec("set names utf8mb4");
28 | }
29 |
30 | /**
31 | * 设置结果集方式
32 | *
33 | * @param string $_style
34 | */
35 | public function setFetchStyle($_style)
36 | {
37 | $this->fetchStyle = $_style;
38 | }
39 |
40 | /**
41 | * 替换数据表前缀
42 | * @param $_sql
43 | *
44 | * @return mixed
45 | */
46 | private function dealPrefix($_sql){
47 | return $_sql;
48 | }
49 |
50 | private function _where($conditions){
51 | $result = array( "_where" => " ","_bindParams" => array());
52 | if(is_array($conditions) && !empty($conditions)){
53 | $fieldss = array(); $sql = null; $join = array();
54 | if(isset($conditions[0]) && $sql = $conditions[0]) unset($conditions[0]);
55 | foreach( $conditions as $key => $condition ){
56 | if(substr($key, 0, 1) != ":"){
57 | unset($conditions[$key]);
58 | $conditions[":".$key] = $condition;
59 | }
60 | $join[] = "`{$key}` = :{$key}";
61 | }
62 | if(!$sql) $sql = join(" AND ",$join);
63 |
64 | $result["_where"] = " WHERE ". $sql;
65 | $result["_bindParams"] = $conditions;
66 | }elseif(!empty($conditions)){
67 | $result["_where"] = " WHERE ". $conditions;
68 | }
69 | return $result;
70 | }
71 |
72 | private function _select($table, $fields = '*', $where = array(), $sort = null, $limit = null){
73 | $sort = !empty($sort) ? ' ORDER BY '.$sort : '';
74 | $fields = !empty($fields) ? $fields : '*';
75 | if(is_array($fields)){
76 | $fields = implode(',',$fields);
77 | }
78 | $conditions = $this->_where($where);
79 |
80 | $sql = ' FROM '.$this->prefix.$table.$conditions["_where"];
81 | if(is_array($limit)){
82 | $limit = ' LIMIT '.$limit[0].','.$limit[1];
83 | }elseif(!empty($limit)){
84 | $limit = ' LIMIT '.$limit;
85 | }else{
86 | $limit = '';
87 | }
88 | return array('sql'=>'SELECT '. $fields . $sql . $sort . $limit, 'bind'=>$conditions["_bindParams"]);
89 | }
90 |
91 | /**
92 | * 查询一条数据
93 | * @param string $table
94 | * @param string $fields
95 | * @param array $where
96 | * @param string $sort
97 | * @param int $limit
98 | *
99 | * @return array
100 | */
101 | public function find($table, $fields = '*', $where = array(), $sort = null, $limit = null){
102 | $sql_arr = $this->_select($table, $fields, $where, $sort, $limit);
103 | return $this->getRow($sql_arr['sql'], $sql_arr['bind']);
104 | }
105 |
106 | /**
107 | * 查询全部数据
108 | * @param string $table
109 | * @param string $fields
110 | * @param array $where
111 | * @param string $sort
112 | * @param int $limit
113 | *
114 | * @return array
115 | */
116 | public function findAll($table, $fields = '*', $where = array(), $sort = null, $limit = null){
117 | $sql_arr = $this->_select($table, $fields, $where, $sort, $limit);
118 | return $this->getAll($sql_arr['sql'], $sql_arr['bind']);
119 | }
120 |
121 | /**
122 | * 查询字段数据
123 | * @param string $table
124 | * @param string $fields
125 | * @param array $where
126 | * @param string $sort
127 | *
128 | * @return mixed
129 | */
130 | public function findColumn($table, $fields, $where = array(), $sort = null){
131 | $sql_arr = $this->_select($table, $fields, $where, $sort, 1);
132 | return $this->getColumn($sql_arr['sql'], $sql_arr['bind']);
133 | }
134 |
135 | /**
136 | * 插入数据
137 | * @param string $table
138 | * @param array $data
139 | *
140 | * @return int
141 | */
142 | public function insert($table, $data){
143 | $values = array();
144 | foreach ($data as $k=>$v){
145 | $keys[] = "`{$k}`";
146 | if ($v == 'NOW()' || $v == 'CURDATE()' || $v == 'CURTIME()') {
147 | $marks[] = $v;
148 | }elseif ($v == '') {
149 | $marks[] = 'NULL';
150 | }else{
151 | $values[":".$k] = $v;
152 | $marks[] = ":".$k;
153 | }
154 | }
155 | $rowCount = $this->exec("INSERT INTO ".$this->prefix.$table." (".implode(', ', $keys).") VALUES (".implode(', ', $marks).")", $values);
156 | if($rowCount){
157 | return $this->lastInsertId();
158 | }else{
159 | return false;
160 | }
161 | }
162 |
163 | /**
164 | * 更新数据
165 | * @param string $table
166 | * @param array $data
167 | * @param array $where
168 | *
169 | * @return int
170 | */
171 | public function update($table, $data, $where){
172 | if(is_array($data) && !empty($data)){
173 | $values = array();
174 | foreach ($data as $k=>$v){
175 | if($v == 'NOW()' || $v == 'CURDATE()' || $v == 'CURTIME()'){
176 | $setstr[] = "`{$k}` = ".$v;
177 | }elseif($v == ''){
178 | $setstr[] = "`{$k}` = NULL";
179 | }else{
180 | $values[":M_UPDATE_".$k] = $v;
181 | $setstr[] = "`{$k}` = :M_UPDATE_".$k;
182 | }
183 | }
184 | $update = implode(', ', $setstr);
185 | }elseif(!empty($data)){
186 | $update = $data;
187 | }else{
188 | return false;
189 | }
190 | $conditions = $this->_where($where);
191 | $rowCount = $this->exec("UPDATE ".$this->prefix.$table." SET ".$update.$conditions["_where"], $conditions["_bindParams"] + $values);
192 | return $rowCount;
193 | }
194 |
195 | /**
196 | * 删除数据
197 | * @param string $table
198 | * @param array $where
199 | *
200 | * @return int
201 | */
202 | public function delete($table, $where){
203 | $conditions = $this->_where($where);
204 | $rowCount = $this->exec("DELETE FROM ".$this->prefix.$table.$conditions["_where"], $conditions["_bindParams"]);
205 | return $rowCount;
206 | }
207 |
208 | /**
209 | * 统计行数
210 | * @param string $table
211 | * @param array $where
212 | *
213 | * @return int
214 | */
215 | public function count($table, $where){
216 | $conditions = $this->_where($where);
217 | $count = $this->getColumn("SELECT COUNT(*) FROM ".$this->prefix.$table.$conditions["_where"], $conditions["_bindParams"]);
218 | return $count;
219 | }
220 |
221 |
222 | /**
223 | * 执行语句
224 | * @param string $_sql
225 | * @param array $_array
226 | *
227 | * @return int|bool
228 | */
229 | public function exec($_sql, $_array = null)
230 | {
231 | $_sql = $this->dealPrefix($_sql);
232 | if (is_array($_array)) {
233 | $stmt = $this->db->prepare($_sql);
234 | if($stmt) {
235 | $result = $stmt->execute($_array);
236 | if($result!==false){
237 | return $result;
238 | }else{
239 | $this->errorInfo = $stmt->errorInfo();
240 | return false;
241 | }
242 | }else{
243 | $this->errorInfo = $this->db->errorInfo();
244 | return false;
245 | }
246 | } else {
247 | $result = $this->db->exec($_sql);
248 | if($result!==false){
249 | return $result;
250 | }else{
251 | $this->errorInfo = $this->db->errorInfo();
252 | return false;
253 | }
254 | }
255 | }
256 |
257 | /**
258 | * 获取PDOStatement
259 | * @param string $_sql
260 | * @param array $_array
261 | *
262 | * @return \PDOStatement
263 | */
264 | public function query($_sql, $_array = null)
265 | {
266 | $_sql = $this->dealPrefix($_sql);
267 | if (is_array($_array)) {
268 | $stmt = $this->db->prepare($_sql);
269 | if($stmt) {
270 | if($stmt->execute($_array)){
271 | return $stmt;
272 | }else{
273 | $this->errorInfo = $stmt->errorInfo();
274 | return false;
275 | }
276 | }else{
277 | $this->errorInfo = $this->db->errorInfo();
278 | return false;
279 | }
280 | } else {
281 | if($stmt = $this->db->query($_sql)){
282 | return $stmt;
283 | }else{
284 | $this->errorInfo = $this->db->errorInfo();
285 | return false;
286 | }
287 | }
288 | }
289 |
290 | /**
291 | * 查询一条结果
292 | *
293 | * @param string $_sql string
294 | * @param array $_array array
295 | *
296 | * @return mixed
297 | */
298 | public function getRow($_sql, $_array = null)
299 | {
300 | $stmt = $this->query($_sql, $_array);
301 | if($stmt) {
302 | return $stmt->fetch($this->fetchStyle);
303 | }else{
304 | return false;
305 | }
306 | }
307 |
308 | /**
309 | * 获取所有结果
310 | *
311 | * @param string $_sql
312 | * @param array $_array
313 | *
314 | * @return array
315 | */
316 | public function getAll($_sql, $_array = null)
317 | {
318 | $stmt = $this->query($_sql, $_array);
319 | if($stmt) {
320 | return $stmt->fetchAll($this->fetchStyle);
321 | }else{
322 | return false;
323 | }
324 | }
325 |
326 | /**
327 | * 获取结果数
328 | * @param string $_sql
329 | * @param array $_array
330 | *
331 | * @return int
332 | */
333 | public function getCount($_sql, $_array = null)
334 | {
335 | $stmt = $this->query($_sql, $_array);
336 | if($stmt) {
337 | return $stmt->rowCount();
338 | }else{
339 | return false;
340 | }
341 | }
342 |
343 | /**
344 | * 获取一个字段值
345 | * @param string $_sql
346 | * @param array $_array
347 | *
348 | * @return int
349 | */
350 | public function getColumn($_sql, $_array = null)
351 | {
352 | $stmt = $this->query($_sql, $_array);
353 | if($stmt) {
354 | return $stmt->fetchColumn();
355 | }else{
356 | return false;
357 | }
358 | }
359 |
360 | /**
361 | * 返回最后插入行的ID
362 | *
363 | * @return int|\PDOStatement
364 | */
365 | public function lastInsertId()
366 | {
367 | return $this->db->lastInsertId();
368 | }
369 |
370 | /**
371 | * 返回错误信息
372 | *
373 | * @return string|\PDOStatement
374 | */
375 | public function error()
376 | {
377 | $error = $this->errorInfo;
378 | if($error){
379 | return '['.$error[1].']'.$error[2];
380 | }else{
381 | return null;
382 | }
383 | }
384 |
385 | //开启事务
386 | public function beginTransaction()
387 | {
388 | return $this->db->beginTransaction();
389 | }
390 |
391 | //提交事务
392 | public function commit()
393 | {
394 | return $this->db->commit();
395 | }
396 |
397 | //回滚事务
398 | public function rollBack()
399 | {
400 | return $this->db->rollBack();
401 | }
402 |
403 | function __get($name)
404 | {
405 | return $this->$name;
406 | }
407 |
408 | function __destruct()
409 | {
410 | $this->db = null;
411 | }
412 |
413 |
414 | }
--------------------------------------------------------------------------------
/includes/lib/WeiboLogin.php:
--------------------------------------------------------------------------------
1 | useragent = $_SERVER['HTTP_USER_AGENT'];
13 | }
14 |
15 | private function jsonp_decode($jsonp, $assoc = false)
16 | {
17 | $jsonp = trim($jsonp);
18 | if (isset($jsonp[0]) && $jsonp[0] !== '[' && $jsonp[0] !== '{') {
19 | $begin = strpos($jsonp, '(');
20 | if (false !== $begin) {
21 | $end = strrpos($jsonp, ')');
22 | if (false !== $end) {
23 | $jsonp = substr($jsonp, $begin + 1, $end - $begin - 1);
24 | }
25 | }
26 | }
27 | return json_decode($jsonp, $assoc);
28 | }
29 |
30 | //获取扫码登录二维码
31 | public function getqrcode()
32 | {
33 | $url = 'https://passport.weibo.com/sso/v2/qrcode/image?entry=miniblog&size=180';
34 | $data = $this->get_curl($url, 0, $this->referrer);
35 | $arr = json_decode($data, true);
36 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
37 | $imgurl = $arr['data']['image'];
38 | parse_str(parse_url($imgurl, PHP_URL_QUERY), $query_arr);
39 | $link = $query_arr['data'];
40 | return array('code' => 0, 'imgurl' => $arr['data']['image'], 'qrid' => $arr['data']['qrid'], 'link' => $link);
41 | } elseif (isset($arr['msg'])) {
42 | return array('code' => -1, 'msg' => '获取二维码失败,' . $arr['msg']);
43 | } else {
44 | return array('code' => -1, 'msg' => '获取二维码失败');
45 | }
46 | }
47 |
48 | //扫码登录操作
49 | public function qrlogin($qrid)
50 | {
51 | if (empty($qrid)) return array('code' => -1, 'msg' => 'qrid不能为空');
52 | $url = 'https://passport.weibo.com/sso/v2/qrcode/check?entry=miniblog&source=miniblog&url=https%3A%2F%2Fweibo.com%2F&qrid='.$qrid.'&disp=popup';
53 | $data = $this->get_curl($url, 0, $this->referrer);
54 | $arr = json_decode($data, true);
55 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
56 | $login_url = $arr['data']['url'];
57 | $result = $this->login_getcookie($login_url);
58 | return $result;
59 | } elseif ($arr['retcode'] == 50114001) {
60 | return array('code' => 1, 'msg' => '请用最新版微博客户端扫码');
61 | } elseif ($arr['retcode'] == 50114002) {
62 | return array('code' => 2, 'msg' => '成功扫描,请在手机点击确认以登录');
63 | } elseif ($arr['retcode'] == 50114003 || $arr['retcode'] == 50114004) {
64 | return array('code' => 3, 'msg' => '该二维码已过期,请重新扫描');
65 | } elseif (isset($arr['msg'])) {
66 | return array('code' => -1, 'msg' => $arr['msg']);
67 | } else {
68 | return array('code' => -1, 'msg' => '登录失败,原因未知');
69 | }
70 | }
71 |
72 | //通用登录后获取cookie
73 | private function login_getcookie($url)
74 | {
75 | $host = parse_url($url, PHP_URL_HOST);
76 | $data = $this->get_curl($url, 0, $this->referrer, 0, 0, 1);
77 | if(preg_match("/Location: (.*?)\r\n/i", $data['header'], $match)){
78 | $jump_url = $match[1];
79 | if($host == 'login.sina.com.cn'){
80 | $cookie=[];
81 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
82 | foreach ($matchs[1] as $val) {
83 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
84 | $key = substr($val, 0, strpos($val, '='));
85 | $cookie[$key]=substr($val, strpos($val, '=')+1);
86 | }
87 |
88 | $wbcookie = $this->get_sso_cookie($jump_url);
89 | }else{
90 | $wbcookie=[];
91 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
92 | foreach ($matchs[1] as $val) {
93 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
94 | $key = substr($val, 0, strpos($val, '='));
95 | $wbcookie[$key]=substr($val, strpos($val, '=')+1);
96 | }
97 |
98 | $cookie = $this->get_sso_cookie($jump_url);
99 | }
100 |
101 | $info = $this->get_user_info($wbcookie);
102 |
103 | return array('code' => 0, 'cookie' => $cookie, 'wbcookie' => $wbcookie, 'uid' => $info['user']['idstr'], 'nick' => $info['user']['screen_name']);
104 | } else {
105 | return array('code' => -1, 'msg' => '登录成功,获取用户信息失败');
106 | }
107 | }
108 |
109 | private function get_user_info($wbcookie){
110 | $cookie_str = '';
111 | foreach($wbcookie as $key=>$value){
112 | $cookie_str .= $key.'='.$value.'; ';
113 | }
114 | $this->useragent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36';
115 | $data = $this->get_curl('https://weibo.com/', 0, 0, $cookie_str);
116 | preg_match('!window\.\$CONFIG = (.*?);\}!',$data,$match);
117 | return json_decode($match[1], true);
118 | }
119 |
120 | private function get_sso_cookie($jump_url){
121 | $data = $this->get_curl($jump_url, 0, $this->referrer, 0, 0, 1);
122 | $cookie=[];
123 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
124 | foreach ($matchs[1] as $val) {
125 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
126 | $key = substr($val, 0, strpos($val, '='));
127 | $cookie[$key]=substr($val, strpos($val, '=')+1);
128 | }
129 | return $cookie;
130 | }
131 |
132 | //获取登录配置
133 | public function getconfig()
134 | {
135 | $data = $this->get_curl($this->referrer, 0, 0, 0, 0, 1);
136 | if(preg_match('/X-CSRF-TOKEN=(.*?);/', $data['header'], $match)){
137 | $csrf_token = $match[1];
138 | }else{
139 | return array('code' => -1, 'msg' => 'X-CSRF-TOKEN获取失败');
140 | }
141 | $url = 'https://passport.weibo.com/sso/v2/web/config';
142 | $post = 'entry=miniblog&source=miniblog';
143 | $cookie = 'X-CSRF-TOKEN='.$csrf_token;
144 | $headers = ['X-CSRF-TOKEN: '.$csrf_token, 'X-Requested-With: XMLHttpRequest'];
145 | $data = $this->get_curl($url, $post, $this->referrer, $cookie, $headers);
146 | $arr = json_decode($data, true);
147 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
148 | return array('code' => 0, 'data' => $arr['data'], 'csrf_token' => $csrf_token);
149 | }elseif(isset($arr['msg'])){
150 | return array('code' => -1, 'msg' => '获取登录配置失败,'.$arr['msg']);
151 | }else{
152 | return array('code' => -1, 'msg' => '获取登录配置失败');
153 | }
154 | }
155 |
156 | //密码登录
157 | public function login($user, $pwd, $rsakv, $cid, $csrf_token)
158 | {
159 | $url = 'https://passport.weibo.com/sso/v2/login';
160 | $param = [
161 | 'entry' => 'miniblog',
162 | 'source' => 'miniblog',
163 | 'type' => '1',
164 | 'url' => 'https://weibo.com/newlogin?tabtype=weibo&gid=102803&openLoginLayer=0&url=https%3A%2F%2Fweibo.com%2F',
165 | 'username' => $user,
166 | 'pass' => $pwd,
167 | 'cid' => $cid,
168 | 'pwencode' => 'rsa',
169 | 'rsakv' => $rsakv,
170 | 'disp' => 'popup',
171 | ];
172 | if(empty($cid)){
173 | unset($param['cid']);
174 | }
175 | $cookie = 'X-CSRF-TOKEN='.$csrf_token;
176 | $headers = ['X-CSRF-TOKEN: '.$csrf_token, 'X-Requested-With: XMLHttpRequest'];
177 | $data = $this->get_curl($url, http_build_query($param), $this->referrer, $cookie, $headers, 1);
178 | $arr = json_decode($data['body'], true);
179 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
180 | $wbcookie=[];
181 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
182 | foreach ($matchs[1] as $val) {
183 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
184 | $key = substr($val, 0, strpos($val, '='));
185 | $wbcookie[$key]=substr($val, strpos($val, '=')+1);
186 | }
187 |
188 | $jump_url = $arr['data']['location'];
189 | $cookie = $this->get_sso_cookie($jump_url);
190 |
191 | $info = $this->get_user_info($wbcookie);
192 |
193 | return array('code' => 0, 'cookie' => $cookie, 'wbcookie' => $wbcookie, 'uid' => $info['user']['idstr'], 'nick' => $info['user']['screen_name']);
194 | }elseif($arr['retcode'] == 2071 && isset($arr['data']['location'])){
195 | $protection_url = $arr['data']['location'];
196 | $host = parse_url($protection_url, PHP_URL_HOST);
197 | parse_str(parse_url($protection_url, PHP_URL_QUERY), $query_arr);
198 | if($host == 'passport.weibo.cn'){
199 | $token = $query_arr['id'];
200 | $this->get_curl($protection_url, 0, $this->referrer);
201 | $data2 = $this->get_curl('https://passport.weibo.cn/signin/secondverify/index?first_enter=1&c=', 0, $this->referrer, 'FID='.$token);
202 | preg_match('!\"maskMobile\":\"(.*?)\"!s', $data2, $match);
203 | if($match[0]){
204 | return array('code' => 1, 'msg' => $arr['msg'], 'type'=>'1', 'token'=>$token, 'mobile'=>$match[1], 'encrypt_mobile'=>$match[1]);
205 | }else{
206 | return array('code' => -1, 'msg' => '手机验证信息获取失败 '.$arr['msg']);
207 | }
208 | }else{
209 | $token = $query_arr['token'];
210 | $data2 = $this->get_curl($protection_url, 0, $this->referrer);
211 | preg_match('!
(.*?)!s', $data2, $match);
212 | if($match[0]){
213 | return array('code' => 1, 'msg' => $arr['msg'], 'type'=>'0', 'token'=>$token, 'mobile'=>$match[2], 'encrypt_mobile'=>$match[1]);
214 | }else{
215 | return array('code' => -1, 'msg' => '手机验证信息获取失败 '.$arr['msg']);
216 | }
217 | }
218 | }elseif($arr['retcode'] == 4049 || $arr['retcode'] == 2120){
219 | return array('code' => 2, 'msg' => $arr['msg'], 'cid' => $arr['data']['mfa_id']);
220 | }elseif(isset($arr['msg'])){
221 | return array('code' => -1, 'msg' => $arr['msg']);
222 | }else{
223 | return array('code' => -1, 'msg' => '登录失败,原因未知');
224 | }
225 | }
226 |
227 | public function verifycaptcha($key, $lot_number, $captcha_output, $pass_token, $gen_time){
228 | $url = 'https://security.weibo.com/captcha/gt';
229 | $param = [
230 | 'key' => $key,
231 | 'lot_number' => $lot_number,
232 | 'captcha_output' => $captcha_output,
233 | 'pass_token' => $pass_token,
234 | 'gen_time' => $gen_time,
235 | ];
236 | $data = $this->get_curl($url.'?'.http_build_query($param), 0, $this->referrer);
237 | $arr = json_decode($data, true);
238 | if (isset($arr['retcode']) && $arr['retcode'] == 100000) {
239 | return array('code' => 0);
240 | }else{
241 | return array('code' => -1, 'msg' => '验证码验证失败 '.$arr['msg']);
242 | }
243 | }
244 |
245 | //登录异常-发送手机验证码
246 | public function sendcode($type, $token, $encrypt_mobile)
247 | {
248 | if($type == '1'){
249 | $url = 'https://passport.weibo.cn/signin/secondverify/ajsend?number=1&mask_mobile='.$encrypt_mobile.'&msg_type=sms';
250 | $referrer = 'https://passport.weibo.cn/signin/secondverify/index?first_enter=1&c=';
251 | $cookie = 'FID='.$token;
252 | $data = $this->get_curl($url, 0, $referrer, $cookie);
253 | $arr = json_decode($data, true);
254 | if (isset($arr['retcode']) && $arr['retcode'] == 100000) {
255 | return array('code' => 0, 'msg' => 'succ');
256 | } elseif (isset($arr['msg'])) {
257 | return array('code' => -1, 'msg' => $arr['msg']);
258 | } else {
259 | return array('code' => -1, 'msg' => '获取验证码失败,原因未知');
260 | }
261 | }else{
262 | $url = 'https://passport.weibo.com/protection/mobile/sendcode?token='.$token;
263 | $post = 'encrypt_mobile='.$encrypt_mobile;
264 | $data = $this->get_curl($url, $post, $this->referrer);
265 | $arr = json_decode($data, true);
266 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
267 | return array('code' => 0, 'msg' => 'succ');
268 | } elseif (isset($arr['msg'])) {
269 | return array('code' => -1, 'msg' => $arr['msg']);
270 | } else {
271 | return array('code' => -1, 'msg' => '获取验证码失败,原因未知');
272 | }
273 | }
274 | }
275 |
276 | //登录异常-提交手机验证码
277 | public function confirmcode($type, $token, $encrypt_mobile, $code)
278 | {
279 | if($type == '1'){
280 | $url = 'https://passport.weibo.cn/signin/secondverify/ajcheck?msg_type=sms&code='.$code;
281 | $referrer = 'https://passport.weibo.cn/signin/secondverify/check';
282 | $cookie = 'FID='.$token;
283 | $data = $this->get_curl($url, 0, $referrer, $cookie);
284 | $arr = json_decode($data, true);
285 | if (isset($arr['retcode']) && $arr['retcode'] == 100000) {
286 | $result = $this->login_getcookie($arr['data']['url']);
287 | return $result;
288 | } elseif (isset($arr['msg'])) {
289 | return array('code' => -1, 'msg' => $arr['msg']);
290 | } else {
291 | return array('code' => -1, 'msg' => '验证失败,原因未知');
292 | }
293 | }else{
294 | $url = 'https://passport.weibo.com/protection/mobile/confirm?token='.$token;
295 | $post = 'encrypt_mobile='.$encrypt_mobile.'&code='.$code;
296 | $data = $this->get_curl($url, $post, $this->referrer);
297 | $arr = json_decode($data, true);
298 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
299 | $result = $this->login_getcookie($arr['data']['redirect_url']);
300 | return $result;
301 | } elseif (isset($arr['msg'])) {
302 | return array('code' => -1, 'msg' => $arr['msg']);
303 | } else {
304 | return array('code' => -1, 'msg' => '验证失败,原因未知');
305 | }
306 | }
307 | }
308 |
309 |
310 | //短信登录-发送手机验证码
311 | public function sendsms($mobile, $cid, $csrf_token)
312 | {
313 | $url = 'https://passport.weibo.com/sso/v2/sms/send';
314 | $post = 'entry=miniblog&mobile='.$mobile;
315 | if(!empty($cid)){
316 | $post .= '&mfa_id='.$cid;
317 | }
318 | $cookie = 'X-CSRF-TOKEN='.$csrf_token;
319 | $headers = ['X-CSRF-TOKEN: '.$csrf_token, 'X-Requested-With: XMLHttpRequest'];
320 | $data = $this->get_curl($url, $post, $this->referrer, $cookie, $headers);
321 | $arr = json_decode($data, true);
322 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
323 | return array('code' => 0, 'msg' => 'succ');
324 | } elseif (isset($arr['retcode']) && $arr['retcode'] == 0) {
325 | return array('code' => 2, 'msg' => $arr['msg'], 'cid' => $arr['data']['mfa_id']);
326 | } elseif (isset($arr['msg'])) {
327 | return array('code' => -1, 'msg' => $arr['msg']);
328 | } else {
329 | return array('code' => -1, 'msg' => '获取验证码失败,原因未知');
330 | }
331 | }
332 |
333 | //手机验证码登录
334 | public function smslogin($user, $code, $csrf_token)
335 | {
336 | $url = 'https://passport.weibo.com/sso/v2/login';
337 | $param = [
338 | 'entry' => 'miniblog',
339 | 'source' => 'miniblog',
340 | 'type' => '2',
341 | 'url' => 'https://weibo.com/newlogin?tabtype=weibo&gid=102803&openLoginLayer=0&url=https%3A%2F%2Fweibo.com%2F',
342 | 'username' => $user,
343 | 'scode' => $code,
344 | 'disp' => 'popup',
345 | ];
346 | $cookie = 'X-CSRF-TOKEN='.$csrf_token;
347 | $headers = ['X-CSRF-TOKEN: '.$csrf_token, 'X-Requested-With: XMLHttpRequest'];
348 | $data = $this->get_curl($url, http_build_query($param), $this->referrer, $cookie, $headers, 1);
349 | $arr = json_decode($data['body'], true);
350 | if (isset($arr['retcode']) && $arr['retcode'] == 20000000) {
351 | $wbcookie=[];
352 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
353 | foreach ($matchs[1] as $val) {
354 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
355 | $key = substr($val, 0, strpos($val, '='));
356 | $wbcookie[$key]=substr($val, strpos($val, '=')+1);
357 | }
358 |
359 | $jump_url = $arr['data']['location'];
360 | $cookie = $this->get_sso_cookie($jump_url);
361 |
362 | $info = $this->get_user_info($wbcookie);
363 |
364 | return array('code' => 0, 'cookie' => $cookie, 'wbcookie' => $wbcookie, 'uid' => $info['user']['idstr'], 'nick' => $info['user']['screen_name']);
365 | }elseif(isset($arr['msg'])){
366 | return array('code' => -1, 'msg' => $arr['msg']);
367 | }else{
368 | return array('code' => -1, 'msg' => '登录失败,原因未知');
369 | }
370 | }
371 |
372 | public function cookielogin($cookie){
373 | $cookies = '';
374 | foreach($cookie as $key=>$value){
375 | $cookies .= $key.'='.$value.'; ';
376 | }
377 | $url = 'https://login.sina.com.cn/sso/login.php?url=https%3A%2F%2Fwww.weibo.com%2F&_rand='.time().'&gateway=1&service=miniblog&entry=miniblog&useticket=1&returntype=TEXT&sudaref=&_client_version=0.6.33';
378 | $data = $this->get_curl($url, 0, $this->referrer, $cookies, 0, 1);
379 | print_r($data);
380 | $arr = json_decode($data['body'], true);
381 | if (isset($arr['retcode']) && $arr['retcode'] == 0) {
382 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
383 | foreach ($matchs[1] as $val) {
384 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
385 | $key = substr($val, 0, strpos($val, '='));
386 | $cookie[$key]=substr($val, strpos($val, '=')+1);
387 | }
388 | $ticket = $arr['ticket'];
389 | $wbcookie = $this->weibosso($ticket);
390 | if(!$wbcookie){
391 | return array('code' => -1, 'msg' => $this->errmsg);
392 | }
393 | return array('code' => 0, 'cookie' => $cookie, 'wbcookie' => $wbcookie, 'uid' => $arr['uid'], 'nick' => $arr['nick']);
394 | } elseif (isset($arr['retcode'])) {
395 | return array('code' => -1, 'msg' => '登录失败,登录COOKIE已失效('.$arr['retcode'].')');
396 | } else {
397 | return array('code' => -1, 'msg' => '登录失败,登录COOKIE已失效');
398 | }
399 | }
400 |
401 | private function weibosso($ticket){
402 | $ssosavestate = time()+2592000;
403 | $url = 'https://passport.weibo.com/wbsso/login?ticket='.$ticket.'&ssosavestate='.$ssosavestate.'&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.2)';
404 | $data = $this->get_curl($url, 0, $this->referrer, 0, 0, 1);
405 | $arr = $this->jsonp_decode($data['body'], true);
406 | if (isset($arr['result']) && $arr['result']==true) {
407 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
408 | $cookie = [];
409 | foreach ($matchs[1] as $val) {
410 | if(strpos($val, '=deleted') || substr($val,-1)=='=') continue;
411 | $key = substr($val, 0, strpos($val, '='));
412 | $cookie[$key]=substr($val, strpos($val, '=')+1);
413 | }
414 | return $cookie;
415 | } elseif (!empty($arr['reason'])) {
416 | $this->errmsg = '登录成功,获取微博cookie失败('.$arr['reason'].')';
417 | return false;
418 | } else {
419 | $this->errmsg = '登录成功,获取微博cookie失败';
420 | return false;
421 | }
422 | }
423 |
424 | public function qq_getqrcode(){
425 | //$url='https://ssl.ptlogin2.qq.com/ptqrshow?appid=716027609&e=2&l=M&s=4&d=72&v=4&t=0.2616844'.time().'&daid=383&pt_3rd_aid=101019034';
426 | $url='https://xui.ptlogin2.qq.com/ssl/ptqrshow?s=8&e=0&appid=716027609&type=1&t=0.492909'.time().'&daid=383&pt_3rd_aid=101019034';
427 | $refer='https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&daid=383&style=33&login_text=%E7%99%BB%E5%BD%95&hide_title_bar=1&hide_border=1&target=self&s_url=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&pt_3rd_aid=101019034&pt_feedback_link=https%3A%2F%2Fsupport.qq.com%2Fproducts%2F77942%3FcustomInfo%3Dweibo.com.appid101019034&theme=2&verify_theme=';
428 | $data=$this->get_curl($url,0,$refer,0,0,1);
429 | preg_match('/qrsig=(.*?);/',$data['header'],$match);
430 | if($qrsig=$match[1]){
431 | $arr = $this->jsonp_decode($data['body'], true);
432 | return array('code'=>0,'qrsig'=>$qrsig,'qrcode'=>$arr['qrcode']);
433 | }
434 | else{
435 | return array('code'=>-1,'msg'=>'二维码获取失败');
436 | }
437 | }
438 |
439 | public function qq_qrlogin($qrsig){
440 | if(empty($qrsig))return array('code'=>-1,'msg'=>'qrsig不能为空');
441 | $url='https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&ptqrtoken='.$this->getqrtoken($qrsig).'&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=4-1-'.time().'000&js_ver=22072900&js_type=1&login_sig=&pt_uistyle=40&aid=716027609&daid=383&pt_3rd_aid=101019034&';
442 | $refer='https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&daid=383&style=33&login_text=%E7%99%BB%E5%BD%95&hide_title_bar=1&hide_border=1&target=self&s_url=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&pt_3rd_aid=101019034&pt_feedback_link=https%3A%2F%2Fsupport.qq.com%2Fproducts%2F77942%3FcustomInfo%3Dweibo.com.appid101019034&theme=2&verify_theme=';
443 | $ret = $this->get_curl($url,0,$refer,'qrsig='.$qrsig.'; ');
444 | if(preg_match("/ptuiCB\('(.*?)'\)/", $ret, $arr)){
445 | $r=explode("','",str_replace("', '","','",$arr[1]));
446 | if($r[0]==0){
447 | preg_match('/uin=(\d+)&/',$ret,$uin);
448 | $uin=$uin[1];
449 | $data=$this->get_curl($r[2],0,$refer,0,0,1);
450 | if($data) {
451 | $cookie='';
452 | preg_match_all('/Set-Cookie: (.*?);/i',$data['header'],$matchs);
453 | foreach ($matchs[1] as $val) {
454 | if(substr($val,-1)=='=')continue;
455 | $cookie.=$val.'; ';
456 | }
457 | preg_match('/p_skey=(.*?);/',$cookie,$pskey);
458 | $cookie = substr($cookie,0,-2);
459 | $data=$this->get_curl('https://passport.weibo.com/othersitebind/authorize?entry=miniblog&site=qq',0,0,0,0,1);
460 | if(preg_match('/crossidccode=(.*?);/',$data['header'],$match)){
461 | $crossidccode = $match[1];
462 | $url = 'https://graph.qq.com/oauth2.0/authorize';
463 | $post = 'response_type=code&client_id=101019034&redirect_uri=https%3A%2F%2Fpassport.weibo.com%2Fothersitebind%2Fbind%3Fsite%3Dqq%26state%3D'.$crossidccode.'%26bentry%3Dminiblog%26wl%3D&scope=get_info%2Cget_user_info&state=&switch=&from_ptlogin=1&src=1&update_auth=1&openapi=80901010&g_tk='.$this->getGTK($pskey[1]).'&auth_time='.time().'304&ui=E4077228-8A59-4020-A957-B5830A9509D3';
464 | $data=$this->get_curl($url,$post,0,$cookie,0,1);
465 | if(preg_match("/Location: (.*?)\r\n/i", $data['header'], $match)){
466 | $redirect_uri = $match[1];
467 | return array('code'=>0,'msg'=>'succ','uin'=>$uin,'redirect_uri'=>$redirect_uri,'crossidccode'=>$crossidccode);
468 | }else{
469 | return array('code'=>-1,'uin'=>$uin,'msg'=>'登录QQ成功,回调网站失败!');
470 | }
471 | }else{
472 | return array('code'=>-1,'uin'=>$uin,'msg'=>'登录QQ成功,获取crossidccode失败!');
473 | }
474 | }else{
475 | return array('code'=>-1,'uin'=>$uin,'msg'=>'登录QQ成功,获取相关信息失败!');
476 | }
477 | }elseif($r[0]==65){
478 | return array('code'=>1,'msg'=>'二维码已失效。');
479 | }elseif($r[0]==66){
480 | return array('code'=>2,'msg'=>'二维码未失效。');
481 | }elseif($r[0]==67){
482 | return array('code'=>3,'msg'=>'正在验证二维码。');
483 | }else{
484 | return array('code'=>-1,'msg'=>$r[4]);
485 | }
486 | }else{
487 | return array('code'=>-1,'msg'=>$ret);
488 | }
489 | }
490 |
491 | public function qq_connect($redirect_uri, $crossidccode){
492 | if(empty($redirect_uri) || parse_url($redirect_uri, PHP_URL_HOST)!='passport.weibo.com')return array('code'=>-1,'msg'=>'回调地址错误');
493 | if(empty($crossidccode))return array('code'=>-1,'msg'=>'crossidccode不能为空');
494 | $data=$this->get_curl($redirect_uri,0,0,'crossidccode='.$crossidccode,0,1);
495 | preg_match("/Location: (.*?)\r\n/i", $data['header'], $match);
496 | if($login_url = $match[1]){
497 | if(strpos($login_url, '/sso/login.php?')){
498 | $result = $this->login_getcookie($login_url);
499 | return $result;
500 | }else{
501 | return array('code'=>-1,'msg'=>'该QQ未绑定微博账号!');
502 | }
503 | }else{
504 | return array('code'=>-1,'msg'=>'登录QQ成功,获取微博登录信息失败!');
505 | }
506 | }
507 |
508 | private function getqrtoken($qrsig){
509 | $len = strlen($qrsig);
510 | $hash = 0;
511 | for($i = 0; $i < $len; $i++){
512 | $hash += (($hash << 5) & 2147483647) + ord($qrsig[$i]) & 2147483647;
513 | $hash &= 2147483647;
514 | }
515 | return $hash & 2147483647;
516 | }
517 | private function getGTK($skey){
518 | $len = strlen($skey);
519 | $hash = 5381;
520 | for ($i = 0; $i < $len; $i++) {
521 | $hash += ($hash << 5 & 2147483647) + ord($skey[$i]) & 2147483647;
522 | $hash &= 2147483647;
523 | }
524 | return $hash & 2147483647;
525 | }
526 |
527 |
528 | private function get_curl($url, $post = 0, $referer = 0, $cookie = 0, $headers = 0, $split = 0)
529 | {
530 | $ch = curl_init();
531 | curl_setopt($ch, CURLOPT_URL, $url);
532 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
533 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
534 | $httpheader[] = "Accept: application/json";
535 | $httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
536 | $httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
537 | $httpheader[] = "Connection: close";
538 | if($headers){
539 | $httpheader = array_merge($httpheader, $headers);
540 | }
541 | curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
542 | //curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
543 | if ($post) {
544 | curl_setopt($ch, CURLOPT_POST, 1);
545 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
546 | }
547 | if ($split) {
548 | curl_setopt($ch, CURLOPT_HEADER, TRUE);
549 | }
550 | if ($cookie) {
551 | curl_setopt($ch, CURLOPT_COOKIE, $cookie);
552 | }
553 | if ($referer) {
554 | curl_setopt($ch, CURLOPT_REFERER, $referer);
555 | }
556 | curl_setopt($ch, CURLOPT_USERAGENT, $this->useragent);
557 | curl_setopt($ch, CURLOPT_TIMEOUT, 10);
558 | curl_setopt($ch, CURLOPT_ENCODING, "gzip");
559 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
560 | $ret = curl_exec($ch);
561 | if($split){
562 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
563 | $header = substr($ret, 0, $headerSize);
564 | $body = substr($ret, $headerSize);
565 | $ret=array();
566 | $ret['header']=$header;
567 | $ret['body']=$body;
568 | }
569 | curl_close($ch);
570 | return $ret;
571 | }
572 | }
573 |
--------------------------------------------------------------------------------
/includes/lib/WeiboTool.php:
--------------------------------------------------------------------------------
1 | cookie = $cookie;
12 | }
13 |
14 | public function checkCookie(){
15 | $url = 'https://weibo.com/ajax/statuses/config?type=push_active';
16 | $data = $this->get_curl($url, 0, $this->referrer, $this->cookie);
17 | $arr = json_decode($data, true);
18 | if(isset($arr['ok']) && $arr['ok']==1){
19 | return true;
20 | }
21 | return false;
22 | }
23 |
24 | public function getBasicInfo(){
25 | $url = 'https://weibo.com/ajax/setting/getBasicInfo';
26 | $data = $this->get_curl($url, 0, $this->referrer, $this->cookie);
27 | $arr = json_decode($data, true);
28 | if(isset($arr['ok']) && $arr['ok']==1){
29 | return ['code'=>0, 'data'=>$arr['data']];
30 | }elseif(isset($arr['ok']) && $arr['ok']==-100){
31 | $this->cookiefail = true;
32 | return ['code'=>-1, 'msg'=>'获取个人基本信息失败:COOKIE已失效'];
33 | }elseif(isset($arr['message'])){
34 | return ['code'=>-1, 'msg'=>'获取个人基本信息失败:'.$arr['message']];
35 | }else{
36 | return ['code'=>-1, 'msg'=>'获取个人基本信息失败:接口请求失败'];
37 | }
38 | }
39 |
40 | public function hotline(){
41 | $url = 'https://weibo.com/ajax/side/hotSearch';
42 | $data = $this->get_curl($url, 0, $this->referrer, $this->cookie);
43 | $arr = json_decode($data, true);
44 | if(isset($arr['ok']) && $arr['ok']==1 && isset($arr['data']['realtime'])){
45 | $list = [];
46 | foreach($arr['data']['realtime'] as $row){
47 | if($row['is_ad']) continue;
48 | $list[] = ['rank'=>$row['realpos'], 'category'=>$row['category'], 'content'=>$row['word'], 'time'=>$row['onboard_time'], 'num'=>$row['num'], 'label'=>$row['label_name'], 'mid'=>$row['mid']];
49 | }
50 | return ['code'=>0, 'data'=>$list];
51 | }elseif(isset($arr['ok']) && $arr['ok']==-100){
52 | $this->cookiefail = true;
53 | return ['code'=>-1, 'msg'=>'获取热搜列表失败:COOKIE已失效'];
54 | }elseif(isset($arr['message'])){
55 | return ['code'=>-1, 'msg'=>'获取热搜列表失败:'.$arr['message']];
56 | }else{
57 | return ['code'=>-1, 'msg'=>'获取热搜列表失败:接口请求失败'];
58 | }
59 | }
60 |
61 | public function parseVideo($oid){
62 | $page = '/tv/show/'.$oid;
63 | $url = 'https://weibo.com/tv/api/component?page='.urlencode($page);
64 | $post = 'data={"Component_Play_Playinfo":{"oid":"'.$oid.'"}}';
65 | $referer = 'https://weibo.com/tv/show/'.$oid;
66 | $data = $this->get_curl($url, $post, $referer, $this->cookie);
67 | $arr = json_decode($data, true);
68 | if(isset($arr['code']) && $arr['code']=='100000'){
69 | if(isset($arr['data']['Component_Play_Playinfo'])){
70 | $info = $arr['data']['Component_Play_Playinfo'];
71 | $result = ['title'=>$info['title'], 'author'=>$info['author'], 'author_id'=>$info['user']['id'], 'author_avatar'=>$info['avatar'], 'urls'=>$info['urls'], 'cover'=>$info['cover_image'], 'time'=>$info['real_date'], 'duration'=>$info['duration']];
72 | return ['code'=>0, 'data'=>$result];
73 | }else{
74 | return ['code'=>-1, 'msg'=>'解析视频失败:视频不存在'];
75 | }
76 | }elseif(isset($arr['msg'])){
77 | return ['code'=>-1, 'msg'=>'解析视频失败:'.$arr['msg']];
78 | }else{
79 | return ['code'=>-1, 'msg'=>'解析视频失败:接口请求失败'];
80 | }
81 | }
82 |
83 | public function getUserInfo($uid){
84 | $url = 'https://weibo.com/ajax/profile/info?uid='.$uid;
85 | $data = $this->get_curl($url, 0, $this->referrer, $this->cookie);
86 | $arr = json_decode($data, true);
87 | if(isset($arr['ok']) && $arr['ok']==1 && isset($arr['data']['user'])){
88 | $info = $arr['data']['user'];
89 | $result = ['uid'=>$info['idstr'], 'name'=>$info['screen_name'], 'avatar'=>$info['avatar_hd'], 'gender'=>$info['gender'], 'location'=>$info['location'], 'description'=>$info['description'], 'domain'=>$info['domain'], 'friends_count'=>$info['friends_count'], 'followers_count'=>$info['followers_count'], 'statuses_count'=>$info['statuses_count'], 'verified'=>$info['verified'], 'verified_reason'=>$info['verified_reason'], 'verified_type'=>$info['verified_type'], 'is_muteuser'=>$info['is_muteuser']];
90 | return ['code'=>0, 'data'=>$result];
91 | }elseif(isset($arr['ok']) && $arr['ok']==-100){
92 | $this->cookiefail = true;
93 | return ['code'=>-1, 'msg'=>'获取用户信息失败:COOKIE已失效'];
94 | }elseif(isset($arr['message'])){
95 | return ['code'=>-1, 'msg'=>'获取用户信息失败:'.$arr['message']];
96 | }else{
97 | return ['code'=>-1, 'msg'=>'获取用户信息失败:接口请求失败'];
98 | }
99 | }
100 |
101 | public function upload($file_path){
102 | $file_content = file_get_contents($file_path);
103 | $params = [
104 | 'file_source' => '1',
105 | 'cs' => crc32($file_content),
106 | 'ent' => 'miniblog',
107 | 'appid' => '339644097',
108 | 'uid' => '',
109 | 'raw_md5' => md5_file($file_path),
110 | 'ori' => '1',
111 | 'mpos' => '1',
112 | 'pri' => '0',
113 | 'request_id' => self::getMillisecond(),
114 | 'file_size' => filesize($file_path)
115 | ];
116 | $url = 'https://picupload.weibo.com/interface/upload.php?' . http_build_query($params);
117 | $data = $this->get_curl($url, $file_content, $this->referrer, $this->cookie);
118 | $arr = json_decode($data, true);
119 | if(isset($arr['ret']) && $arr['ret']==true){
120 | $pid = $arr['pic']['pid'];
121 | return ['code'=>0, 'data'=>'https://image.baidu.com/search/down?thumburl=https://baidu.com&url=https://fc.sinaimg.cn/large/'.$pid.'.jpg'];
122 | }else{
123 | if($arr['errno'] == -1){
124 | $this->cookiefail = true;
125 | return ['code'=>-1, 'msg'=>'上传失败,COOKIE已失效'];
126 | }else{
127 | return ['code'=>-1, 'msg'=>'上传失败,请稍后再试'];
128 | }
129 | }
130 | return false;
131 | }
132 |
133 | static private function getMillisecond() {
134 | list($s1, $s2) = explode(' ', microtime());
135 | return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
136 | }
137 |
138 | private function get_curl($url, $post = 0, $referer = 0, $cookie = 0, $header = 0)
139 | {
140 | $ch = curl_init();
141 | curl_setopt($ch, CURLOPT_URL, $url);
142 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
143 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
144 | $httpheader[] = "Accept: application/json";
145 | $httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
146 | $httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
147 | $httpheader[] = "Connection: close";
148 | curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
149 | if ($post) {
150 | curl_setopt($ch, CURLOPT_POST, 1);
151 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
152 | }
153 | if ($header) {
154 | curl_setopt($ch, CURLOPT_HEADER, TRUE);
155 | }
156 | if ($cookie) {
157 | curl_setopt($ch, CURLOPT_COOKIE, $cookie);
158 | }
159 | if ($referer) {
160 | curl_setopt($ch, CURLOPT_REFERER, $referer);
161 | }
162 | curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36');
163 | curl_setopt($ch, CURLOPT_TIMEOUT, 10);
164 | curl_setopt($ch, CURLOPT_ENCODING, "gzip");
165 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
166 | $ret = curl_exec($ch);
167 | curl_close($ch);
168 | return $ret;
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/includes/lib/mail/Aliyun.php:
--------------------------------------------------------------------------------
1 | AccessKeyId = $AccessKeyId;
13 | $this->AccessKeySecret = $AccessKeySecret;
14 | }
15 | private function aliyunSignature($parameters, $accessKeySecret, $method)
16 | {
17 | ksort($parameters);
18 | $canonicalizedQueryString = '';
19 | foreach ($parameters as $key => $value) {
20 | if($value === null) continue;
21 | $canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
22 | }
23 | $stringToSign = $method . '&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
24 | $signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&", true));
25 |
26 | return $signature;
27 | }
28 | private function percentEncode($str)
29 | {
30 | $search = ['+', '*', '%7E'];
31 | $replace = ['%20', '%2A', '~'];
32 | return str_replace($search, $replace, urlencode($str));
33 | }
34 | public function send($to, $sub, $msg, $from, $from_name)
35 | {
36 | if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) return false;
37 | $url = 'https://dm.aliyuncs.com/';
38 | $data = array(
39 | 'Action' => 'SingleSendMail',
40 | 'AccountName' => $from,
41 | 'ReplyToAddress' => 'false',
42 | 'AddressType' => 1,
43 | 'ToAddress' => $to,
44 | 'FromAlias' => $from_name,
45 | 'Subject' => $sub,
46 | 'HtmlBody' => $msg,
47 | 'Format' => 'JSON',
48 | 'Version' => '2015-11-23',
49 | 'AccessKeyId' => $this->AccessKeyId,
50 | 'SignatureMethod' => 'HMAC-SHA1',
51 | 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
52 | 'SignatureVersion' => '1.0',
53 | 'SignatureNonce' => random(8)
54 | );
55 | $data['Signature'] = $this->aliyunSignature($data, $this->AccessKeySecret, 'POST');
56 | $ch = curl_init($url);
57 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
58 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
59 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
60 | curl_setopt($ch, CURLOPT_TIMEOUT, 10);
61 | curl_setopt($ch, CURLOPT_POST, 1);
62 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
63 | $json = curl_exec($ch);
64 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
65 | curl_close($ch);
66 | $arr = json_decode($json, true);
67 | if ($httpCode == 200) {
68 | return true;
69 | } else {
70 | return $arr['Message'];
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/includes/lib/mail/PHPMailer/Exception.php:
--------------------------------------------------------------------------------
1 | ' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "
\n"; } }
--------------------------------------------------------------------------------
/includes/lib/mail/PHPMailer/SMTP.php:
--------------------------------------------------------------------------------
1 | '/[\d]{3} OK id=(.*)/', 'sendmail' => '/[\d]{3} 2\.0\.0 (.*) Message/', 'postfix' => '/[\d]{3} 2\.0\.0 Ok: queued as (.*)/', 'Microsoft_ESMTP' => '/[0-9]{3} 2\.[\d]\.0 (.*)@(?:.*) Queued mail for delivery/', 'Amazon_SES' => '/[\d]{3} Ok (.*)/', 'SendGrid' => '/[\d]{3} Ok: queued as (.*)/', 'CampaignMonitor' => '/[\d]{3} 2\.0\.0 OK:([a-zA-Z\d]{48})/', 'Haraka' => '/[\d]{3} Message Queued \((.*)\)/', 'ZoneMTA' => '/[\d]{3} Message queued as (.*)/', 'Mailjet' => '/[\d]{3} OK queued as (.*)/', ]; public static $xclient_allowed_attributes = [ 'NAME', 'ADDR', 'PORT', 'PROTO', 'HELO', 'LOGIN', 'DESTADDR', 'DESTPORT' ]; protected $last_smtp_transaction_id; protected $smtp_conn; protected $error = [ 'error' => '', 'detail' => '', 'smtp_code' => '', 'smtp_code_ex' => '', ]; protected $helo_rply; protected $server_caps; protected $last_reply = ''; protected function edebug($str, $level = 0) { if ($level > $this->do_debug) { return; } if ($this->Debugoutput instanceof \Psr\Log\LoggerInterface) { $this->Debugoutput->debug(rtrim($str, "\r\n")); return; } if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) { call_user_func($this->Debugoutput, $str, $level); return; } switch ($this->Debugoutput) { case 'error_log': error_log($str); break; case 'html': echo gmdate('Y-m-d H:i:s'), ' ', htmlentities( preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, 'UTF-8' ), "
\n"; break; case 'echo': default: $str = preg_replace('/\r\n|\r/m', "\n", $str); echo gmdate('Y-m-d H:i:s'), "\t", trim( str_replace( "\n", "\n \t ", trim($str) ) ), "\n"; } } public function connect($host, $port = null, $timeout = 30, $options = []) { $this->setError(''); if ($this->connected()) { $this->setError('Already connected to a server'); return false; } if (empty($port)) { $port = self::DEFAULT_PORT; } $this->edebug( "Connection: opening to $host:$port, timeout=$timeout, options=" . (count($options) > 0 ? var_export($options, true) : 'array()'), self::DEBUG_CONNECTION ); $this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $options); if ($this->smtp_conn === false) { return false; } $this->edebug('Connection: opened', self::DEBUG_CONNECTION); $this->last_reply = $this->get_lines(); $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); $responseCode = (int)substr($this->last_reply, 0, 3); if ($responseCode === 220) { return true; } if ($responseCode === 554) { $this->quit(); } $this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION); $this->close(); return false; } protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = []) { static $streamok; if (null === $streamok) { $streamok = function_exists('stream_socket_client'); } $errno = 0; $errstr = ''; if ($streamok) { $socket_context = stream_context_create($options); set_error_handler([$this, 'errorHandler']); $connection = stream_socket_client( $host . ':' . $port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $socket_context ); } else { $this->edebug( 'Connection: stream_socket_client not available, falling back to fsockopen', self::DEBUG_CONNECTION ); set_error_handler([$this, 'errorHandler']); $connection = fsockopen( $host, $port, $errno, $errstr, $timeout ); } restore_error_handler(); if (!is_resource($connection)) { $this->setError( 'Failed to connect to server', '', (string) $errno, $errstr ); $this->edebug( 'SMTP ERROR: ' . $this->error['error'] . ": $errstr ($errno)", self::DEBUG_CLIENT ); return false; } if (strpos(PHP_OS, 'WIN') !== 0) { $max = (int)ini_get('max_execution_time'); if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) { @set_time_limit($timeout); } stream_set_timeout($connection, $timeout, 0); } return $connection; } public function startTLS() { if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { return false; } $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; } set_error_handler([$this, 'errorHandler']); $crypto_ok = stream_socket_enable_crypto( $this->smtp_conn, true, $crypto_method ); restore_error_handler(); return (bool) $crypto_ok; } public function authenticate( $username, $password, $authtype = null, $OAuth = null ) { if (!$this->server_caps) { $this->setError('Authentication is not allowed before HELO/EHLO'); return false; } if (array_key_exists('EHLO', $this->server_caps)) { if (!array_key_exists('AUTH', $this->server_caps)) { $this->setError('Authentication is not allowed at this stage'); return false; } $this->edebug('Auth method requested: ' . ($authtype ?: 'UNSPECIFIED'), self::DEBUG_LOWLEVEL); $this->edebug( 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']), self::DEBUG_LOWLEVEL ); if (null !== $authtype && !in_array($authtype, $this->server_caps['AUTH'], true)) { $this->edebug('Requested auth method not available: ' . $authtype, self::DEBUG_LOWLEVEL); $authtype = null; } if (empty($authtype)) { foreach (['CRAM-MD5', 'LOGIN', 'PLAIN', 'XOAUTH2'] as $method) { if (in_array($method, $this->server_caps['AUTH'], true)) { $authtype = $method; break; } } if (empty($authtype)) { $this->setError('No supported authentication methods found'); return false; } $this->edebug('Auth method selected: ' . $authtype, self::DEBUG_LOWLEVEL); } if (!in_array($authtype, $this->server_caps['AUTH'], true)) { $this->setError("The requested authentication method \"$authtype\" is not supported by the server"); return false; } } elseif (empty($authtype)) { $authtype = 'LOGIN'; } switch ($authtype) { case 'PLAIN': if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) { return false; } if ( !$this->sendCommand( 'User & Password', base64_encode("\0" . $username . "\0" . $password), 235 ) ) { return false; } break; case 'LOGIN': if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { return false; } if (!$this->sendCommand('Username', base64_encode($username), 334)) { return false; } if (!$this->sendCommand('Password', base64_encode($password), 235)) { return false; } break; case 'CRAM-MD5': if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { return false; } $challenge = base64_decode(substr($this->last_reply, 4)); $response = $username . ' ' . $this->hmac($challenge, $password); return $this->sendCommand('Username', base64_encode($response), 235); case 'XOAUTH2': if (null === $OAuth) { return false; } $oauth = $OAuth->getOauth64(); if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) { return false; } break; default: $this->setError("Authentication method \"$authtype\" is not supported"); return false; } return true; } protected function hmac($data, $key) { if (function_exists('hash_hmac')) { return hash_hmac('md5', $data, $key); } $bytelen = 64; if (strlen($key) > $bytelen) { $key = pack('H*', md5($key)); } $key = str_pad($key, $bytelen, chr(0x00)); $ipad = str_pad('', $bytelen, chr(0x36)); $opad = str_pad('', $bytelen, chr(0x5c)); $k_ipad = $key ^ $ipad; $k_opad = $key ^ $opad; return md5($k_opad . pack('H*', md5($k_ipad . $data))); } public function connected() { if (is_resource($this->smtp_conn)) { $sock_status = stream_get_meta_data($this->smtp_conn); if ($sock_status['eof']) { $this->edebug( 'SMTP NOTICE: EOF caught while checking if connected', self::DEBUG_CLIENT ); $this->close(); return false; } return true; } return false; } public function close() { $this->server_caps = null; $this->helo_rply = null; if (is_resource($this->smtp_conn)) { fclose($this->smtp_conn); $this->smtp_conn = null; $this->edebug('Connection: closed', self::DEBUG_CONNECTION); } } public function data($msg_data) { if (!$this->sendCommand('DATA', 'DATA', 354)) { return false; } $lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data)); $field = substr($lines[0], 0, strpos($lines[0], ':')); $in_headers = false; if (!empty($field) && strpos($field, ' ') === false) { $in_headers = true; } foreach ($lines as $line) { $lines_out = []; if ($in_headers && $line === '') { $in_headers = false; } while (isset($line[self::MAX_LINE_LENGTH])) { $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); if (!$pos) { $pos = self::MAX_LINE_LENGTH - 1; $lines_out[] = substr($line, 0, $pos); $line = substr($line, $pos); } else { $lines_out[] = substr($line, 0, $pos); $line = substr($line, $pos + 1); } if ($in_headers) { $line = "\t" . $line; } } $lines_out[] = $line; foreach ($lines_out as $line_out) { if (!empty($line_out) && $line_out[0] === '.') { $line_out = '.' . $line_out; } $this->client_send($line_out . static::LE, 'DATA'); } } $savetimelimit = $this->Timelimit; $this->Timelimit *= 2; $result = $this->sendCommand('DATA END', '.', 250); $this->recordLastTransactionID(); $this->Timelimit = $savetimelimit; return $result; } public function hello($host = '') { if ($this->sendHello('EHLO', $host)) { return true; } if (substr($this->helo_rply, 0, 3) == '421') { return false; } return $this->sendHello('HELO', $host); } protected function sendHello($hello, $host) { $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250); $this->helo_rply = $this->last_reply; if ($noerror) { $this->parseHelloFields($hello); } else { $this->server_caps = null; } return $noerror; } protected function parseHelloFields($type) { $this->server_caps = []; $lines = explode("\n", $this->helo_rply); foreach ($lines as $n => $s) { $s = trim(substr($s, 4)); if (empty($s)) { continue; } $fields = explode(' ', $s); if (!empty($fields)) { if (!$n) { $name = $type; $fields = $fields[0]; } else { $name = array_shift($fields); switch ($name) { case 'SIZE': $fields = ($fields ? $fields[0] : 0); break; case 'AUTH': if (!is_array($fields)) { $fields = []; } break; default: $fields = true; } } $this->server_caps[$name] = $fields; } } } public function mail($from) { $useVerp = ($this->do_verp ? ' XVERP' : ''); return $this->sendCommand( 'MAIL FROM', 'MAIL FROM:<' . $from . '>' . $useVerp, 250 ); } public function quit($close_on_error = true) { $noerror = $this->sendCommand('QUIT', 'QUIT', 221); $err = $this->error; if ($noerror || $close_on_error) { $this->close(); $this->error = $err; } return $noerror; } public function recipient($address, $dsn = '') { if (empty($dsn)) { $rcpt = 'RCPT TO:<' . $address . '>'; } else { $dsn = strtoupper($dsn); $notify = []; if (strpos($dsn, 'NEVER') !== false) { $notify[] = 'NEVER'; } else { foreach (['SUCCESS', 'FAILURE', 'DELAY'] as $value) { if (strpos($dsn, $value) !== false) { $notify[] = $value; } } } $rcpt = 'RCPT TO:<' . $address . '> NOTIFY=' . implode(',', $notify); } return $this->sendCommand( 'RCPT TO', $rcpt, [250, 251] ); } public function xclient(array $vars) { $xclient_options = ""; foreach ($vars as $key => $value) { if (in_array($key, SMTP::$xclient_allowed_attributes)) { $xclient_options .= " {$key}={$value}"; } } if (!$xclient_options) { return true; } return $this->sendCommand('XCLIENT', 'XCLIENT' . $xclient_options, 250); } public function reset() { return $this->sendCommand('RSET', 'RSET', 250); } protected function sendCommand($command, $commandstring, $expect) { if (!$this->connected()) { $this->setError("Called $command without being connected"); return false; } if ((strpos($commandstring, "\n") !== false) || (strpos($commandstring, "\r") !== false)) { $this->setError("Command '$command' contained line breaks"); return false; } $this->client_send($commandstring . static::LE, $command); $this->last_reply = $this->get_lines(); $matches = []; if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) { $code = (int) $matches[1]; $code_ex = (count($matches) > 2 ? $matches[2] : null); $detail = preg_replace( "/{$code}[ -]" . ($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m', '', $this->last_reply ); } else { $code = (int) substr($this->last_reply, 0, 3); $code_ex = null; $detail = substr($this->last_reply, 4); } $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); if (!in_array($code, (array) $expect, true)) { $this->setError( "$command command failed", $detail, $code, $code_ex ); $this->edebug( 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, self::DEBUG_CLIENT ); return false; } if ($command !== 'RSET') { $this->setError(''); } return true; } public function sendAndMail($from) { return $this->sendCommand('SAML', "SAML FROM:$from", 250); } public function verify($name) { return $this->sendCommand('VRFY', "VRFY $name", [250, 251]); } public function noop() { return $this->sendCommand('NOOP', 'NOOP', 250); } public function turn() { $this->setError('The SMTP TURN command is not implemented'); $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); return false; } public function client_send($data, $command = '') { if ( self::DEBUG_LOWLEVEL > $this->do_debug && in_array($command, ['User & Password', 'Username', 'Password'], true) ) { $this->edebug('CLIENT -> SERVER: [credentials hidden]', self::DEBUG_CLIENT); } else { $this->edebug('CLIENT -> SERVER: ' . $data, self::DEBUG_CLIENT); } set_error_handler([$this, 'errorHandler']); $result = fwrite($this->smtp_conn, $data); restore_error_handler(); return $result; } public function getError() { return $this->error; } public function getServerExtList() { return $this->server_caps; } public function getServerExt($name) { if (!$this->server_caps) { $this->setError('No HELO/EHLO was sent'); return null; } if (!array_key_exists($name, $this->server_caps)) { if ('HELO' === $name) { return $this->server_caps['EHLO']; } if ('EHLO' === $name || array_key_exists('EHLO', $this->server_caps)) { return false; } $this->setError('HELO handshake was used; No information about server extensions available'); return null; } return $this->server_caps[$name]; } public function getLastReply() { return $this->last_reply; } protected function get_lines() { if (!is_resource($this->smtp_conn)) { return ''; } $data = ''; $endtime = 0; stream_set_timeout($this->smtp_conn, $this->Timeout); if ($this->Timelimit > 0) { $endtime = time() + $this->Timelimit; } $selR = [$this->smtp_conn]; $selW = null; while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { set_error_handler([$this, 'errorHandler']); $n = stream_select($selR, $selW, $selW, $this->Timelimit); restore_error_handler(); if ($n === false) { $message = $this->getError()['detail']; $this->edebug( 'SMTP -> get_lines(): select failed (' . $message . ')', self::DEBUG_LOWLEVEL ); if (stripos($message, 'interrupted system call') !== false) { $this->edebug( 'SMTP -> get_lines(): retrying stream_select', self::DEBUG_LOWLEVEL ); $this->setError(''); continue; } break; } if (!$n) { $this->edebug( 'SMTP -> get_lines(): select timed-out in (' . $this->Timelimit . ' sec)', self::DEBUG_LOWLEVEL ); break; } $str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH); $this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL); $data .= $str; if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") { break; } $info = stream_get_meta_data($this->smtp_conn); if ($info['timed_out']) { $this->edebug( 'SMTP -> get_lines(): stream timed-out (' . $this->Timeout . ' sec)', self::DEBUG_LOWLEVEL ); break; } if ($endtime && time() > $endtime) { $this->edebug( 'SMTP -> get_lines(): timelimit reached (' . $this->Timelimit . ' sec)', self::DEBUG_LOWLEVEL ); break; } } return $data; } public function setVerp($enabled = false) { $this->do_verp = $enabled; } public function getVerp() { return $this->do_verp; } protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') { $this->error = [ 'error' => $message, 'detail' => $detail, 'smtp_code' => $smtp_code, 'smtp_code_ex' => $smtp_code_ex, ]; } public function setDebugOutput($method = 'echo') { $this->Debugoutput = $method; } public function getDebugOutput() { return $this->Debugoutput; } public function setDebugLevel($level = 0) { $this->do_debug = $level; } public function getDebugLevel() { return $this->do_debug; } public function setTimeout($timeout = 0) { $this->Timeout = $timeout; } public function getTimeout() { return $this->Timeout; } protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) { $notice = 'Connection failed.'; $this->setError( $notice, $errmsg, (string) $errno ); $this->edebug( "$notice Error #$errno: $errmsg [$errfile line $errline]", self::DEBUG_CONNECTION ); } protected function recordLastTransactionID() { $reply = $this->getLastReply(); if (empty($reply)) { $this->last_smtp_transaction_id = null; } else { $this->last_smtp_transaction_id = false; foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) { $matches = []; if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) { $this->last_smtp_transaction_id = trim($matches[1]); break; } } } return $this->last_smtp_transaction_id; } public function getLastTransactionID() { return $this->last_smtp_transaction_id; } }
--------------------------------------------------------------------------------
/includes/lib/mail/Sendcloud.php:
--------------------------------------------------------------------------------
1 | apiUser = $apiUser;
10 | $this->apiKey = $apiKey;
11 | }
12 | public function send($to, $sub, $msg, $from, $from_name){
13 | if(empty($this->apiUser)||empty($this->apiKey))return false;
14 | $url='http://api.sendcloud.net/apiv2/mail/send';
15 | $data=array(
16 | 'apiUser' => $this->apiUser,
17 | 'apiKey' => $this->apiKey,
18 | 'from' => $from,
19 | 'fromName' => $from_name,
20 | 'to' => $to,
21 | 'subject' => $sub,
22 | 'html' => $msg);
23 | $ch=curl_init($url);
24 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
25 | curl_setopt($ch, CURLOPT_TIMEOUT, 10);
26 | curl_setopt($ch, CURLOPT_POST, 1);
27 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
28 | $json=curl_exec($ch);
29 | curl_close($ch);
30 | $arr=json_decode($json,true);
31 | if($arr['statusCode']==200){
32 | return true;
33 | }else{
34 | return implode("\n",$arr['message']);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | window.location.href='./admin/';");
5 |
--------------------------------------------------------------------------------
/install/index.php:
--------------------------------------------------------------------------------
1 | $host,
42 | 'port' => $port,
43 | 'user' => $user,
44 | 'pwd' => $pwd,
45 | 'dbname' => $database,
46 | 'dbqz' => $dbqz
47 | );
48 | $config=" '{$host}', //数据库服务器
52 | 'port' => {$port}, //数据库端口
53 | 'user' => '{$user}', //数据库用户名
54 | 'pwd' => '{$pwd}', //数据库密码
55 | 'dbname' => '{$database}', //数据库名
56 | 'prefix' => '{$dbqz}' //数据表前缀
57 | );
58 | ";
59 | }
60 | if(empty($errorMsg)){
61 | try{
62 | $DB=new PDO("mysql:host=".$dbconfig['host'].";dbname=".$dbconfig['dbname'].";port=".$dbconfig['port'],$dbconfig['user'],$dbconfig['pwd']);
63 | }catch(Exception $e){
64 | if($e->getCode() == 2002){
65 | $errorMsg='连接数据库失败:数据库地址填写错误!';
66 | }elseif($e->getCode() == 1045){
67 | $errorMsg='连接数据库失败:数据库用户名或密码填写错误!';
68 | }elseif($e->getCode() == 1049){
69 | $errorMsg='连接数据库失败:数据库名不存在!';
70 | }else{
71 | $errorMsg='连接数据库失败:'.$e->getMessage();
72 | }
73 | }
74 | if(empty($errorMsg)){
75 | $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
76 | $DB->exec("set sql_mode = ''");
77 | $DB->exec("set names utf8");
78 | $mysqlversion = $DB->query("select version()")->fetchColumn();
79 | if(version_compare($mysqlversion, '5.5.3', '<')){
80 | $errorMsg='MySQL数据库版本太低,需要MySQL 5.6或以上版本!';
81 | }
82 | if(!$_GET['jump'] && !file_put_contents($databaseFile, $config)){
83 | $errorMsg='保存失败,请确保网站根目录有写入权限';
84 | }
85 | }
86 | }
87 | }elseif($step==4){
88 | include '../config.php';
89 | if(!$dbconfig['user']||!$dbconfig['pwd']||!$dbconfig['dbname']) {
90 | $errorMsg='请先填写好数据库并保存后再安装!';
91 | }else{
92 | try{
93 | $DB=new PDO("mysql:host=".$dbconfig['host'].";dbname=".$dbconfig['dbname'].";port=".$dbconfig['port'],$dbconfig['user'],$dbconfig['pwd']);
94 | }catch(Exception $e){
95 | $errorMsg='连接数据库失败:'.$e->getMessage();
96 | }
97 | if(empty($errorMsg) && !$_GET['jump']){
98 | $dbqz = $dbconfig['prefix'];
99 | $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
100 | $DB->exec("set sql_mode = ''");
101 | $DB->exec("set names utf8");
102 | $sqls=file_get_contents('install.sql');
103 | $sqls=explode(';', $sqls);
104 | $sqls[]="INSERT INTO `".$dbqz."config` VALUES ('syskey', '".random(20)."')";
105 | $sqls[]="INSERT INTO `".$dbqz."config` VALUES ('apikey', '".random(16)."')";
106 | $sqls[]="INSERT INTO `".$dbqz."config` VALUES ('cookie_key', '".random(16)."')";
107 | $success=0;$error=0;$errorMsg=null;
108 | foreach ($sqls as $value) {
109 | $value=trim($value);
110 | if(empty($value))continue;
111 | if($DB->exec($value)===false){
112 | $error++;
113 | $dberror=$DB->errorInfo();
114 | $errorMsg.=$dberror[2]."
";
115 | }else{
116 | $success++;
117 | }
118 | }
119 | }
120 | if(empty($errorMsg)){
121 | $lock_status = file_put_contents("install.lock",'安装锁');
122 | $step = 5;
123 | }
124 | }
125 | }
126 |
127 | ?>
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
微博API - 安装程序
136 |
137 |
138 |
139 |
140 |
141 |
142 |
微博API - 安装程序
143 |
144 |
147 |
MYSQL数据库信息配置
148 |
194 |
195 |
保存数据库配置
196 |
197 | '.$errorMsg.'
';
200 | }else{
201 | echo '
数据库配置文件保存成功!
';
202 | if($DB->query("select * from ".$dbconfig['dbqz']."_config")){
203 | ?>
204 |
系统检测到你已安装过微博API
205 |
208 |
211 |
212 |
215 |
218 |
219 |
220 |
安装数据表
221 |
226 |
227 |
安装完成
228 |
229 | 0){?>
成功执行SQL语句条,失败条!
230 |
231 | 1、系统已成功安装完毕!
232 | 2、后台地址:/admin/ 密码:123456
233 | 3、请及时修改后台管理员密码!
234 | 4、你的空间不支持本地文件读写,请自行在 /install/ 目录建立 install.lock 文件!
235 | 进入网站后台
236 |
237 |
238 |
239 |
安装环境检测
240 |
241 | 支持';
245 | }else{
246 | $check[2]='
不支持 ';
247 | $install=false;
248 | }
249 | if(class_exists("PDO")){
250 | $check[0]='
支持 ';
251 | }else{
252 | $check[0]='
不支持 ';
253 | $install=false;
254 | }
255 | if(is_writable($databaseFile)) {
256 | $check[1]='
支持 ';
257 | }else{
258 | $check[1]='
不支持 ';
259 | }
260 | if(version_compare(PHP_VERSION,'7.1.0','<')){
261 | $check[3]='
不支持 ';
262 | $install=false;
263 | }else{
264 | $check[3]='
支持 ';
265 | }
266 |
267 | ?>
268 |
269 | PHP版本>=7.1
270 | PDO_MYSQL组件
271 | CURL组件
272 | 主目录写入权限
273 | 成功安装后安装文件就会锁定,如需重新安装,请手动删除install目录下install.lock配置文件!
274 | 检测通过,下一步 ';
276 | ?>
277 |
278 |
279 |
280 |
281 |
284 |
285 |
286 |
287 |
288 |
289 |
--------------------------------------------------------------------------------
/install/install.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS `weiboapi_config`;
2 | CREATE TABLE `weiboapi_config` (
3 | `k` varchar(32) NOT NULL,
4 | `v` text NULL,
5 | PRIMARY KEY (`k`)
6 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
7 |
8 | INSERT INTO `weiboapi_config` VALUES ('admin_user', 'admin');
9 | INSERT INTO `weiboapi_config` VALUES ('admin_pwd', '123456');
10 | INSERT INTO `weiboapi_config` VALUES ('ip_type', '0');
11 | INSERT INTO `weiboapi_config` VALUES ('white_list', '');
12 | INSERT INTO `weiboapi_config` VALUES ('mail_open', '0');
13 | INSERT INTO `weiboapi_config` VALUES ('mail_cloud', '0');
14 | INSERT INTO `weiboapi_config` VALUES ('mail_smtp', 'smtp.qq.com');
15 | INSERT INTO `weiboapi_config` VALUES ('mail_port', '465');
16 | INSERT INTO `weiboapi_config` VALUES ('mail_name', '');
17 | INSERT INTO `weiboapi_config` VALUES ('mail_pwd', '');
18 | INSERT INTO `weiboapi_config` VALUES ('sitename', '微博API管理中心');
19 | INSERT INTO `weiboapi_config` VALUES ('cache_time', '300');
20 | INSERT INTO `weiboapi_config` VALUES ('cache_clean', '');
21 |
22 |
23 | DROP TABLE IF EXISTS `weiboapi_account`;
24 | CREATE TABLE `weiboapi_account` (
25 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
26 | `uid` varchar(15) NOT NULL,
27 | `nickname` varchar(150) NOT NULL,
28 | `loginname` varchar(100) DEFAULT NULL,
29 | `cookie_login` text DEFAULT NULL,
30 | `cookie_weibo` text DEFAULT NULL,
31 | `addtime` datetime DEFAULT NULL,
32 | `usetime` datetime DEFAULT NULL,
33 | `checktime` datetime DEFAULT NULL,
34 | `refreshtime` datetime DEFAULT NULL,
35 | `status` tinyint(1) NOT NULL DEFAULT 0,
36 | PRIMARY KEY (`id`),
37 | UNIQUE KEY `uid`(`uid`)
38 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
39 |
40 | DROP TABLE IF EXISTS `weiboapi_log`;
41 | CREATE TABLE `weiboapi_log` (
42 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
43 | `aid` int(11) NOT NULL,
44 | `action` varchar(20) NOT NULL,
45 | `time` datetime NOT NULL,
46 | PRIMARY KEY (`id`),
47 | KEY `aid` (`aid`)
48 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
49 |
50 | DROP TABLE IF EXISTS `weiboapi_cache`;
51 | CREATE TABLE `weiboapi_cache` (
52 | `key` varchar(32) NOT NULL,
53 | `data` mediumtext DEFAULT NULL,
54 | `time` int(11) NOT NULL,
55 | PRIMARY KEY (`key`)
56 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--------------------------------------------------------------------------------