Project

General

Profile

« Previous | Next » 

Revision 72cbfa74

Added by koszko almost 2 years ago

limit allowed pattern lengths

View differences:

common/patterns.js
5 5
 * Redistribution terms are gathered in the `copyright' file.
6 6
 */
7 7

  
8
const MAX_URL_PATH_LEN = 12;
9
const MAX_URL_PATH_CHARS = 255;
10
const MAX_DOMAIN_LEN = 7;
11
const MAX_DOMAIN_CHARS = 100;
12

  
8 13
const proto_regex = /^(\w+):\/\/(.*)$/;
9 14

  
10 15
const user_re = "[^/?#@]+@"
......
37 42
	[deco.domain, deco.path, deco.query] = http_match.slice(1, 4);
38 43
    }
39 44

  
40
    if (deco.domain)
41
	deco.domain = deco.domain.split(".");
42

  
43 45
    const leading_dash = deco.path[0] === "/";
44 46
    deco.trailing_dash = deco.path[deco.path.length - 1] === "/";
45
    deco.path = deco.path.split("/").filter(s => s !== "");
46
    if (leading_dash || deco.path.length === 0)
47
	deco.path.unshift("");
48 47

  
49
    return deco;
50
}
48
    if (deco.domain) {
49
	if (deco.domain.length > MAX_DOMAIN_CHARS) {
50
	    const idx = deco.domain.indexOf(".", deco.domain.length -
51
					    MAX_DOMAIN_CHARS);
52
	    if (idx === -1)
53
		deco.domain = [];
54
	    else
55
		deco.domain = deco.domain.substring(idx + 1);
51 56

  
52
/* Be sane: both arguments should be arrays of length >= 2 */
53
function domain_matches(url_domain, pattern_domain)
54
{
55
    const length_difference = url_domain.length - pattern_domain.length;
56

  
57
    for (let i = 1; i <= url_domain.length; i++) {
58
	const url_part = url_domain[url_domain.length - i];
59
	const pattern_part = pattern_domain[pattern_domain.length - i];
60

  
61
	if (pattern_domain.length === i) {
62
	    if (pattern_part === "*")
63
		return length_difference === 0;
64
	    if (pattern_part === "**")
65
		return length_difference > 0;
66
	    if (pattern_part === "***")
67
		return true;
68
	    return length_difference === 0 && pattern_part === url_part;
57
	    deco.domain_truncated = true;
69 58
	}
70 59

  
71
	if (pattern_part !== url_part)
72
	    return false;
73
    }
74

  
75
    return pattern_domain.length === url_domain.length + 1 &&
76
	pattern_domain[0] === "***";
77
}
78

  
79
function path_matches(url_path, url_trailing_dash,
80
		      pattern_path, pattern_trailing_dash)
81
{
82
    const dashes_ok = !(pattern_trailing_dash && !url_trailing_dash);
83

  
84
    if (pattern_path.length === 0)
85
	return url_path.length === 0 && dashes_ok;
86

  
87
    const length_difference = url_path.length - pattern_path.length;
88

  
89
    for (let i = 0; i < url_path.length; i++) {
90
	if (pattern_path.length === i + 1) {
91
	    if (pattern_path[i] === "*")
92
		return length_difference === 0;
93
	    if (pattern_path[i] === "**") {
94
		return length_difference > 0 ||
95
		    (url_path[i] === "**" && dashes_ok);
96
	    }
97
	    if (pattern_path[i] === "***")
98
		return length_difference >= 0;
99
	    return length_difference === 0 &&
100
		pattern_path[i] === url_path[i] && dashes_ok;
60
	if (deco.path.length > MAX_URL_PATH_CHARS) {
61
	    deco.path = deco.path.substring(0, deco.path.lastIndexOf("/"));
62
	    deco.path_truncated = true;
101 63
	}
102

  
103
	if (pattern_path[i] !== url_path[i])
104
	    return false;
105 64
    }
106 65

  
107
    return false;
108
}
109

  
110
function url_matches(url, pattern)
111
{
112
    const url_deco = deconstruct_url(url);
113
    const pattern_deco = deconstruct_url(pattern);
114

  
115
    if (url_deco === undefined || pattern_deco === undefined) {
116
	console.log(`bad comparison: ${url} and ${pattern}`);
117
	return false
66
    if (typeof deco.domain === "string") {
67
	deco.domain = deco.domain.split(".");
68
	if (deco.domain.splice(0, deco.domain.length - MAX_DOMAIN_LEN).length
69
	    > 0)
70
	    deco.domain_truncated = true;
118 71
    }
119 72

  
120
    return pattern_deco.proto === url_deco.proto &&
121
	!(pattern_deco.proto === "file" && pattern_deco.trailing_dash) &&
122
	!!url_deco.domain === !!pattern_deco.domain &&
123
	(!url_deco.domain ||
124
	 domain_matches(url_deco.domain, pattern_deco.domain)) &&
125
	path_matches(url_deco.path, url_deco.trailing_dash,
126
		     pattern_deco.path, pattern_deco.trailing_dash);
73
    deco.path = deco.path.split("/").filter(s => s !== "");
74
    if (deco.domain && deco.path.splice(MAX_URL_PATH_LEN).length > 0)
75
	deco.path_truncated = true;
76
    if (leading_dash || deco.path.length === 0)
77
	deco.path.unshift("");
78

  
79
    return deco;
127 80
}
128 81

  
129
function* each_domain_pattern(domain_segments)
82
function* each_domain_pattern(deco)
130 83
{
131
    for (let slice = 0; slice < domain_segments.length; slice++) {
132
	const domain_part = domain_segments.slice(slice).join(".");
84
    for (let slice = 0; slice < deco.domain.length - 1; slice++) {
85
	const domain_part = deco.domain.slice(slice).join(".");
133 86
	const domain_wildcards = [];
134
	if (slice === 0)
87
	if (slice === 0 && !deco.domain_truncated)
135 88
	    yield domain_part;
136
	if (slice === 1)
89
	if (slice === 1 && !deco.domain_truncated)
137 90
	    yield "*." + domain_part;
138 91
	if (slice > 1)
139 92
	    yield "**." + domain_part;
......
141 94
    }
142 95
}
143 96

  
144
function* each_path_pattern(path_segments, trailing_dash)
97
function* each_path_pattern(deco)
145 98
{
146
    for (let slice = path_segments.length; slice > 0; slice--) {
147
	const path_part = path_segments.slice(0, slice).join("/");
99
    for (let slice = deco.path.length; slice > 0; slice--) {
100
	const path_part = deco.path.slice(0, slice).join("/");
148 101
	const path_wildcards = [];
149
	if (slice === path_segments.length) {
150
	    if (trailing_dash)
102
	if (slice === deco.path.length && !deco.path_truncated) {
103
	    if (deco.trailing_dash)
151 104
		yield path_part + "/";
152 105
	    yield path_part;
153 106
	}
154
	if (slice === path_segments.length - 1 && path_segments[slice] !== "*")
107
	if (slice === deco.path.length - 1 && !deco.path_truncated &&
108
	    deco.path[slice] !== "*")
155 109
	    yield path_part + "/*";
156
	if (slice < path_segments.length - 1)
110
	if (slice < deco.path.length - 1)
157 111
	    yield path_part + "/**";
158
	if (slice < path_segments.length - 1 ||
159
	    path_segments[path_segments.length - 1] !== "***")
112
	if (slice !== deco.path.length - 1 || deco.path_truncated ||
113
	    deco.path[slice] !== "***")
160 114
	    yield path_part + "/***";
161 115
    }
162 116
}
......
167 121
    const deco = deconstruct_url(url);
168 122

  
169 123
    if (deco === undefined) {
170
	console.log("bad url format", url);
124
	console.error("bad url format", url);
171 125
	return false;
172 126
    }
173 127

  
174
    const all_domains = deco.domain ? each_domain_pattern(deco.domain) : [""];
128
    const all_domains = deco.domain ? each_domain_pattern(deco) : [""];
175 129
    for (const domain of all_domains) {
176
	for (const path of each_path_pattern(deco.path, deco.trailing_dash))
130
	for (const path of each_path_pattern(deco))
177 131
	    yield `${deco.proto}://${domain}${path}`;
178 132
    }
179 133
}
180 134

  
181 135
/*
182 136
 * EXPORTS_START
183
 * EXPORT url_matches
184 137
 * EXPORT each_url_pattern
185 138
 * EXPORTS_END
186 139
 */
html/display-panel.js
21 21
 * IMPORT TYPE_PREFIX
22 22
 * IMPORT nice_name
23 23
 * IMPORT open_in_settings
24
 * IMPORT url_matches
25 24
 * IMPORT each_url_pattern
26 25
 * IMPORT by_id
27 26
 * IMPORT clone_template
......
114 113
    return template;
115 114
}
116 115

  
117
function ensure_pattern_exists(pattern)
118
{
119
    let entry_object = known_patterns.get(pattern);
120
    /*
121
     * As long as pattern computation works well, we should never get into this
122
     * conditional block. This is just a safety measure. To be removed as part
123
     * of a bigger rework when we start taking iframes into account.
124
     */
125
    if (entry_object === undefined) {
126
	console.log(`unknown pattern: ${pattern}`);
127
	entry_object = add_pattern_to_list(pattern);
128
    }
129

  
130
    return entry_object;
131
}
132

  
133 116
function style_possible_pattern_entry(pattern, exists_in_settings)
134 117
{
135 118
    const [text, class_action] = exists_in_settings ?
136 119
	  ["Edit", "add"] : ["Add", "remove"];
137
    const entry_object = ensure_pattern_exists(pattern);
120
    const entry_object = known_patterns.get(pattern);
138 121

  
139
    entry_object.button.textContent = `${text} setting`;
140
    entry_object.entry.classList[class_action]("matched_pattern");
122
    if (entry_object) {
123
	entry_object.button.textContent = `${text} setting`;
124
	entry_object.entry.classList[class_action]("matched_pattern");
125
    }
141 126
}
142 127

  
143 128
function handle_page_change(change)
144 129
{
145
    if (url_matches(tab_url, change.item))
146
        style_possible_pattern_entry(change.item, change.new_val !== undefined);
130
    style_possible_pattern_entry(change.item, change.new_val !== undefined);
147 131
}
148 132

  
149 133
function populate_possible_patterns_list(url)

Also available in: Unified diff