File size: 4,038 Bytes
61c26f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def generate_download_settings_js(dl_fn, control_ids):
    js_code = """

    async (""" + ", ".join([f'{ctrl[0]}' for ctrl in control_ids]) + """) => {  

        const password = prompt("Please enter a password for encryption", " ");

        if (!password) {

            alert("No password provided. Cancelling download.");

            return;

        }

        

        let settings = {""" + ", ".join([f'"{ctrl[0]}": {ctrl[0]}' for ctrl in control_ids]) + """};

        const settingsStr = JSON.stringify(settings);

        const textEncoder = new TextEncoder();

        const encodedSettings = textEncoder.encode(settingsStr);

        const salt = crypto.getRandomValues(new Uint8Array(16));

        const passwordBuffer = textEncoder.encode(password);

        const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);

        const key = await crypto.subtle.deriveKey(

            {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'}, 

            keyMaterial, 

            {name: 'AES-GCM', length: 256}, 

            false, 

            ['encrypt']

        );

        const iv = crypto.getRandomValues(new Uint8Array(12));

        const encryptedSettings = await crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, encodedSettings);

        const blob = new Blob([salt, iv, new Uint8Array(encryptedSettings)], {type: 'application/octet-stream'});

        const url = URL.createObjectURL(blob);

        const a = document.createElement('a');

        a.href = url;

        a.download = '""" + dl_fn + """';

        document.body.appendChild(a);

        a.click();

        document.body.removeChild(a);

        URL.revokeObjectURL(url);

    }"""
    return js_code

def generate_upload_settings_js(control_ids):
    js_code = """

    async () => {

        const input = document.createElement('input');

        input.type = 'file';

        input.onchange = async e => {

            const file = e.target.files[0];

            if (!file) {

                alert("No file selected.");

                return;

            }

            

            const password = prompt("Please enter the password for decryption", " ");

            if (!password) {

                alert("No password provided. Cancelling upload.");

                return;

            }

            

            const arrayBuffer = await file.arrayBuffer();

            const salt = arrayBuffer.slice(0, 16);

            const iv = arrayBuffer.slice(16, 28);

            const encryptedData = arrayBuffer.slice(28);

            const textEncoder = new TextEncoder();

            const passwordBuffer = textEncoder.encode(password);

            const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);

            const key = await crypto.subtle.deriveKey(

                {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'}, 

                keyMaterial, 

                {name: 'AES-GCM', length: 256}, 

                false, 

                ['decrypt']

            );

            

            try {

                const decryptedData = await crypto.subtle.decrypt({name: 'AES-GCM', iv: iv}, key, encryptedData);

                const textDecoder = new TextDecoder();

                const settingsStr = textDecoder.decode(decryptedData);

                const settings = JSON.parse(settingsStr);

                """ + "\n".join([f'document.querySelector("{ctrl[1]}").value = settings["{ctrl[0]}"];' for ctrl in control_ids]) + """

                """ + "\n".join([f'document.querySelector("{ctrl[1]}").dispatchEvent(new InputEvent("input", {{ bubbles: true }}));' for ctrl in control_ids]) + """

            } catch (err) {

                alert("Failed to decrypt. Check your password and try again.");

                console.error("Decryption failed:", err);

            }

        };

        input.click();

    }"""
    return js_code