From 4240f550d9fe070525557133c96e0f1ee4f55873 Mon Sep 17 00:00:00 2001 From: ghol Date: Fri, 9 Jan 2026 23:18:00 +0000 Subject: [PATCH] =?UTF-8?q?vmess=E6=89=B9=E9=87=8F=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- z.ai/ip-replace/vmess-editor.php | 521 +++++++++++++++++++++++++++++++ 1 file changed, 521 insertions(+) create mode 100644 z.ai/ip-replace/vmess-editor.php diff --git a/z.ai/ip-replace/vmess-editor.php b/z.ai/ip-replace/vmess-editor.php new file mode 100644 index 0000000..69b02d5 --- /dev/null +++ b/z.ai/ip-replace/vmess-editor.php @@ -0,0 +1,521 @@ + 0) { + $b64 .= str_repeat('=', 4 - $mod); + } + + $json_str = base64_decode($b64, true); + if ($json_str === false) { + return [false, null]; + } + + $data = json_decode($json_str, true); + if (!is_array($data)) { + return [false, null]; + } + + return [true, $data]; +} + +// 将配置重新编码为 vmess 行 +function build_vmess_line(array $data): string { + $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $b64 = base64_encode($json); + return 'vmess://' . $b64; +} + +// 标准 vmess 字段定义(显示顺序 + 中文说明) +$vmess_fields = [ + 'ps' => '备注(ps)', + 'add' => '地址(add)', + 'port' => '端口(port)', + 'id' => 'UUID(id)', + 'aid' => '额外ID(aid)', + 'scy' => '加密方式(scy)', + 'net' => '网络(net)', + 'type' => '伪装类型(type)', + 'host' => 'Host(host)', + 'path' => '路径(path)', + 'tls' => 'TLS(tls)', + 'sni' => 'SNI(sni)', + 'alpn' => 'ALPN(alpn)', + 'insecure' => 'insecure', +]; + +// ===== 控制流程变量 ===== +$mode = 'input'; // input | edit | result +$original_text = ''; +$result_text = ''; +$gost_text = ''; +$vmess_rows = []; // 仅合法 vmess 行的解析结果 +$other_lines = []; // 非 vmess 行或解析失败的行 +$target_ip = ''; +$batch_from = ''; +$batch_to = ''; +$batch_ip_from = ''; +$batch_ip_to = ''; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $step = $_POST['step'] ?? 'input'; + $target_ip = trim($_POST['target_ip'] ?? ''); + $batch_from = trim($_POST['batch_from'] ?? ''); + $batch_to = trim($_POST['batch_to'] ?? ''); + $batch_ip_from = trim($_POST['batch_ip_from'] ?? ''); + $batch_ip_to = trim($_POST['batch_ip_to'] ?? ''); + + if ($step === 'upload') { + // 第一步:用户粘贴 vmess 列表,进入“表格编辑模式” + $original_text = trim($_POST['content'] ?? ''); + if ($original_text !== '') { + $lines = preg_split("/\r\n|\n|\r/", $original_text); + foreach ($lines as $line) { + $raw = trim($line); + if ($raw === '') { + continue; + } + [$ok, $data] = parse_vmess_line($raw); + if (!$ok) { + $other_lines[] = $raw; + continue; + } + + // 拆分成标准字段 + 额外字段 + $fields = []; + foreach ($vmess_fields as $key => $_label) { + $fields[$key] = isset($data[$key]) ? (string)$data[$key] : ''; + } + $extra = array_diff_key($data, $vmess_fields); + + $vmess_rows[] = [ + 'fields' => $fields, + 'extra' => !empty($extra) + ? json_encode($extra, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) + : '', + ]; + } + } + $mode = 'edit'; + } elseif ($step === 'save') { + // 第二步:从表格接收编辑后的数据,生成最终 vmess 列表 + $rows_post = $_POST['rows'] ?? []; + $other_lines = []; + $other_raw = trim($_POST['other_lines'] ?? ''); + if ($other_raw !== '') { + $other_lines = preg_split("/\r\n|\n|\r/", $other_raw); + } + + $lines_out = []; + $gost_lines_out = []; + + // 从表格重建 JSON + foreach ($rows_post as $row) { + $fields = $row['fields'] ?? []; + $extra_json = $row['extra'] ?? ''; + + $data = []; + foreach ($vmess_fields as $key => $_label) { + if (isset($fields[$key]) && $fields[$key] !== '') { + $data[$key] = $fields[$key]; + } + } + + if ($extra_json !== '') { + $extra = json_decode($extra_json, true); + if (is_array($extra)) { + $data = array_merge($data, $extra); + } + } + + // 批量替换(提交阶段再兜底跑一遍) + if ($target_ip !== '') { + $data['add'] = $target_ip; + } + + if ($batch_from !== '' && $batch_to !== '') { + array_walk_recursive($data, function (&$value) use ($batch_from, $batch_to) { + if (is_string($value) && $value !== '') { + $value = str_replace($batch_from, $batch_to, $value); + } + }); + } + + if ($batch_ip_from !== '' && $batch_ip_to !== '' && isset($data['add'])) { + $data['add'] = str_replace($batch_ip_from, $batch_ip_to, (string)$data['add']); + } + + // 构建 vmess 行 + $lines_out[] = build_vmess_line($data); + + // 构建对应的 Gost 配置行(端口使用当前记录的 port 字段) + $ip_for_gost = isset($data['add']) ? (string)$data['add'] : ''; + $port_for_gost = isset($data['port']) ? (string)$data['port'] : ''; + if ($ip_for_gost !== '' && $port_for_gost !== '') { + if (strpos($ip_for_gost, ':') === false) { + // IPv4 + $gost_lines_out[] = 'nonencrypt/' . $port_for_gost . '#' . $ip_for_gost . '#' . $port_for_gost; + } else { + // IPv6,添加方括号 + $ip = $ip_for_gost; + if ($ip[0] !== '[') { + $ip = '[' . $ip . ']'; + } + $gost_lines_out[] = 'nonencrypt/' . $port_for_gost . '#' . $ip . '#' . $port_for_gost; + } + } else { + $gost_lines_out[] = ''; + } + } + + // 把无法解析的其它行也保留在结果中 + foreach ($other_lines as $raw) { + $raw = trim($raw); + if ($raw !== '') { + $lines_out[] = $raw; + } + } + + $result_text = implode(PHP_EOL, $lines_out); + $gost_text = implode(PHP_EOL, $gost_lines_out); + $mode = 'result'; + } +} else { + // 默认示例文本 + $original_text = "vmess://ew0KICAidiI6ICIyIiwNCiAgInBzIjogIkFsaVBDLUdHWS1TaGFyZS1CZXN0dm0tU0ciLA0KICAiYWRkIjogIjEuMS4xLjEiLA0KICAicG9ydCI6ICIzMzg4OCIsDQogICJpZCI6ICI3N2MwYWFmZC03MTNhLTQwZDUtYmI2MS1mZWMyN2JiMTI0MTEiLA0KICAiYWlkIjogIjAiLA0KICAic2N5IjogImF1dG8iLA0KICAibmV0IjogInRjcCIsDQogICJ0eXBlIjogIm5vbmUiLA0KICAiaG9zdCI6ICIiLA0KICAicGF0aCI6ICIiLA0KICAidGxzIjogIiIsDQogICJzbmkiOiAiIiwNCiAgImFscG4iOiAiIiwNCiAgImZwIjogIiIsDQogICJpbnNlY3VyZSI6ICIwIg0KfQ=="; + $mode = 'input'; +} +?> + + + + + + + vmess 批量编辑与替换工具 + + + +
+

vmess 批量编辑与替换工具

+ + +
+ + +
+

① 粘贴 vmess 分享地址(每行一条)

+ +
提交后会进入类似 Excel 的表格界面,可以逐行编辑字段。
+
+ + +
+ + +
+ + +
+

② 全局批量替换设置(可选)

+
+
+
+ + +
留空则不修改 IP。
+
+
+ + +
+ +
+ 点击下方按钮可在当前表格中直接替换,不提交到服务器。 +
+ +
+
+
+
+ + +
+ +
+ 点击按钮仅在 IP 列(add)中替换,方便从一台机器迁移到另一台。 +
+ +
+
+
+
+ +
+

③ 表格编辑(类似 Excel,可逐行修改任意字段)

+
+ + + + + $label): ?> + + + + + + $row): ?> + + + $label): ?> + + + + + + + +
#
+ +
+
+ +
+ 下列行无法识别为 vmess,将原样保留在结果中(如需要可自行编辑后粘贴回上一步): +
+ + "> + + + +
+ +
+ +
+
+ + + + +
+

④ 生成结果

+
+
+ + +
+
+ + +
示例:IPv4 => nonencrypt/33888#1.1.1.1#33888;IPv6 => nonencrypt/22777#[2403:2c80::1]#22777(端口都取自各自 vmess 的 port)。
+
+
+
+
+ + +
+
+
+ +
+ +