aboutsummaryrefslogtreecommitdiff
path: root/background/settings_query.js
blob: 43538d56dddc5b3e18006a613b402a10d7b29d52 (about) (plain)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
 * Myext querying page settings with regard to wildcard records
 *
 * Copyright (C) 2021 Wojtek Kosior
 * Redistribution terms are gathered in the `copyright' file.
 */

"use strict";

(() => {
    const make_once = window.make_once;
    const get_storage = window.get_storage;

    var storage;

    var exports = {};

    async function init(fun)
    {
	storage = await get_storage();

	return fun;
    }

    // TODO: also support urls with specified ports as well as `data:' urls
    function query(url, multiple)
    {
	let proto_re = "[a-zA-Z]*:\/\/";
	let domain_re = "[^/?#]+";
	let segments_re = "/[^?#]*";
	let query_re = "\\?[^#]*";

	let url_regex = new RegExp(`\
^\
(${proto_re})\
(${domain_re})\
(${segments_re})?\
(${query_re})?\
#?.*\$\
`);

	let regex_match = url_regex.exec(url);
	if (regex_match === null) {
	    console.log("bad url format", url);
	    return multiple ? [] : [undefined, undefined];
	}

	let [_, proto, domain, segments, query] = regex_match;

	domain = domain.split(".");
	let segments_trailing_dash =
	    segments && segments[segments.length - 1] === "/";
	segments = (segments || "").split("/").filter(s => s !== "");
	segments.unshift("");

	let matched = [];

	for (let d_slice = 0; d_slice < domain.length; d_slice++) {
	    let domain_part = domain.slice(d_slice).join(".");
	    let domain_wildcards = [];
	    if (d_slice === 0)
		domain_wildcards.push("");
	    if (d_slice === 1)
		domain_wildcards.push("*.");
	    if (d_slice > 0)
		domain_wildcards.push("**.");
	    domain_wildcards.push("***.");

	    for (let domain_wildcard of domain_wildcards) {
		let domain_pattern = domain_wildcard + domain_part;

		for (let s_slice = segments.length; s_slice > 0; s_slice--) {
		    let segments_part = segments.slice(0, s_slice).join("/");
		    let segments_wildcards = [];
		    if (s_slice === segments.length) {
			if (segments_trailing_dash)
			    segments_wildcards.push("/");
			segments_wildcards.push("");
		    }
		    if (s_slice === segments.length - 1) {
			if (segments[s_slice] !== "*")
			    segments_wildcards.push("/*");
		    }
		    if (s_slice < segments.length &&
			(segments[s_slice] !== "**" ||
			 s_slice < segments.length - 1))
			segments_wildcards.push("/**");
		    if (segments[s_slice] !== "***" ||
			s_slice < segments.length)
			segments_wildcards.push("/***");

		    for (let segments_wildcard of segments_wildcards) {
			let segments_pattern =
			    segments_part + segments_wildcard;

			let pattern = proto + domain_pattern + segments_pattern;
			console.log("trying", pattern);
			let settings = storage.get(TYPE_PREFIX.PAGE, pattern);

			if (settings === undefined)
			    continue;

			if (!multiple)
			    return [pattern, settings];

			matched.push([pattern, settings]);
		    }
		}
	    }
	}

	return multiple ?  matched : [undefined, undefined];
    }

    function query_best(url)
    {
	return query(url, false);
    }

    function query_all(url)
    {
	return query(url, true);
    }

    window.get_query_best = make_once(() => init(query_best));
    window.get_query_all = make_once(() => init(query_all));
})();