-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpopup.js
405 lines (285 loc) · 11.5 KB
/
popup.js
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
let privateIpCheckbox = document.getElementById("privateIpCheckbox");
let allowedIpList = document.getElementById("allowedIpList");
let newIpForm = document.getElementById("newIpForm");
let newIpInput = document.getElementById("newIpInput");
let errorMessage = document.getElementById("errorMessage");
let allowedIps = [];
const privateIpsArray = [ //array of private IP addresses
"*://10.*.*.*",
"*://192.168.*.*",
"*://172.16.*.*",
"*://172.17.*.*",
"*://172.18.*.*",
"*://172.19.*.*",
"*://172.20.*.*",
"*://172.21.*.*",
"*://172.22.*.*",
"*://172.23.*.*",
"*://172.24.*.*",
"*://172.25.*.*",
"*://172.26.*.*",
"*://172.27.*.*",
"*://172.28.*.*",
"*://172.29.*.*",
"*://172.30.*.*",
"*://172.31.*.*",
];
const errorMessages = [
"Please enter a valid IP address",
"This IP address is already on the allow list"
]
intialGetRules()
setPrivateIpCheckbox();
newIpForm.addEventListener("submit",(e) => {
//event listener for input field that add new ips
e.preventDefault();
let uniqueIp = false;
getRules().then((rules) =>{
let allIps = [];
rules.forEach(rule => {
allIps.push(rule.condition.urlFilter);
})
if(!allIps.includes(newIpInput.value)){
uniqueIp = true;
}
let validIp = isIpValid(newIpInput.value)
if (validIp && uniqueIp) {
//passing the value to the addNewAllowedIp function
addNewAllowedIp(newIpInput.value);
newIpInput.value = "";
}
else {
if(!validIp) {
errorMessage.innerHTML = errorMessages[0] //Please enter a valid IP address
}
else if (!uniqueIp) {
errorMessage.innerHTML = errorMessages[1] //This IP address is already on the allow list
}
newIpInput.addEventListener("click", () => {
errorMessage.innerHTML = null;
})
newIpInput.addEventListener("input", () => {
errorMessage.innerHTML = null;
})
}
})
})
//Event listener for when the checkbox is clicked
privateIpCheckbox.addEventListener('click', () => {
if (privateIpCheckbox.checked === true){
privateIpsArray.forEach((domain, index) => {
let id = index + 1;
chrome.declarativeNetRequest.updateDynamicRules(
{addRules:[{
"id": id,
"priority": 2,
"action": { "type": "allowAllRequests" },
"condition": {"urlFilter": domain, "resourceTypes": ["main_frame"] }}
],
removeRuleIds: [id]
},
)
})
}
else {
chrome.declarativeNetRequest.updateDynamicRules(
{
removeRuleIds: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
})
}
})
async function intialGetRules(){
//Function to get the rules initially to then add to the HTML
const rules = await getRules();
rules.forEach(rule => {
if (rule.priority == 3) {
//allowed IPs that the user has added have a priority of 3
allowedIps.push(rule.condition.urlFilter)
}
})
allowedIps.forEach((ip, index) =>{
//passing the IPs to the addAllowedIPsToHTML function which will render them in the html
addAllowedIPsToHTML(ip, index)
})
}
async function setPrivateIpCheckbox() {
//function to see if there is already allow rules for the private IP ranges to then set the privateIpCheckbox.checked value
let possiblePrivateIPs = [];
const rules = await getRules();
rules.forEach(rule => {
if (rule.priority == 2) {
possiblePrivateIPs.push(rule.condition.urlFilter)
}
})
if(privateIpsArray.every(ip => possiblePrivateIPs.includes(ip))) {
privateIpCheckbox.checked = true;
}
else {
privateIpCheckbox.checked = false;
}
}
async function getRules() {
//Funciton to get all of the rules
try {
return await chrome.declarativeNetRequest.getDynamicRules();
} catch(error) {
console.log(error);
}
}
function isIpValid(ip) {
//Function to check if an IP address is vaild
return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip)
//^^^^ Regex to check to see if the input is a valid ip address
}
function addAllowedIPsToHTML(ip, index) {
//Function to add the allowed IPs to the HTML
let li = document.createElement("li");
//Create the div that the IP address (in the input element) and the edit and delete btns will be in
let AllowedIPAndBtnsDiv = document.createElement("div");
AllowedIPAndBtnsDiv.classList.add("AllowedIPAndBtns")
li.appendChild(AllowedIPAndBtnsDiv) //Add to the Li of the allowed IPs list
let inputField = document.createElement("input")
inputField.value = ip;
inputField.readOnly = true;
let deleteIpBtn = document.createElement("button")
deleteIpBtn.innerText = "Delete"
deleteIpBtn.classList.add("deleteBtn", "btn")
deleteIpBtn.addEventListener("click", () => {
deleteAllowedIp(index, li, ip)
})
let editIpBtn = document.createElement("button")
editIpBtn.innerText = "Edit"
editIpBtn.classList.add("editBtn", "btn")
editIpBtn.addEventListener("click", () => {
editAllowedIp(index, li, AllowedIPAndBtnsDiv, inputField, editIpBtn, inputField.value);
})
AllowedIPAndBtnsDiv.appendChild(inputField)
AllowedIPAndBtnsDiv.appendChild(deleteIpBtn)
AllowedIPAndBtnsDiv.appendChild(editIpBtn)
allowedIpList.appendChild(li)
}
async function addNewAllowedIp(ip) {
//Function to add a new IP to the rule list
//first pass the IP to the addAllowedIPsToHTML function to create the li for it and add it to the allowedIps array for local storage
addAllowedIPsToHTML(ip);
const rules = await getRules();
rules.sort((a, b) => (a.id > b.id) ? 1 : -1) // sorting the rules by ID
let ruleIds = [];
let ruleId;
rules.forEach(rule => {
ruleIds.push(rule.id) //add the rule IDs to a new variable
})
let gapsInRuleIDs = [];
for (let i in ruleIds) {
//find gaps in the rules, as long as that ID number is greater than 28
//28 because thats the number of rules for blocking the private and public IP ranges
// get the size of the gap
let x = ruleIds[i] - ruleIds[i - 1];
// start filling in the gap with `1`
let diff = 1;
// while there's still a gap, push the correct numbers
// into `gapsInRuleIDs`, calculated by the number + diff
while (diff < x && (ruleIds[i - 1] + diff) > 28) {
gapsInRuleIDs.push(ruleIds[i - 1] + diff);
diff++;
}
}
if(gapsInRuleIDs.length != 0) {
ruleId = gapsInRuleIDs[0]; //If there is a gap, get the first gap from the array
}
else {
let CurrentMaxId = Math.max.apply(Math, rules.map(rule => rule.id)); // finds the current largest ID number
ruleId = CurrentMaxId + 1; // new highest ID
}
chrome.declarativeNetRequest.updateDynamicRules(
{addRules:[{
"id": ruleId,
"priority": 3,
"action": { "type": "allowAllRequests" },
"condition": {"urlFilter": ip, "resourceTypes": ["main_frame"] }}
],
removeRuleIds: [ruleId]
},
)
}
async function deleteAllowedIp(index, li, ip){
// Function to delete an IP from the allow list
allowedIps.splice(index, 1); //delete it from the local allowed IP array
const rules = await getRules();
li.remove();
rules.forEach(rule => {
if (rule.condition.urlFilter == ip && rule.priority == 3) {
//if IP address of the rule and the one passed match and the prority is 3 then delete the rule
chrome.declarativeNetRequest.updateDynamicRules(
{
removeRuleIds: [rule.id]
}
)
}
})
}
async function editAllowedIp (index, li, AllowedIPAndBtnsDiv, inputField, editIpBtn, ip) {
//function that edits the allowed IP addresses
//allows the user to edit the field and hide the edit btn
inputField.readOnly = false;
editIpBtn.classList.add("hidden");
const rules = await getRules();
//create a save IP btn
let saveIpBtn = document.createElement("button")
saveIpBtn.innerText = "Save"
saveIpBtn.classList.add("btn","saveBtn")
AllowedIPAndBtnsDiv.appendChild(saveIpBtn)
saveIpBtn.addEventListener("click", () => {
let ruleId;
let uniqueIp = false;
let allIps = [];
rules.forEach(rule => {
allIps.push(rule.condition.urlFilter); //push all of the IP addresses to a new variable
})
if (!allIps.includes(inputField.value) || inputField.value == ip){
// If the new IP isn't already on the allowed or the IP address is the same as it already was
uniqueIp = true;
}
rules.forEach(rule => {
if(rule.condition.urlFilter == ip && rule.priority == 3){
//finds the ID of the old IP address
ruleId = rule.id
}
})
let validIp = isIpValid(inputField.value) //check if the new IP is a vaild IP address
if(validIp && uniqueIp) {
allowedIps[index] = inputField.value; //saving the IP address to the local array of IPs
inputField.readOnly = true; //set it back so they can't edit it
saveIpBtn.remove()
editIpBtn.classList.remove("hidden");
chrome.declarativeNetRequest.updateDynamicRules(
//save the new IP address to the ID of the old one
{addRules:[{
"id": ruleId,
"priority": 3,
"action": { "type": "allowAllRequests" },
"condition": {"urlFilter": inputField.value, "resourceTypes": ["main_frame"] }}
],
removeRuleIds: [ruleId]
},
)
}
else {
//Error cehcking for editing the IP
let editErrorMessage = document.createElement("p")
if(!validIp) {
editErrorMessage.innerHTML = errorMessages[0] //Please enter a valid IP address
}
else if (!uniqueIp) {
editErrorMessage.innerHTML = errorMessages[1] //This IP address is already on the allow list
}
li.appendChild(editErrorMessage)
inputField.addEventListener("click", () => {
editErrorMessage.remove();
})
inputField.addEventListener("input", () => {
editErrorMessage.remove();
})
}
})
}