从字符串重新创建HTML文档的正确方法

Correct way to recreate HTML document from a string?

本文关键字:文档 HTML 方法 创建 字符串 新创建      更新时间:2023-09-26

首先,我很便宜!:)我买不起我的域的静态IP,也买不起那些花哨的证书。。。所以我没有SSL/HTTPS。

我试图在这里实现的是推出我自己的"HTTP加密"。以下是我迄今为止所取得的成就:

  1. 修改了现有的代理脚本(Glype/PHProxy)以"加密"(目前为base64)回声输出。(顺便说一句,我正在将整个内容包装在一个body元素中)
  2. 编写了一个GreaseMonkey脚本来"解密"加密的输出

这个东西在简单的网站上运行。但是,当我加载复杂的网站(比如浏览器游戏)时,java脚本会被破坏(顺便说一句,当我关闭加密时,脚本可以完美地渲染游戏)。

通过FireBug进行检查后,我注意到head元素的内容被放置在body元素中。这种情况并不总是发生,所以我怀疑PHP抛出了格式错误的输出,但我使用离线工具解码了base64,HTML看起来还可以。

以下是PHP的示例输出:

<html><body>PGh0bWw+DQo8aGVhZD4NCjx0aXRsZT5IZWxsbzwvdGl0bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxoMT5IZWxsbyBXb3JsZDwvaDE+DQo8L2JvZHk+DQo8L2h0bWw+</body></html>

以下是来自Firebug的解码HTML(经过GM脚本处理后):

<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

以下是我解码PHP输出的GM脚本:

function utf8_decode (str_data) {
    var tmp_arr = [],
        i = 0,
        ac = 0,
        c1 = 0,
        c2 = 0,
        c3 = 0;
    str_data += '';
    while (i < str_data.length) {
        c1 = str_data.charCodeAt(i);
        if (c1 < 128) {
            tmp_arr[ac++] = String.fromCharCode(c1);
            i++;
        } else if (c1 > 191 && c1 < 224) {
            c2 = str_data.charCodeAt(i + 1);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
            i += 2;
        } else {
            c2 = str_data.charCodeAt(i + 1);
            c3 = str_data.charCodeAt(i + 2);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }
    }
    return tmp_arr.join('');
}
function base64_decode (data) {
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
        ac = 0,
        dec = "",
        tmp_arr = [];
    if (!data) {
        return data;
    }
    data += '';
    do { // unpack four hexets into three octets using index points in b64
        h1 = b64.indexOf(data.charAt(i++));
        h2 = b64.indexOf(data.charAt(i++));
        h3 = b64.indexOf(data.charAt(i++));
        h4 = b64.indexOf(data.charAt(i++));
        bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
        o1 = bits >> 16 & 0xff;
        o2 = bits >> 8 & 0xff;
        o3 = bits & 0xff;
        if (h3 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1);
        } else if (h4 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1, o2);
        } else {
            tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
        }
    } while (i < data.length);
    dec = tmp_arr.join('');
    dec = utf8_decode(dec);
    return dec;
}
document.documentElement.innerHTML = base64_decode(document.body.innerHTML);

我认为问题是我将解码后的HTML分配给document.documentElement.innerHTML,这样做会将整个内容放在body元素中吗?

所以问题是,从字符串中重新创建HTML文档的正确方法是什么?

既然你只是基于64编码,而且正如@Battle_707所说,问题在于dom事件,为什么不发送一个重定向到数据url的页面呢。通过这种方式,浏览器应该触发所有正确的事件。

但说真的,只要拿到一个证书并登录dyndns.com,基本64就不会给你带来额外的安全性

编辑

既然你提到了迁移到AES,如果你能找到一个JS AES实现,你可以在这里使用我的建议,构建数据URL客户端并重定向到它。

function openPageFromString(html){
    location="data:text/html,"+encodeURIComponent(html);
}

您所说的"复杂"页面的问题在于它们有非常特定的DOM事件。这些事件将在浏览器第一次读取该行时触发,或在某些"断点"(如"onload")时触发。由于你混淆了代码,然后在完全下载后对其进行解码,你的浏览器不会重新读取页面来处理这些事件。也许,只是也许,你可以在页面加载后手动调用这些事件中的每个函数,但如果(某些)浏览器会让你很难做到这一点,我不会感到惊讶,因为页面是像<html><head></head><body><html>.....your decoded page....</html></body></html>一样创建的。除此之外,JS引擎甚至可能根本不会对新代码进行索引。