-
Notifications
You must be signed in to change notification settings - Fork 5
/
Pull.php
271 lines (234 loc) · 10.7 KB
/
Pull.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* User: hewro
* Blog: www.ihewro.com
* Date: 2019/4/24
* Time: 20:43
*
* 将微博图床的图片迁移到自己的博客服务器上
*/
// ❗【使用说明】:https://github.com/ihewro/PullSinaimgtoTypecho
//【调用说明】你的博客地址/?action=pullsina&key=下面的$key变量的值
// 举个例子 http://www.ihewro.com/?action=pullsina&key=ihewro
//【变量说明】:这个变量是为了防止别人恶意调用接口设置的,调用该接口的时候key参数的值要与这个变量对应
$GLOBALS['key'] = "ihewro";
// 【变量说明】:
// false 表示执行该接口不会修改数据库内容,只会显示数据库中含有新浪图床的数目信息,
// true 表示会自动下载新浪图片图片到本地服务器并修改数据库内容
$GLOBALS['is_replace'] = false;
// 【变量说明】每次替换的数目,为了防止替换数目太多一直处于等待状态,你可以将这个变量设置较小的值,多次调用该接口
$GLOBALS['limit'] = 9999;
//这个变量请勿修改值
$GLOBALS['haveNum'] = 0;//已经替换的图片数目
$options = Helper::options();
$GLOBALS['blog_url'] = $options->rootUrl;
$GLOBALS['patten'] = '/(https|http):\/\/[^\s|\"|\)]+sinaimg\.cn[^\s|\"|\)]+/';
function getDataFromWebUrl($url){
$file_contents = "";
if (function_exists('file_get_contents')) {
$file_contents = @file_get_contents($url);
}
if ($file_contents == "") {
$ch = curl_init();
$timeout = 30;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
}
return $file_contents;
}
if ($_SERVER["REQUEST_METHOD"] == "GET") {
$action = @$_GET['action'];
if($action == "pullsina"){
$key = @$_GET['key'];
if ($GLOBALS['key'] == $key){
//显示提示信息
if ($GLOBALS['is_replace']){
print_l("开始执行新浪图床拉取到本地服务器……@ihewro",3,"normal");
}else{
print_l("下面为你的博客包含新浪图片的列表,本次操作不会替换和修改数据库,请修改「is_replace」变量为true进行执行……@ihewro",3,"underline","注意");
}
$db = Typecho_Db::get();//获取数据库对象
//替换文章和独立页面
$sql_content = $db->select('text','cid')->from('table.contents')//查询文章
->where('text like ?', "%sinaimg.cn%");
$content = $db->fetchAll($sql_content);
print_l(count($content)."篇文章含有新浪图床的图片",2,"normal","文章&&独立页面");
$index = 1;
foreach ($content as $item){
if ($GLOBALS['haveNum'] > $GLOBALS['limit']){
break;
}
print_l("替换第".$index."篇文章的图片(cid=".$item['cid'].")",1,"underline","开始");
$text = $item['text'];//不能转换成HTML,否则会导致数据库markdown语法失效
//维护这三种方式的正则表达式太麻烦了,难以确保适合任何情况,直接暴力匹配新浪图片的URL即可,因为一般都是用新浪图床做图片的吧,没其他用途……
/*//替换text中HTML图片结构
$text = preg_replace_callback('/<img.*?src="(.*?sinaimg\.cn.*?)"(.*?)(alt="(.*?)")??(.*?)\/?>/',"replaceImage",
$text);
//替换text中的markdown1图片结构 ![xxx](xxx.jpg)
$text = preg_replace_callback('/\!\[.*\]\((.*?sinaimg\.cn.*?)\)/',"replaceImage",
$text);
//替换text中的markdown2图片结构 ![xxx][1] [1]:
$text = preg_replace_callback('/\[\d\]:\s(.*?sinaimg\.cn.*)\n?/',"replaceImage",
$text);*/
$text = preg_replace_callback($GLOBALS['patten'],"replaceImage",$text);
//写数据库
if ($GLOBALS['is_replace']){
$db->query($db->update('table.contents')->rows(array('text' => $text))->where('cid = ?', $item['cid']));
}
print_l("替换第".$index."篇文章的所有图片",3,"underline","成功");
$index ++;
}
//替换评论
$sql_comment = $db->select('text','coid')->from('table.comments')//查询评论
->where('text like ?', "%sinaimg.cn%");
$comment = $db->fetchAll($sql_comment);
print_l(count($comment)."条评论含有新浪图床的图片",2,"normal","评论");
$index = 1;
foreach ($comment as $item){
if ($GLOBALS['haveNum'] > $GLOBALS['limit']){
break;
}
print_l("替换第".$index."条评论的图片",1,"underline","开始");
$text = $item['text'];//不能转换成HTML,否则会导致数据库markdown语法失效
$text = preg_replace_callback($GLOBALS['patten'],"replaceImage",$text);
//写数据库
if ($GLOBALS['is_replace']){
$db->query($db->update('table.comments')->rows(array('text' => $text))->where('coid = ?', $item['coid']));
}
print_l("替换第".$index."条评论的所有图片",3,"underline","成功");
$index ++;
}
//替换字段
$sql_fields = $db->select('str_value','cid','name')->from('table.fields')//查询评论
->where('str_value like ?', "%sinaimg.cn%");
$fields = $db->fetchAll($sql_fields);
print_l(count($fields)."个字段含有新浪图床的图片",2,"normal","评论");
$index = 1;
foreach ($fields as $item){
if ($GLOBALS['haveNum'] > $GLOBALS['limit']){
break;
}
print_l("替换第".$index."个字段的图片",1,"underline","开始");
$text = $item['str_value'];//不能转换成HTML,否则会导致数据库markdown语法失效
$text = preg_replace_callback($GLOBALS['patten'],"replaceImage",$text);
//写数据库
if ($GLOBALS['is_replace']){
$db->query($db->update('table.fields')->rows(array('str_value' => $text))->where('cid = ? and name = ?',
$item['cid'],$item['name']));
}
print_l("替换第".$index."个字段的所有图片",3,"underline","成功");
$index ++;
}
//替换设置里面
$sql_options = $db->select('value','user','name')->from('table.options')//查询评论
->where('value like ?', "%sinaimg.cn%");
$options = $db->fetchAll($sql_options);
print_l(count($options)."个设置项含有新浪图床的图片",2,"normal","评论");
$index = 1;
foreach ($options as $item){
if ($GLOBALS['haveNum'] > $GLOBALS['limit']){
break;
}
print_l("替换第".$index."个设置的图片",1,"underline","开始");
$text = $item['value'];//需要先进行反序列化替换后再序列化
//一定不能对序列化的字符串直接操作,否则导致对象错误❌
$array = @unserialize($text);
if (count($array) == 0 || count($array) == 1){
print_l("当前[".$item['name']."设置数据结构有问题,无法替换",1);
}else{
foreach ($array as $key => $value){
if (is_array($value)){
foreach ($value as $key2 => $vvalue){
$array[$key][$key2] = preg_replace_callback($GLOBALS['patten'],"replaceImage",$vvalue);
}
}else{
$array[$key] = preg_replace_callback($GLOBALS['patten'],"replaceImage",$value);
}
}
$text = serialize($array);//序列化
//写数据库
if ($GLOBALS['is_replace']){
$db->query($db->update('table.options')->rows(array('value' => $text))->where('user = ? and name = ?',
$item['user'],$item['name']));
}
}
print_l("替换第".$index."个设置的所有图片",3,"underline","成功");
$index ++;
}
}else{
echo "你的key变量配置错误,无法鉴权,请联系博客主人。";
}
die();
}
}
/**
* @param string $str
* @param int $num 换行的格式
* @param string $type 打印的格式,underline 表示强调输出,normal 表示普通打印
* @param string $prefix 前缀
* @param string $suffix 后缀
*/
function print_l($str,$num = 1,$type = "normal",$prefix = "",$suffix = ""){
//按照要求输出字符串
if (trim($prefix) != ""){
$prefix = "【".$prefix."】";
}
if (trim($suffix) != ""){
$suffix = "【".$suffix."】";
}
if ($type == "underline"){
print_r("----------".$prefix."----------");
}
print_r($str);
if ($type == "underline"){
print_r("----------".$suffix."----------");
}
for ($i = 0; $i< $num; $i++){
print_r("</br>"."\n");
}
//TODO:可以在打印的同时写到log文件里
}
function replaceImage($matches){
$url = $matches[0];
if ($GLOBALS['haveNum'] <= $GLOBALS['limit']){
$GLOBALS['haveNum'] ++;
if ($GLOBALS['is_replace']){//上传并替换
$url = uploadPic($url);
print_l($matches[0]."已替换成".$url,1);
return $url;
}else{//不替换
print_l($url,1);
return $url;
}
}else{
return $url;//不替换
}
}
/**
* @param $pic
* @return string
*/
function uploadPic($pic){
$suffix = ".jpg";//新浪图床的图片都是jpg后缀
$blogUrl = $GLOBALS['blog_url'];
$name = uniqid();
$DIRECTORY_SEPARATOR = "/";
$childDir = $DIRECTORY_SEPARATOR.'usr'.$DIRECTORY_SEPARATOR.'uploads' . $DIRECTORY_SEPARATOR .'sina'
.$DIRECTORY_SEPARATOR;
$dir = __TYPECHO_ROOT_DIR__ . $childDir;
if (!file_exists($dir)){
mkdir($dir, 0777, true);
}
$fileName = $name. $suffix;
$file = $dir .$fileName;
//开始捕捉
$img = getDataFromWebUrl($pic);
$fp2 = fopen($file , "a");
fwrite($fp2, $img);
fclose($fp2);
return $blogUrl.$childDir.$fileName;
}