Project

General

Profile

Download (5.37 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / common / misc.js @ 79446ca5

1
/**
2
 * This file is part of Haketilo.
3
 *
4
 * Function: Miscellaneous operations refactored to a separate file.
5
 *
6
 * Copyright (C) 2021 Wojtek Kosior
7
 * Copyright (C) 2021 jahoti
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * As additional permission under GNU GPL version 3 section 7, you
20
 * may distribute forms of that code without the copy of the GNU
21
 * GPL normally required by section 4, provided you include this
22
 * license notice and, in case of non-source distribution, a URL
23
 * through which recipients can access the Corresponding Source.
24
 * If you modify file(s) with this exception, you may extend this
25
 * exception to your version of the file(s), but you are not
26
 * obligated to do so. If you do not wish to do so, delete this
27
 * exception statement from your version.
28
 *
29
 * As a special exception to the GPL, any HTML file which merely
30
 * makes function calls to this code, and for that purpose
31
 * includes it by reference shall be deemed a separate work for
32
 * copyright law purposes. If you modify this code, you may extend
33
 * this exception to your version of the code, but you are not
34
 * obligated to do so. If you do not wish to do so, delete this
35
 * exception statement from your version.
36
 *
37
 * You should have received a copy of the GNU General Public License
38
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
39
 *
40
 * I, Wojtek Kosior, thereby promise not to sue for violation of this file's
41
 * license. Although I request that you do not make use this code in a
42
 * proprietary program, I am not going to enforce this in court.
43
 */
44

    
45
/*
46
 * IMPORTS_START
47
 * IMPORT browser
48
 * IMPORT TYPE_NAME
49
 * IMPORT TYPE_PREFIX
50
 * IMPORTS_END
51
 */
52

    
53
/* Generate a random base64-encoded 128-bit sequence */
54
function gen_nonce()
55
{
56
    let randomData = new Uint8Array(16);
57
    crypto.getRandomValues(randomData);
58
    return btoa(String.fromCharCode.apply(null, randomData));
59
}
60

    
61
/*
62
 * generating unique, per-site value that can be computed synchronously
63
 * and is impossible to guess for a malicious website
64
 */
65

    
66
/* Uint8toHex is a separate function not exported as (a) it's useful and (b) it will be used in crypto.subtle-based digests */
67
function Uint8toHex(data)
68
{
69
    let returnValue = '';
70
    for (let byte of data)
71
	returnValue += ('00' + byte.toString(16)).slice(-2);
72
    return returnValue;
73
}
74

    
75
function gen_nonce(length=16)
76
{
77
    let randomData = new Uint8Array(length);
78
    crypto.getRandomValues(randomData);
79
    return Uint8toHex(randomData);
80
}
81

    
82
/* CSP rule that blocks scripts according to policy's needs. */
83
function make_csp_rule(policy)
84
{
85
    let rule = "prefetch-src 'none'; script-src-attr 'none';";
86
    const script_src = policy.nonce !== undefined ?
87
	  `'nonce-${policy.nonce}'` : "'none'";
88
    rule += ` script-src ${script_src}; script-src-elem ${script_src};`;
89
    return rule;
90
}
91

    
92
/* Check if some HTTP header might define CSP rules. */
93
const csp_header_regex =
94
      /^\s*(content-security-policy|x-webkit-csp|x-content-security-policy)/i;
95

    
96
/*
97
 * Print item together with type, e.g.
98
 * nice_name("s", "hello") → "hello (script)"
99
 */
100
function nice_name(prefix, name)
101
{
102
    return `${name} (${TYPE_NAME[prefix]})`;
103
}
104

    
105
/* Open settings tab with given item's editing already on. */
106
function open_in_settings(prefix, name)
107
{
108
    name = encodeURIComponent(name);
109
    const url = browser.runtime.getURL("html/options.html#" + prefix + name);
110
    window.open(url, "_blank");
111
}
112

    
113
/*
114
 * Check if url corresponds to a browser's special page (or a directory index in
115
 * case of `file://' protocol).
116
 */
117
const privileged_reg =
118
      /^(chrome(-extension)?|moz-extension):\/\/|^about:|^file:\/\/.*\/$/;
119
const is_privileged_url = url => privileged_reg.test(url);
120

    
121
/* Parse a CSP header */
122
function parse_csp(csp) {
123
    let directive, directive_array;
124
    let directives = {};
125
    for (directive of csp.split(';')) {
126
	directive = directive.trim();
127
	if (directive === '')
128
	    continue;
129

    
130
	directive_array = directive.split(/\s+/);
131
	directive = directive_array.shift();
132
	/* The "true" case should never occur; nevertheless... */
133
	directives[directive] = directive in directives ?
134
	    directives[directive].concat(directive_array) :
135
	    directive_array;
136
    }
137
    return directives;
138
}
139

    
140
/* Regexes and objects to use as/in schemas for parse_json_with_schema(). */
141
const nonempty_string_matcher = /.+/;
142

    
143
const matchers = {
144
    sha256: /^[0-9a-f]{64}$/,
145
    nonempty_string: nonempty_string_matcher,
146
    component: [
147
	new RegExp(`^[${TYPE_PREFIX.SCRIPT}${TYPE_PREFIX.BAG}]$`),
148
	nonempty_string_matcher
149
    ]
150
};
151

    
152
/*
153
 * Facilitates checking if there aren't any keys in object. This does *NOT*
154
 * account for pathological cases like redefined properties of Object prototype.
155
 */
156
function is_object_empty(object)
157
{
158
    for (const key in object)
159
	return false;
160
    return true;
161
}
162

    
163
/*
164
 * EXPORTS_START
165
 * EXPORT gen_nonce
166
 * EXPORT make_csp_rule
167
 * EXPORT csp_header_regex
168
 * EXPORT nice_name
169
 * EXPORT open_in_settings
170
 * EXPORT is_privileged_url
171
 * EXPORT matchers
172
 * EXPORT is_object_empty
173
 * EXPORTS_END
174
 */
(7-7/18)