From 0d39a81fe4754fc2624873459f7d1aab0b33dcdd Mon Sep 17 00:00:00 2001 From: spirit Date: Wed, 4 Dec 2019 20:35:35 +0800 Subject: [PATCH] encrypt QQ avatar link --- functions.php | 45 +++++++++++++++++----- inc/api.php | 88 ++++++++++++++++++++++++++++++++------------ manifest/manifest.py | 86 ++++++++++++++++++++++++++++++------------- options.php | 7 ++++ 4 files changed, 168 insertions(+), 58 deletions(-) diff --git a/functions.php b/functions.php index 19844fd..1810e82 100644 --- a/functions.php +++ b/functions.php @@ -1616,11 +1616,17 @@ function output_comments_qq_columns( $column_name, $comment_id ){ */ add_filter( 'get_avatar', 'change_avatar', 10, 3 ); function change_avatar($avatar){ - global $comment; + global $comment,$sakura_pubkey; if ($comment) { if( get_comment_meta( $comment->comment_ID, 'new_field_qq', true )){ $qq_number = get_comment_meta( $comment->comment_ID, 'new_field_qq', true ); - return '😀'; + if(akina_option('qq_avatar_link')){ + openssl_public_encrypt($qq_number, $encrypted, openssl_pkey_get_public($sakura_pubkey)); + $qq_number = urlencode(base64_encode($encrypted)); + return '😀'; + }else{ + return '😀'; + } }else{ return $avatar ; } @@ -1728,20 +1734,39 @@ function create_sakura_table(){ PRIMARY KEY (`mate_key`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;"); //default data - $manifest = array( - "mate_key" => "manifest_json", - "mate_value" => file_get_contents(get_template_directory()."/manifest/manifest.json") - ); - $time = array( - "mate_key" => "json_time", - "mate_value" => date("Y-m-d H:i:s",time()) - ); if ( !$wpdb->get_var("SELECT COUNT(*) FROM $sakura_table_name WHERE mate_key = 'manifest_json'") ){ + $manifest = array( + "mate_key" => "manifest_json", + "mate_value" => file_get_contents(get_template_directory()."/manifest/manifest.json") + ); $wpdb->insert($sakura_table_name,$manifest); } if ( !$wpdb->get_var("SELECT COUNT(*) FROM $sakura_table_name WHERE mate_key = 'json_time'") ){ + $time = array( + "mate_key" => "json_time", + "mate_value" => date("Y-m-d H:i:s",time()) + ); $wpdb->insert($sakura_table_name,$time); } + if ( !$wpdb->get_var("SELECT COUNT(*) FROM $sakura_table_name WHERE mate_key = 'privkey'") ){ + $privkey = array( + "mate_key" => "privkey", + "mate_value" => file_get_contents(get_template_directory()."/manifest/private.key") + ); + $wpdb->insert($sakura_table_name,$privkey); + } + if ( !$wpdb->get_var("SELECT COUNT(*) FROM $sakura_table_name WHERE mate_key = 'pubkey'") ){ + $pubkey = array( + "mate_key" => "pubkey", + "mate_value" => file_get_contents(get_template_directory()."/manifest/public.key") + ); + $wpdb->insert($sakura_table_name,$pubkey); + } + //reduce sql query + global $sakura_image_array,$sakura_privkey,$sakura_pubkey; + $sakura_image_array = $wpdb->get_var("SELECT `mate_value` FROM `wp_sakura` WHERE `mate_key`='manifest_json'"); + $sakura_privkey = $wpdb->get_var("SELECT `mate_value` FROM `wp_sakura` WHERE `mate_key`='privkey'"); + $sakura_pubkey = $wpdb->get_var("SELECT `mate_value` FROM `wp_sakura` WHERE `mate_key`='pubkey'"); } add_action( 'after_setup_theme', 'create_sakura_table' ); diff --git a/inc/api.php b/inc/api.php index 1450261..20db90c 100644 --- a/inc/api.php +++ b/inc/api.php @@ -20,18 +20,23 @@ add_action('rest_api_init', function () { 'methods' => 'GET', 'callback' => 'feature_gallery', )); - register_rest_route('sakura/v1', '/image/manifest', array( + register_rest_route('sakura/v1', '/database/update', array( 'methods' => 'POST', - 'callback' => 'update_manifest_json', + 'callback' => 'update_database', )); register_rest_route('sakura/v1', '/qqinfo/json', array( 'methods' => 'GET', 'callback' => 'get_qq_info', )); + register_rest_route('sakura/v1', '/qqinfo/avatar', array( + 'methods' => 'GET', + 'callback' => 'get_qq_avatar', + )); }); /** * QQ info + * https://sakura.2heng.xin/wp-json/sakura/v1/qqinfo/json */ function get_qq_info(WP_REST_Request $request) { @@ -337,8 +342,8 @@ EOS; * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/image/cover */ function cover_gallery() { - global $wpdb; - $img_array = json_decode($wpdb->get_var("SELECT `mate_value` FROM `wp_sakura` WHERE `mate_key`='manifest_json'"), true); + global $wpdb,$sakura_image_array; + $img_array = json_decode($sakura_image_array, true); $img = array_rand($img_array); $img_domain = akina_option('cover_cdn') ? akina_option('cover_cdn') : get_template_directory_uri(); if(strpos($_SERVER['HTTP_ACCEPT'], 'image/webp')) { @@ -358,8 +363,8 @@ function cover_gallery() { * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/image/feature */ function feature_gallery() { - global $wpdb; - $img_array = json_decode($wpdb->get_var("SELECT `mate_value` FROM `wp_sakura` WHERE `mate_key`='manifest_json'"), true); + global $wpdb,$sakura_image_array; + $img_array = json_decode($sakura_image_array, true); $img = array_rand($img_array); $img_domain = akina_option('cover_cdn') ? akina_option('cover_cdn') : get_template_directory_uri(); if(strpos($_SERVER['HTTP_ACCEPT'], 'image/webp')) { @@ -375,10 +380,10 @@ function feature_gallery() { } /* - * update manifest.json rest api - * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/image/json + * update database rest api + * @rest api接口路径:https://sakura.2heng.xin/wp-json/sakura/v1/database/update */ -function update_manifest_json() { +function update_database() { $username = $_SERVER['PHP_AUTH_USER']; $password = $_SERVER['PHP_AUTH_PW']; $user = wp_authenticate($username, $password); @@ -386,24 +391,45 @@ function update_manifest_json() { if (in_array('administrator', (array) $user->roles)) { global $wpdb; $sakura_table_name = $wpdb->base_prefix.'sakura'; - $manifest = array( - "key" => "manifest_json", - "value" => file_get_contents($_FILES["manifest"]["tmp_name"]) - ); - $time = array( - "key" => "json_time", - "value" => date("Y-m-d H:i:s",time()) - ); - - $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='manifest_json'"); - $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='json_time'"); - $wpdb->insert($sakura_table_name,$manifest); - $wpdb->insert($sakura_table_name,$time); + if(isset($_FILES["manifest"])) { + $manifest = array( + "key" => "manifest_json", + "value" => file_get_contents($_FILES["manifest"]["tmp_name"]) + ); + $time = array( + "key" => "json_time", + "value" => date("Y-m-d H:i:s",time()) + ); + $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='manifest_json'"); + $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='json_time'"); + $wpdb->insert($sakura_table_name,$manifest); + $wpdb->insert($sakura_table_name,$time); + $message = "manifest.json has been stored into database."; + } + if(isset($_FILES["rsa"])){ + if($_FILES["rsa"]["name"]=="public.key"){ + $pubkey = array( + "mate_key" => "pubkey", + "mate_value" => file_get_contents($_FILES["rsa"]["tmp_name"]) + ); + $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='pubkey'"); + $wpdb->insert($sakura_table_name,$pubkey); + } + if($_FILES["rsa"]["name"]=="private.key"){ + $privkey = array( + "mate_key" => "privkey", + "mate_value" => file_get_contents($_FILES["rsa"]["tmp_name"]) + ); + $wpdb->query("DELETE FROM `wp_sakura` WHERE `mate_key` ='privkey'"); + $wpdb->insert($sakura_table_name,$privkey); + } + $message = "key pairs has been stored into database."; + } $output = array( 'status' => 200, 'success' => true, - 'message' => 'manifest.json has been stored into database' + 'message' => $message ); $result = new WP_REST_Response($output, 200); $result->set_headers(array('Content-Type' => 'application/json')); @@ -420,3 +446,19 @@ function update_manifest_json() { return $result; } } + +/** + * QQ头像链接解密 + */ +function get_qq_avatar(){ + global $sakura_privkey; + $qq_number=$_GET["qq"]; + $encrypted = urldecode(base64_decode($qq_number)); + openssl_private_decrypt($encrypted, $qq_number, openssl_pkey_get_private($sakura_privkey)); + preg_match('/^\d{3,}$/', $qq_number, $matches); + $imgurl='https://q2.qlogo.cn/headimg_dl?dst_uin='.$matches[0].'&spec=100'; + $response = new WP_REST_Response(); + $response->set_status(302); + $response->header('Location', $imgurl); + return $response; +} diff --git a/manifest/manifest.py b/manifest/manifest.py index 4504583..941b3fd 100644 --- a/manifest/manifest.py +++ b/manifest/manifest.py @@ -10,6 +10,7 @@ import json import requests import base64 import hashlib +from Crypto.PublicKey import RSA from PIL import Image class Single(object): @@ -43,47 +44,82 @@ class Single(object): 'webp': [self.webp, self.webp_th] } - #这个最好新建一个类 - def upload_manifest(self): - username = input('Enter your username: ') - password = input('Enter your password: ') - url = input('Enter your rest api url: ') - data_string = username + ':' + password + def main(self): + self.hash() + # if os.path.exists(self.jpeg) and os.path.exists(self.webp): + self.optimize() + self.manifest() + return self.mani + + +class Upload2Wordpress: + def __init__(self, username, password, url): + self.username = username + self.password = password + self.url = url + + def upload(self, file, field): + data_string = self.username + ':' + self.password token = base64.b64encode(data_string.encode()).decode('utf-8') headers = { 'Authorization': 'Basic ' + token, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97" } - files = {'manifest': open('manifest.json', mode="rb")} - reply = requests.post(url, headers=headers, files=files) + files = {field: open(file, mode="rb")} + reply = requests.post(self.url, headers=headers, files=files) print(json.loads(reply.content)['message']) - def main(self): - self.hash() - # if os.path.exists(self.jpeg) and os.path.exists(self.webp): - self.optimize() - self.thumbnail() - self.manifest() - return self.mani + def upload_manifest(self): + print('start uploading `manifest.json`...') + self.upload('manifest.json', 'manifest') -def main(): + def upload_key(self): + print('start uploading `private.key`...') + self.upload('private.key', 'rsa') + print('start uploading `public.key`...') + self.upload('public.key', 'rsa') + + def main(self): + self.upload_manifest() + self.upload_key() + + +def gen_manifest_json(): onlyfiles = [f for f in os.listdir('gallary') if os.path.isfile(os.path.join('gallary', f))] id = 1 Manifest = {} - for f in onlyfiles: - worker = Single(f, Manifest) - Manifest = worker.main() - print(str(id) + '/' + str(len(onlyfiles))) - id += 1 - + worker = Single(f, Manifest) + Manifest = worker.main() + print(str(id) + '/' + str(len(onlyfiles))) + id += 1 with open('manifest.json', 'w+') as json_file: json.dump(Manifest, json_file) - up_json = Single(f, Manifest) - up_json.upload_manifest() + +def gen_key_pairs(): + key = RSA.generate(1024) + pv_key_string = key.exportKey() + with open("private.key", "w+") as prv_file: + print("{}".format(pv_key_string.decode()), file=prv_file) + pb_key_string = key.publickey().exportKey() + with open("public.key", "w+") as pub_file: + print("{}".format(pb_key_string.decode()), file=pub_file) + + +def main(): + gen_manifest_json() + if not os.path.exists("public.key") or not os.path.exists("private.key"): + print("start generating key pairs...") + gen_key_pairs() + username = input('Enter your username: ') + password = input('Enter your password: ') + url = input('Enter your rest api url: ') + upload = Upload2Wordpress(username, password, url) + upload.main() + if __name__ == '__main__': main() - key = input('`manifest.json` saved. Press any key to quit.') + key = input('`manifest.json` saved. Press any key to quit.') quit() diff --git a/options.php b/options.php index a9171a7..e659e49 100644 --- a/options.php +++ b/options.php @@ -1135,6 +1135,13 @@ function optionsframework_options() { 'std' => '0', 'type' => 'checkbox'); + $options[] = array( + 'name' => __('QQ avatar link encryption', 'sakura'),/*QQ头像链接加密*/ + 'desc' => __('Check to enable, do not display the user\'s qq avatar links directly.', 'sakura'),/*勾选开启,不直接暴露用户qq头像链接*/ + 'id' => 'qq_avatar_link', + 'std' => '0', + 'type' => 'checkbox'); + $options[] = array( 'name' => __('Comment UA infomation', 'sakura'),/*评论UA信息*/ 'desc' => __('Check to enable, display the user\'s browser, operating system information', 'sakura'),/*勾选开启,显示用户的浏览器,操作系统信息*/