PageSourceSearch

https://pornhub-e.com/assets/91cg/image-decrypt.js?v=4

js pornhub-e.com collected 2026-09-28 01:38:14 UTC 4,377 bytes, 108 lines download raw bytes

1(() => {
2    const toBase64 = buffer => {
3        const bytes = new Uint8Array(buffer);
4        let binary = '';
5        const chunkSize = 0x8000;
6        for (let offset = 0; offset < bytes.length; offset += chunkSize) {
7            binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));
8        }
9        return btoa(binary);
10    };
11
12    const normalizeMime = extension => {
13        const value = String(extension || '').toLowerCase();
14        if (value === 'jpg') return 'jpeg';
15        return /^(?:jpeg|png|gif|webp|avif)$/i.test(value) ? value : 'jpeg';
16    };
17
18    const rawImageMime = buffer => {
19        const bytes = new Uint8Array(buffer);
20        if (bytes.length >= 6) {
21            const signature = String.fromCharCode(...bytes.subarray(0, 6));
22            if (signature === 'GIF87a' || signature === 'GIF89a') return 'gif';
23        }
24        if (bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) return 'jpeg';
25        if (bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) return 'png';
26        if (bytes.length >= 12 && String.fromCharCode(...bytes.subarray(0, 4)) === 'RIFF' &&
27            String.fromCharCode(...bytes.subarray(8, 12)) === 'WEBP') return 'webp';
28        return '';
29    };
30
31    const getImageDataUrl = buffer => {
32        const rawMime = rawImageMime(buffer);
33        if (rawMime) return `data:image/${rawMime};base64,${toBase64(buffer)}`;
34        if (typeof window.decryptImage !== 'function') return '';
35        const decrypted = window.decryptImage(toBase64(buffer));
36        return decrypted || '';
37    };
38
39    const loadEncryptedBackground = async card => {
40        const url = card.dataset.encryptedBg;
41        const background = card.querySelector('.blog-background');
42        if (!url || !background || card.dataset.encryptedLoading) return;
43        card.dataset.encryptedLoading = 'true';
44
45        try {
46            const response = await fetch(url);
47            if (!response.ok) return;
48            const buffer = await response.arrayBuffer();
49            const image = getImageDataUrl(buffer);
50            if (!image) return;
51            const dataUrl = image.startsWith('data:image/')
52                ? image
53                : `data:image/${normalizeMime(card.dataset.encryptedType)};base64,${image}`;
54            background.style.backgroundImage = `url("${dataUrl}")`;
55            card.removeAttribute('data-encrypted-bg');
56        } catch (_) {
57        } finally {
58            card.removeAttribute('data-encrypted-loading');
59        }
60    };
61
62    const loadEncryptedImage = async image => {
63        const url = image.dataset.encryptedImg;
64        if (!url) return;
65
66        try {
67            const response = await fetch(url);
68            if (!response.ok) return;
69            const buffer = await response.arrayBuffer();
70            const decoded = getImageDataUrl(buffer);
71            if (!decoded) return;
72            image.src = decoded.startsWith('data:image/')
73                ? decoded
74                : `data:image/${normalizeMime(image.dataset.encryptedType)};base64,${decoded}`;
75            image.removeAttribute('data-encrypted-img');
76        } catch (_) {}
77    };
78
79    const initialize = root => {
80        if (!(root instanceof Element || root instanceof Document)) return;
81        if (root instanceof Element && root.matches('[data-encrypted-bg]')) loadEncryptedBackground(root);
82        if (root instanceof HTMLImageElement && root.matches('[data-encrypted-img]')) loadEncryptedImage(root);
83        root.querySelectorAll('[data-encrypted-bg]').forEach(loadEncryptedBackground);
84        root.querySelectorAll('img[data-encrypted-img]').forEach(loadEncryptedImage);
85    };
86
87    const observe = () => new MutationObserver(records => {
88        records.forEach(record => {
89            if (record.type === 'attributes') initialize(record.target);
90            record.addedNodes.forEach(initialize);
91        });
92    }).observe(document.documentElement, {
93        attributes: true,
94        attributeFilter: ['data-encrypted-bg', 'data-encrypted-img'],
95        childList: true,
96        subtree: true
97    });
98
99    if (document.readyState === 'loading') {
100        document.addEventListener('DOMContentLoaded', () => {
101            initialize(document);
102            observe();
103        });
104    } else {
105        initialize(document);
106        observe();
107    }
108})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.