From: Alexander Moisseev Date: Thu, 8 May 2025 15:31:38 +0000 (+0300) Subject: [WebUI] Add deletion of specific fuzzy hashes X-Git-Tag: 3.12.0~28^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec9f768ad791127b4582f74054de7cd4ec585499;p=thirdparty%2Frspamd.git [WebUI] Add deletion of specific fuzzy hashes --- diff --git a/interface/index.html b/interface/index.html index 8329a74ddd..14dd880dcc 100644 --- a/interface/index.html +++ b/interface/index.html @@ -474,8 +474,8 @@
-
-
+
+

Learn Bayesian classifier:

@@ -486,21 +486,39 @@
-
-
+
+

Fuzzy hash storage management:

-
-
- - +
+
+ +
-
- - +
+ +
- - - +
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js index d851962964..2ad3153841 100644 --- a/interface/js/app/upload.js +++ b/interface/js/app/upload.js @@ -36,7 +36,9 @@ define(["jquery", "app/common", "app/libft"], $("#" + source + "TextSource").val(""); } - function uploadText(data, source, headers) { + function uploadText(data, source, headers, method = "POST") { + const deferred = new $.Deferred(); + let url = null; if (source === "spam") { url = "learnspam"; @@ -46,6 +48,8 @@ define(["jquery", "app/common", "app/libft"], url = "fuzzyadd"; } else if (source === "fuzzydel") { url = "fuzzydel"; + } else if (source === "fuzzydelhash") { + url = "fuzzydelhash"; } else if (source === "scan") { url = "checkv2"; } @@ -64,7 +68,7 @@ define(["jquery", "app/common", "app/libft"], params: { processData: false, }, - method: "POST", + method: method, headers: headers, success: function (json, jqXHR) { cleanTextUpload(source); @@ -72,13 +76,17 @@ define(["jquery", "app/common", "app/libft"], if (jqXHR.status !== 200) { common.alertMessage("alert-info", jqXHR.statusText); } + deferred.resolve(); }, + complete: () => deferred.resolve(), server: server() }); + + return deferred.promise(); } function enable_disable_scan_btn(disable) { - $("#scan button:not(#cleanScanHistory, #scanOptionsToggle, .ft-columns-btn)") + $("#scan button:not(#cleanScanHistory, #deleteHashesBtn, #scanOptionsToggle, .ft-columns-btn)") .prop("disabled", (disable || $.trim($("textarea").val()).length === 0)); } @@ -265,6 +273,57 @@ define(["jquery", "app/common", "app/libft"], return false; }); + + function setDelhashButtonsDisabled(disabled = true) { + ["#deleteHashesBtn", "#clearHashesBtn"].forEach((s) => $(s).prop("disabled", disabled)); + } + + /** + * Parse a textarea (or any input) value into an array of non-empty tokens. + * Splits on commas, semicolons or any whitespace (space, tab, newline). + * + * @param {string} selector - jQuery selector for the input element. + * @returns {string[]} - Trimmed, non-empty tokens. + */ + function parseHashes(selector) { + return $(selector).val() + .split(/[,\s;]+/) + .map((t) => t.trim()) + .filter((t) => t.length > 0); + } + + $("#fuzzyDelList").on("input", () => { + const hasTokens = parseHashes("#fuzzyDelList").length > 0; + setDelhashButtonsDisabled(!hasTokens); + }); + + $("#deleteHashesBtn").on("click", () => { + $("#fuzzyDelList").prop("disabled", true); + setDelhashButtonsDisabled(); + $("#deleteHashesBtn").find(".btn-label").text("Deleting…"); + + const hashes = parseHashes("#fuzzyDelList"); + const promises = hashes.map((h) => { + const headers = { + flag: $("#fuzzyFlagText").val(), + Hash: h + }; + return uploadText(null, "fuzzydelhash", headers, "GET"); + }); + + $.when.apply($, promises).always(() => { + $("#fuzzyDelList").prop("disabled", false); + setDelhashButtonsDisabled(false); + $("#deleteHashesBtn").find(".btn-label").text("Delete hashes"); + }); + }); + + $("#clearHashesBtn").on("click", () => { + $("#fuzzyDelList").val("").focus(); + setDelhashButtonsDisabled(); + }); + + function fileInputHandler(obj) { ({files} = obj); filesIdx = 0;