NewHome/func/navicat.html

195 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<script>(function(){var t;try{t=localStorage.getItem("hp-theme")}catch(e){}if(!t){t=(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)?"dark":"light"}document.documentElement.setAttribute("data-theme",t);})();</script>
<title>Navicat 密码解密</title>
<link rel="icon" href="../assets/img/logo.svg">
<link rel="stylesheet" href="../assets/css/common.css">
</head>
<body>
<div class="func-bar"><div class="wrap func-bar-inner">
<a class="btn btn-sm js-fb-back" href="index.php" title="返回功能区首页">← 返回功能区首页</a>
<span class="func-bar-title">Navicat 密码解密</span>
<a class="btn btn-sm" href="../index.php">首页</a>
</div></div>
<main class="page-main">
<div class="wrap page-body">
<div class="panel-card">
<p class="tip" style="margin-top:0">🔒 全部运算在本机浏览器完成,<b>密文 / 明文不会上传服务器</b>,可放心处理。</p>
<p class="tip" style="margin-top:4px">打开Navicat点击左上角<code>文件</code>,点击<code>导出连接</code>选项,必须选择<code>导出密码</code>然后上传ncx或者自行筛选password即可</p>
<div class="field-row" style="align-items:center;margin-top:12px">
<label class="fl" style="margin:0" for="nvVer">Navicat 版本</label>
<select id="nvVer">
<option value="12">12 及以后AES-128-CBC</option>
<option value="11">11 及以前Blowfish</option>
</select>
<div class="seg" id="nvDir">
<button type="button" data-dir="dec" class="active">解密</button>
<button type="button" data-dir="enc">加密</button>
</div>
<button type="button" class="btn btn-primary" id="nvRun">执行</button>
<button type="button" class="btn" id="nvSwap" title="把输出内容放入输入区">输出 → 输入</button>
<button type="button" class="btn" id="nvClear">清空</button>
</div>
<div id="nvMsg"></div>
</div>
<div class="panel-card">
<h2>解析 .ncx 连接文件</h2>
<p class="tip">选择 Navicat 导出的 <code>.ncx</code> 连接文件,本工具在本地解析其中全部连接并按规范格式输出;连接密码会用<b>上方所选 Navicat 版本</b>自动解密。文件不会上传服务器。</p>
<div class="field-row" style="align-items:center;flex-wrap:wrap">
<input type="file" id="nvFile" accept=".ncx,.xml,text/xml,application/xml" style="flex:1 1 280px;min-width:220px">
<button type="button" class="btn btn-primary" id="nvParse">解析文件</button>
<span class="tip" style="align-self:center">选择后自动解析;切换版本后可点“解析文件”重新解密</span>
</div>
<div id="nvFileMsg"></div>
</div>
<div class="io-area">
<div class="io-box">
<div class="io-label">
<span>输入区(密文 / 明文,可编辑)</span>
<button type="button" class="btn btn-sm js-copy" data-target="#nvIn">复制</button>
</div>
<textarea id="nvIn" placeholder="解密:粘贴十六进制密文(如 CE3AAB73CBBE383C加密输入明文密码" spellcheck="false"></textarea>
</div>
<div class="io-box">
<div class="io-label">
<span>输出区(可编辑)</span>
<button type="button" class="btn btn-sm js-copy" data-target="#nvOut">复制</button>
</div>
<textarea id="nvOut" placeholder="结果输出到这里,可手动修改后再次使用" spellcheck="false"></textarea>
</div>
</div>
</div>
</main>
<button type="button" class="theme-fab js-theme-btn" title="切换昼夜模式" aria-label="切换昼夜模式"><span class="js-theme-icon"></span></button>
<button type="button" class="theme-fab to-top js-to-top" title="返回顶部" aria-label="返回顶部"></button>
<script src="../assets/js/common.js"></script>
<script src="../assets/js/navicat.js"></script>
<script>
(function () {
'use strict';
function $(id) { return document.getElementById(id); }
var verSel = $('nvVer');
var dirButtons = Array.prototype.slice.call(document.querySelectorAll('#nvDir button'));
var nvIn = $('nvIn');
var nvOut = $('nvOut');
var nvMsg = $('nvMsg');
function activeDir() {
var b = dirButtons.filter(function (x) { return x.classList.contains('active'); })[0];
return b ? b.getAttribute('data-dir') : 'dec';
}
function setMsg(text, isErr) {
nvMsg.innerHTML = '';
if (!text) return;
var d = document.createElement('div');
d.className = isErr ? 'err-msg' : 'ok-msg';
d.textContent = text;
nvMsg.appendChild(d);
}
function busy(on) {
$('nvRun').disabled = on;
$('nvRun').textContent = on ? '处理中…' : '执行';
}
function label(dir) { return dir === 'dec' ? '解密' : '加密'; }
function run() {
var ver = verSel.value;
var dir = activeDir();
var text = nvIn.value;
if (!text) { setMsg('请先输入内容', true); nvIn.focus(); return; }
var C = window.NavicatCipher;
if (!C) { setMsg('组件未加载,请刷新页面重试', true); return; }
busy(true);
setMsg('正在' + label(dir) + '…', false);
var p = (dir === 'dec') ? C.decrypt(text, ver) : C.encrypt(text, ver);
p.then(function (out) {
nvOut.value = out;
busy(false);
if (dir === 'dec' && out && out.indexOf('\uFFFD') >= 0) {
setMsg('解密完成,但结果含乱码字符:可能是密文与所选版本不匹配,或密文不完整 / 不合法,请核对版本后重试。', true);
} else {
setMsg(label(dir) + '完成Navicat ' + ver + '', false);
}
}).catch(function (e) {
busy(false);
setMsg(label(dir) + '失败:' + (e && e.message ? e.message : e), true);
});
}
dirButtons.forEach(function (b) {
b.addEventListener('click', function () {
dirButtons.forEach(function (x) { x.classList.remove('active'); });
b.classList.add('active');
nvIn.placeholder = (b.getAttribute('data-dir') === 'dec')
? '解密:粘贴十六进制密文(如 CE3AAB73CBBE383C'
: '加密:输入明文密码';
});
});
$('nvRun').addEventListener('click', run);
$('nvSwap').addEventListener('click', function () {
if (nvOut.value) { nvIn.value = nvOut.value; setMsg('已将输出内容回填到输入区', false); }
});
$('nvClear').addEventListener('click', function () {
nvIn.value = ''; nvOut.value = ''; setMsg('', false); nvIn.focus();
});
nvIn.addEventListener('keydown', function (ev) {
if ((ev.ctrlKey || ev.metaKey) && ev.key === 'Enter') { ev.preventDefault(); run(); }
});
/* ---------- .ncx 连接文件解析 ---------- */
var nvFile = $('nvFile');
var nvFileMsg = $('nvFileMsg');
var nvParseBtn = $('nvParse');
var ncxText = '';
function setFileMsg(text, isErr) {
nvFileMsg.innerHTML = '';
if (!text) return;
var d = document.createElement('div');
d.className = isErr ? 'err-msg' : 'ok-msg';
d.textContent = text;
nvFileMsg.appendChild(d);
}
function parseBusy(on) {
nvParseBtn.disabled = on;
nvParseBtn.textContent = on ? '解析中…' : '解析文件';
}
function runNcx() {
var C = window.NavicatCipher;
if (!C) { setFileMsg('组件未加载,请刷新页面重试', true); return; }
if (!ncxText) { setFileMsg('请先选择 .ncx 文件', true); return; }
parseBusy(true);
setFileMsg('正在解析并解密…', false);
C.buildConnectionReport(ncxText, verSel.value).then(function (report) {
nvOut.value = report;
parseBusy(false);
setFileMsg('解析完成,结果已输出到下方输出区', false);
}).catch(function (e) {
parseBusy(false);
setFileMsg('解析失败:' + (e && e.message ? e.message : e), true);
});
}
nvFile.addEventListener('change', function () {
var f = nvFile.files && nvFile.files[0];
if (!f) return;
var reader = new FileReader();
reader.onload = function () { ncxText = String(reader.result || ''); setFileMsg('已读取:' + f.name, false); runNcx(); };
reader.onerror = function () { setFileMsg('文件读取失败', true); };
reader.readAsText(f, 'UTF-8');
});
nvParseBtn.addEventListener('click', runNcx);
})();
</script>
</body>
</html>