diff options
Diffstat (limited to 'interface/js/app/upload.js')
-rw-r--r-- | interface/js/app/upload.js | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js new file mode 100644 index 0000000..546f5cc --- /dev/null +++ b/interface/js/app/upload.js @@ -0,0 +1,243 @@ +/* + The MIT License (MIT) + + Copyright (C) 2017 Vsevolod Stakhov <vsevolod@highsecure.ru> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/* global require */ + +define(["jquery", "app/common", "app/libft"], + ($, common, libft) => { + "use strict"; + const ui = {}; + + function cleanTextUpload(source) { + $("#" + source + "TextSource").val(""); + } + + // @upload text + function uploadText(data, source, headers) { + let url = null; + if (source === "spam") { + url = "learnspam"; + } else if (source === "ham") { + url = "learnham"; + } else if (source === "fuzzy") { + url = "fuzzyadd"; + } else if (source === "scan") { + url = "checkv2"; + } + + function server() { + if (common.getSelector("selSrv") === "All SERVERS" && + common.getSelector("selLearnServers") === "random") { + const servers = $("#selSrv option").slice(1).map((_, o) => o.value); + return servers[Math.floor(Math.random() * servers.length)]; + } + return null; + } + + common.query(url, { + data: data, + params: { + processData: false, + }, + method: "POST", + headers: headers, + success: function (json, jqXHR) { + cleanTextUpload(source); + common.alertMessage("alert-success", "Data successfully uploaded"); + if (jqXHR.status !== 200) { + common.alertMessage("alert-info", jqXHR.statusText); + } + }, + server: server() + }); + } + + function get_server() { + const checked_server = common.getSelector("selSrv"); + return (checked_server === "All SERVERS") ? "local" : checked_server; + } + + // @upload text + function scanText(data, headers) { + common.query("checkv2", { + data: data, + params: { + processData: false, + }, + method: "POST", + headers: headers, + success: function (neighbours_status) { + function scrollTop(rows_total) { + // Is there a way to get an event when all rows are loaded? + libft.waitForRowsDisplayed("scan", rows_total, () => { + $("#cleanScanHistory").removeAttr("disabled", true); + $("html, body").animate({ + scrollTop: $("#scanResult").offset().top + }, 1000); + }); + } + + const json = neighbours_status[0].data; + if (json.action) { + common.alertMessage("alert-success", "Data successfully scanned"); + + const rows_total = $("#historyTable_scan > tbody > tr:not(.footable-detail-row)").length + 1; + const o = libft.process_history_v2({rows: [json]}, "scan"); + const {items} = o; + common.symbols.scan.push(o.symbols[0]); + + if (Object.prototype.hasOwnProperty.call(common.tables, "scan")) { + common.tables.scan.rows.load(items, true); + scrollTop(rows_total); + } else { + libft.destroyTable("scan"); + require(["footable"], () => { + // Is there a way to get an event when the table is destroyed? + setTimeout(() => { + libft.initHistoryTable(data, items, "scan", libft.columns_v2("scan"), true); + scrollTop(rows_total); + }, 200); + }); + } + } else { + common.alertMessage("alert-error", "Cannot scan data"); + } + }, + errorMessage: "Cannot upload data", + statusCode: { + 404: function () { + common.alertMessage("alert-error", "Cannot upload data, no server found"); + }, + 500: function () { + common.alertMessage("alert-error", "Cannot tokenize message: no text data"); + }, + 503: function () { + common.alertMessage("alert-error", "Cannot tokenize message: no text data"); + } + }, + server: get_server() + }); + } + + function getFuzzyHashes(data) { + function fillHashTable(rules) { + $("#hashTable tbody").empty(); + for (const [rule, hashes] of Object.entries(rules)) { + hashes.forEach((hash, i) => { + $("#hashTable tbody").append("<tr>" + + (i === 0 ? '<td rowspan="' + Object.keys(hashes).length + '">' + rule + "</td>" : "") + + "<td>" + hash + "</td></tr>"); + }); + } + $("#hash-card").slideDown(); + } + + common.query("plugins/fuzzy/hashes?flag=" + $("#fuzzy-flag").val(), { + data: data, + params: { + processData: false, + }, + method: "POST", + success: function (neighbours_status) { + const json = neighbours_status[0].data; + if (json.success) { + common.alertMessage("alert-success", "Message successfully processed"); + fillHashTable(json.hashes); + } else { + common.alertMessage("alert-error", "Unexpected error processing message"); + } + }, + server: get_server() + }); + } + + + libft.set_page_size("scan", $("#scan_page_size").val()); + libft.bindHistoryTableEventHandlers("scan", 3); + + $("#cleanScanHistory").off("click"); + $("#cleanScanHistory").on("click", (e) => { + e.preventDefault(); + if (!confirm("Are you sure you want to clean scan history?")) { // eslint-disable-line no-alert + return; + } + libft.destroyTable("scan"); + common.symbols.scan.length = 0; + $("#cleanScanHistory").attr("disabled", true); + }); + + function enable_disable_scan_btn() { + $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)") + .prop("disabled", ($.trim($("textarea").val()).length === 0)); + } + enable_disable_scan_btn(); + $("textarea").on("input", () => { + enable_disable_scan_btn(); + }); + + $("#scanClean").on("click", () => { + $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)").attr("disabled", true); + $("#scanForm")[0].reset(); + $("#scanResult").hide(); + $("#scanOutput tbody").remove(); + $("html, body").animate({scrollTop: 0}, 1000); + return false; + }); + + $(".card-close-btn").on("click", function () { + $(this).closest(".card").slideUp(); + }); + + $("[data-upload]").on("click", function () { + const source = $(this).data("upload"); + const data = $("#scanMsgSource").val(); + let headers = {}; + if ($.trim(data).length > 0) { + if (source === "scan") { + headers = ["IP", "User", "From", "Rcpt", "Helo", "Hostname"].reduce((o, header) => { + const value = $("#scan-opt-" + header.toLowerCase()).val(); + if (value !== "") o[header] = value; + return o; + }, {}); + if ($("#scan-opt-pass-all").prop("checked")) headers.Pass = "all"; + scanText(data, headers); + } else if (source === "compute-fuzzy") { + getFuzzyHashes(data); + } else { + if (source === "fuzzy") { + headers = { + flag: $("#fuzzyFlagText").val(), + weight: $("#fuzzyWeightText").val() + }; + } + uploadText(data, source, headers); + } + } else { + common.alertMessage("alert-error", "Message source field cannot be blank"); + } + return false; + }); + + return ui; + }); |