Skip to content

Commit

Permalink
Add ability to specify domains, lists, clients and group names as arr…
Browse files Browse the repository at this point in the history
…ays (#2707)
  • Loading branch information
DL6ER authored Oct 24, 2023
2 parents 48fd33b + b46a8a5 commit 82f1965
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 50 deletions.
20 changes: 14 additions & 6 deletions scripts/pi-hole/js/groups-adlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,13 +499,21 @@ function delItems(ids) {

function addAdlist(event) {
const type = event.data.type;
const address = utils.escapeHtml($("#new_address").val());
const comment = utils.escapeHtml($("#new_comment").val());

// Check if the user wants to add multiple domains (space or newline separated)
// If so, split the input and store it in an array
var addresses = utils.escapeHtml($("#new_address").val()).split(/[\s,]+/);
// Remove empty elements
addresses = addresses.filter(function (el) {
return el !== "";
});
const addressestr = JSON.stringify(addresses);

utils.disableAll();
utils.showAlert("info", "", "Adding subscribed " + type + "list...", address);
utils.showAlert("info", "", "Adding subscribed " + type + "list(s)...", addressestr);

if (address.length === 0) {
if (addresses.length === 0) {
// enable the ui elements again
utils.enableAll();
utils.showAlert("warning", "", "Warning", "Please specify " + type + "list address");
Expand All @@ -517,10 +525,10 @@ function addAdlist(event) {
method: "post",
dataType: "json",
processData: false,
data: JSON.stringify({ address: address, comment: comment, type: type }),
success: function () {
data: JSON.stringify({ address: addresses, comment: comment, type: type }),
success: function (data) {
utils.enableAll();
utils.showAlert("success", "fas fa-plus", "Successfully added " + type + "list", address);
utils.listsAlert("list", addresses, data);
table.ajax.reload(null, false);
table.rows().deselect();

Expand Down
57 changes: 35 additions & 22 deletions scripts/pi-hole/js/groups-clients.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,34 +405,47 @@ function delItems(ids) {
}

function addClient() {
var ip = utils.escapeHtml($("#select").val().trim());
const comment = utils.escapeHtml($("#new_comment").val());

utils.disableAll();
utils.showAlert("info", "", "Adding client...", ip);

if (ip.length === 0) {
utils.enableAll();
utils.showAlert("warning", "", "Warning", "Please specify a client IP or MAC address");
return;
}
// Check if the user wants to add multiple IPs (space or newline separated)
// If so, split the input and store it in an array
var ips = utils.escapeHtml($("#select").val().trim()).split(/[\s,]+/);
// Remove empty elements
ips = ips.filter(function (el) {
return el !== "";
});
const ipStr = JSON.stringify(ips);

// Validate input, can be:
// - IPv4 address (with and without CIDR)
// - IPv6 address (with and without CIDR)
// - MAC address (in the form AA:BB:CC:DD:EE:FF)
// - host name (arbitrary form, we're only checking against some reserved characters)
if (utils.validateIPv4CIDR(ip) || utils.validateIPv6CIDR(ip) || utils.validateMAC(ip)) {
// Convert input to upper case (important for MAC addresses)
ip = ip.toUpperCase();
} else if (!utils.validateHostname(ip)) {
for (var i = 0; i < ips.length; i++) {
if (
utils.validateIPv4CIDR(ips[i]) ||
utils.validateIPv6CIDR(ips[i]) ||
utils.validateMAC(ips[i])
) {
// Convert input to upper case (important for MAC addresses)
ips[i] = ips[i].toUpperCase();
} else if (!utils.validateHostname(ips[i])) {
utils.showAlert(
"warning",
"",
"Warning",
"Input is neither a valid IP or MAC address nor a valid host name!"
);
return;
}
}

utils.disableAll();
utils.showAlert("info", "", "Adding client(s)...", ipStr);

if (ips.length === 0) {
utils.enableAll();
utils.showAlert(
"warning",
"",
"Warning",
"Input is neither a valid IP or MAC address nor a valid host name!"
);
utils.showAlert("warning", "", "Warning", "Please specify a client IP or MAC address");
return;
}

Expand All @@ -441,10 +454,10 @@ function addClient() {
method: "post",
dataType: "json",
processData: false,
data: JSON.stringify({ client: ip, comment: comment }),
success: function () {
data: JSON.stringify({ client: ips, comment: comment }),
success: function (data) {
utils.enableAll();
utils.showAlert("success", "fas fa-plus", "Successfully added client", ip);
utils.listsAlert("client", ips, data);
reloadClientSuggestions();
table.ajax.reload(null, false);
table.rows().deselect();
Expand Down
40 changes: 24 additions & 16 deletions scripts/pi-hole/js/groups-domains.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,46 +497,54 @@ function addDomain() {
commentEl = $("#new_regex_comment");
}

var domain = utils.escapeHtml(domainEl.val());
const comment = utils.escapeHtml(commentEl.val());

// Check if the user wants to add multiple domains (space or newline separated)
// If so, split the input and store it in an array
var domains = utils.escapeHtml(domainEl.val()).split(/[\s,]+/);
// Remove empty elements
domains = domains.filter(function (el) {
return el !== "";
});
const domainStr = JSON.stringify(domains);

utils.disableAll();
utils.showAlert("info", "", "Adding domain...", domain);
utils.showAlert("info", "", "Adding domain(s)...", domainStr);

if (domain.length < 2) {
if (domains.length === 0) {
utils.enableAll();
utils.showAlert("warning", "", "Warning", "Please specify a domain");
utils.showAlert("warning", "", "Warning", "Please specify at least one domain");
return;
}

// strip "*." if specified by user in wildcard mode
if (kind === "exact" && wildcardChecked && domain.startsWith("*.")) {
domain = domain.substr(2);
for (var i = 0; i < domains.length; i++) {
if (kind === "exact" && wildcardChecked) {
// Transform domain to wildcard if specified by user
domains[i] = "(\\.|^)" + domains[i].replaceAll(".", "\\.") + "$";
kind = "regex";

// strip leading "*." if specified by user in wildcard mode
if (domains[i].startsWith("*.")) domains[i] = domains[i].substr(2);
}
}

// determine list type
const type = action === "add_deny" ? "deny" : "allow";

// Transform domain to wildcard if specified by user
if (kind === "exact" && wildcardChecked) {
domain = "(\\.|^)" + domain.replaceAll(".", "\\.") + "$";
kind = "regex";
}

$.ajax({
url: "/api/domains/" + type + "/" + kind,
method: "post",
dataType: "json",
processData: false,
data: JSON.stringify({
domain: domain,
domain: domains,
comment: comment,
type: type,
kind: kind,
}),
success: function () {
success: function (data) {
utils.enableAll();
utils.showAlert("success", "fas fa-plus", "Successfully added domain", domain);
utils.listsAlert("domain", domains, data);
table.ajax.reload(null, false);
table.rows().deselect();

Expand Down
23 changes: 17 additions & 6 deletions scripts/pi-hole/js/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,24 @@ function delItems(ids) {
}

function addGroup() {
const name = utils.escapeHtml($("#new_name").val());
const comment = utils.escapeHtml($("#new_comment").val());

// Check if the user wants to add multiple groups (space or newline separated)
// If so, split the input and store it in an array
var names = utils
.escapeHtml($("#new_name"))
.val()
.split(/[\s,]+/);
// Remove empty elements
names = names.filter(function (el) {
return el !== "";
});
const groupStr = JSON.stringify(names);

utils.disableAll();
utils.showAlert("info", "", "Adding group...", name);
utils.showAlert("info", "", "Adding group(s)...", groupStr);

if (name.length === 0) {
if (names.length === 0) {
// enable the ui elements again
utils.enableAll();
utils.showAlert("warning", "", "Warning", "Please specify a group name");
Expand All @@ -296,13 +307,13 @@ function addGroup() {
dataType: "json",
processData: false,
data: JSON.stringify({
name: name,
name: names,
comment: comment,
enabled: true,
}),
success: function () {
success: function (data) {
utils.enableAll();
utils.showAlert("success", "fas fa-plus", "Successfully added group", name);
utils.listsAlert("group", names, data);
$("#new_name").val("");
$("#new_comment").val("");
table.ajax.reload();
Expand Down
76 changes: 76 additions & 0 deletions scripts/pi-hole/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,81 @@ function hexDecode(string) {
return back;
}

function listAlert(type, items, data) {
// Show simple success message if there is no "processed" object in "data" or
// if all items were processed successfully
if (data.processed === undefined || data.processed.success.length === items.length) {
showAlert(
"success",
"fas fa-plus",
"Successfully added " + type + (items.length !== 1 ? "s" : ""),
items.join(", ")
);
return;
}

// Show a more detailed message if there is a "processed" object in "data" and
// not all items were processed successfully
let message = "";

// Show a list of successful items if there are any
if (data.processed.success.length > 0) {
message +=
"<strong>Successfully added " +
data.processed.success.length +
" " +
type +
(data.processed.success.length !== 1 ? "s" : "") +
":</strong>";

// Loop over data.processed.success and print "item"
for (const item in data.processed.success) {
if (Object.prototype.hasOwnProperty.call(data.processed.success, item)) {
message += "<br>- <strong>" + data.processed.success[item].item + "</strong>";
}
}
}

// Add a line break if there are both successful and failed items
if (data.processed.success.length > 0 && data.processed.errors.length > 0) {
message += "<br><br>";
}

// Show a list of failed items if there are any
if (data.processed.errors.length > 0) {
message +=
"<strong>Failed to add " +
data.processed.errors.length +
" " +
type +
(data.processed.errors.length !== 1 ? "s" : "") +
":</strong>\n";

// Loop over data.processed.errors and print "item: error"
for (const item in data.processed.errors) {
if (Object.prototype.hasOwnProperty.call(data.processed.errors, item)) {
let error = data.processed.errors[item].error;
// Replace some error messages with a more user-friendly text
if (error.indexOf("UNIQUE constraint failed") > -1) {
error = "Already present";
}

message += "<br>- <strong>" + data.processed.errors[item].item + "</strong>: " + error;
}
}
}

// Show the warning message
const total = data.processed.success.length + data.processed.errors.length;
const processed = "(" + total + " " + type + (total !== 1 ? "s" : "") + " processed)";
showAlert(
"warning",
"fas fa-exclamation-triangle",
"Some " + type + (items.length !== 1 ? "s" : "") + " could not be added " + processed,
message
);
}

window.utils = (function () {
return {
escapeHtml: escapeHtml,
Expand Down Expand Up @@ -570,5 +645,6 @@ window.utils = (function () {
parseQueryString: parseQueryString,
hexEncode: hexEncode,
hexDecode: hexDecode,
listsAlert: listAlert,
};
})();

0 comments on commit 82f1965

Please sign in to comment.