跳至正文

ooooooooooooooooooooooo.ooo url长网址生成

今天在某群里无聊刷信息的时候发现了这个链接:

没错,自导自演,因为忘记截图了

出于好奇的本能,我点开了这个链接,发现跳转到了朋友的博客,于是我就去访问了根目录的url,看起来页面是长这个样子的

我们不难可以直接看出这就是制造长链接的地方了,出于刨根问到底的精神,我去看了一下它的主要源码

该项目的github主页
// https://github.com/lucaceriani/ooo/blob/main/worker.js
/**
 * V1 of OOO - cloudflare worker to redirect traffic to correct url
 */
class OOO {
    enc = ["o", "ο", "о", "ᴏ"]
    //           006f 03bf 043e 1d0f
    dec = {
        "o": "0",
        "ο": "1",
        "о": "2",
        "ᴏ": "3"
    }

    ver = {
        "oooo": true
    }

    currVer = "oooo"

    removeAndCheckVersion(ooo) {
        if (this.ver[ooo.substring(0, 4)]) {
            return ooo.substring(4)
        } else {
            return null
        }
    }

    addVersion(ooo) {
        return this.currVer + ooo
    }

    encodeUrl(url) {
        // get utf8 array
        let unversioned = this.toUTF8Array(url)
            // convert to string with base 4
            // padstart very important! otherwise missing leading 0s
            .map(n => n.toString(4).padStart(4, "0"))
            // convert to array of characters
            .join("").split("")
            // map to the o's
            .map(x => this.enc[parseInt(x)])
            // join into single string
            .join("")

        return this.addVersion(unversioned)
    }

    decodeUrl(ooo) {

        ooo = this.removeAndCheckVersion(ooo)
        if (ooo === null) return

        // get the base 4 string representation of the url
        let b4str = ooo.split("").map(x => this.dec[x]).join("")

        let utf8arr = []

        // parse 4 characters at a time (255 in b10 = 3333 in b4)
        // remember adding leading 0s padding
        for (let i = 0; i < b4str.length; i += 4)
            utf8arr.push(parseInt(b4str.substring(i, i + 4), 4))

        return this.Utf8ArrayToStr(utf8arr)
    }


    // from https://gist.github.com/joni/3760795
    toUTF8Array(str) {
        var utf8 = [];
        for (var i = 0; i < str.length; i++) {
            var charcode = str.charCodeAt(i);
            if (charcode < 0x80) utf8.push(charcode);
            else if (charcode < 0x800) {
                utf8.push(0xc0 | (charcode >> 6),
                    0x80 | (charcode & 0x3f));
            }
            else if (charcode < 0xd800 || charcode >= 0xe000) {
                utf8.push(0xe0 | (charcode >> 12),
                    0x80 | ((charcode >> 6) & 0x3f),
                    0x80 | (charcode & 0x3f));
            }
            // surrogate pair
            else {
                i++;
                charcode = ((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff)
                utf8.push(0xf0 | (charcode >> 18),
                    0x80 | ((charcode >> 12) & 0x3f),
                    0x80 | ((charcode >> 6) & 0x3f),
                    0x80 | (charcode & 0x3f));
            }
        }
        return utf8;
    }

    // from https://gist.github.com/wumingdan/759564f6cb887a55bceb
    Utf8ArrayToStr(array) {
        var out, i, len, c;
        var char2, char3;

        out = "";
        len = array.length;
        i = 0;
        while (i < len) {
            c = array[i++];
            switch (c >> 4) {
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    // 0xxxxxxx
                    out += String.fromCharCode(c);
                    break;
                case 12: case 13:
                    // 110x xxxx   10xx xxxx
                    char2 = array[i++];
                    out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14:
                    // 1110 xxxx  10xx xxxx  10xx xxxx
                    char2 = array[i++];
                    char3 = array[i++];
                    out += String.fromCharCode(((c & 0x0F) << 12) |
                        ((char2 & 0x3F) << 6) |
                        ((char3 & 0x3F) << 0));
                    break;
            }
        }

        return out;
    }

}

async function handleRequest(request) {
  let reqUrl = new URL(request.url)
  let redirectLocation = new OOO().decodeUrl(decodeURI(reqUrl.pathname.replace("/", "")))
  
  let response;
  try {
    response = Response.redirect(redirectLocation, 302)
  } catch(e) {
    response = new Response(null, {status: 400})
  }

  return response
}

addEventListener("fetch", async event => {
  event.respondWith(handleRequest(event.request))
})

看完之后,原理也就浮出水面了。实现非常简单,通过建立OOO类,并调用.decodeUrl和相关函数及方法

006f 03bf 043e 1d0f(实际上他们长得都像o)这四个字符通过不同的排列组合,生成新的长url

同理,绝大部分短链接也是这个原理

4
为博客质量打分

给我的博客打个分吧,喜欢的话还请多多支持!

Please add vote reason
标签:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注