123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 |
- /*
- The MIT License (MIT)
-
- Copyright (C) 2012-2013 Anton Simonov <untone@gmail.com>
- Copyright (C) 2014-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 jQuery:false, FooTable:false, Visibility:false */
-
- define(["jquery", "d3pie", "visibility", "nprogress", "stickytabs", "app/stats", "app/graph", "app/config",
- "app/symbols", "app/history", "app/upload"],
- // eslint-disable-next-line max-params
- function ($, D3pie, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config,
- tab_symbols, tab_history, tab_upload) {
- "use strict";
- var ui = {
- page_size: {
- scan: 25,
- errors: 25,
- history: 25
- },
- symbols: {
- scan: [],
- history: []
- }
- };
-
- var graphs = {};
- var tables = {};
- var neighbours = []; // list of clusters
- var checked_server = "All SERVERS";
- var timer_id = [];
- var selData = null; // Graph's dataset selector state
- var symbolDescriptions = {};
-
- NProgress.configure({
- minimum: 0.01,
- showSpinner: false,
- });
-
- function cleanCredentials() {
- sessionStorage.clear();
- $("#statWidgets").empty();
- $("#listMaps").empty();
- $("#modalBody").empty();
- }
-
- function stopTimers() {
- for (var key in timer_id) {
- if (!{}.hasOwnProperty.call(timer_id, key)) continue;
- Visibility.stop(timer_id[key]);
- }
- }
-
- function disconnect() {
- [graphs, tables].forEach(function (o) {
- Object.keys(o).forEach(function (key) {
- o[key].destroy();
- delete o[key];
- });
- });
-
- stopTimers();
- cleanCredentials();
- ui.connect();
- }
-
- function tabClick(id) {
- var tab_id = id;
- if ($(tab_id).attr("disabled")) return;
- $(tab_id).attr("disabled", true);
-
- stopTimers();
-
- if (tab_id === "#refresh") {
- tab_id = "#" + $(".navbar-nav .active > a").attr("id");
- }
-
- switch (tab_id) {
- case "#status_nav":
- tab_stat.statWidgets(ui, graphs, checked_server);
- timer_id.status = Visibility.every(10000, function () {
- tab_stat.statWidgets(ui, graphs, checked_server);
- });
- break;
- case "#throughput_nav":
- tab_graph.draw(ui, graphs, tables, neighbours, checked_server, selData);
-
- var autoRefresh = {
- hourly: 60000,
- daily: 300000
- };
- timer_id.throughput = Visibility.every(autoRefresh[selData] || 3600000, function () {
- tab_graph.draw(ui, graphs, tables, neighbours, checked_server, selData);
- });
- break;
- case "#configuration_nav":
- tab_config.getActions(ui, checked_server);
- tab_config.getMaps(ui, checked_server);
- break;
- case "#symbols_nav":
- tab_symbols.getSymbols(ui, tables, checked_server);
- break;
- case "#history_nav":
- tab_history.getHistory(ui, tables);
- tab_history.getErrors(ui, tables);
- break;
- case "#disconnect":
- disconnect();
- break;
- default:
- }
-
- setTimeout(function () {
- $(tab_id).removeAttr("disabled");
- $("#refresh").removeAttr("disabled");
- }, 1000);
- }
-
- function drawTooltips() {
- // Update symbol description tooltips
- $.each(symbolDescriptions, function (key, description) {
- $("abbr[data-sym-key=" + key + "]").tooltip({
- placement: "bottom",
- html: true,
- title: description
- });
- });
- }
-
- function getPassword() {
- return sessionStorage.getItem("Password");
- }
-
- // Get selectors' current state
- function getSelector(id) {
- var e = document.getElementById(id);
- return e.options[e.selectedIndex].value;
- }
-
- function get_compare_function(table) {
- var compare_functions = {
- magnitude: function (e1, e2) {
- return Math.abs(e2.score) - Math.abs(e1.score);
- },
- name: function (e1, e2) {
- return e1.name.localeCompare(e2.name);
- },
- score: function (e1, e2) {
- return e2.score - e1.score;
- }
- };
-
- return compare_functions[getSelector("selSymOrder_" + table)];
- }
-
- function saveCredentials(password) {
- sessionStorage.setItem("Password", password);
- }
-
- function set_page_size(table, page_size, callback) {
- var n = parseInt(page_size, 10); // HTML Input elements return string representing a number
- if (n !== ui.page_size[table] && n > 0) {
- ui.page_size[table] = n;
- if (callback) {
- return callback(n);
- }
- }
- return null;
- }
-
- function sort_symbols(o, compare_function) {
- return Object.keys(o)
- .map(function (key) {
- return o[key];
- })
- .sort(compare_function)
- .map(function (e) { return e.str; })
- .join("<br>\n");
- }
-
- function unix_time_format(tm) {
- var date = new Date(tm ? tm * 1000 : 0);
- return date.toLocaleString();
- }
-
- function displayUI() {
- ui.query("auth", {
- success: function (neighbours_status) {
- $("#selSrv").empty();
- $("#selSrv").append($('<option value="All SERVERS">All SERVERS</option>'));
- neighbours_status.forEach(function (e) {
- $("#selSrv").append($('<option value="' + e.name + '">' + e.name + "</option>"));
- if (checked_server === e.name) {
- $('#selSrv [value="' + e.name + '"]').prop("selected", true);
- } else if (!e.status) {
- $('#selSrv [value="' + e.name + '"]').prop("disabled", true);
- }
- });
- },
- errorMessage: "Cannot get server status",
- server: "All SERVERS"
- });
-
- // In many browsers local storage can only store string.
- // So when we store the boolean true or false, it actually stores the strings "true" or "false".
- ui.read_only = sessionStorage.getItem("read_only") === "true";
- if (ui.read_only) {
- $(".learn").hide();
- $("#resetHistory").attr("disabled", true);
- $("#errors-history").hide();
- } else {
- $(".learn").show();
- $("#resetHistory").removeAttr("disabled", true);
- $("#errors-history").show();
- }
-
- var buttons = $("#navBar .pull-right");
- $("#mainUI").show();
- $(buttons).show();
- $(".nav-tabs-sticky").stickyTabs({initialTab:"#status_nav"});
- }
-
- function alertMessage(alertClass, alertText) {
- var a = $("<div class=\"alert " + alertClass + " alert-dismissible fade in show\">" +
- "<button type=\"button\" class=\"close\" data-dismiss=\"alert\" title=\"Dismiss\">×</button>" +
- "<strong>" + alertText + "</strong>");
- $(".notification-area").append(a);
-
- setTimeout(function () {
- $(a).fadeTo(500, 0).slideUp(500, function () {
- $(this).alert("close");
- });
- }, 5000);
- }
-
- function queryServer(neighbours_status, ind, req_url, o) {
- neighbours_status[ind].checked = false;
- neighbours_status[ind].data = {};
- neighbours_status[ind].status = false;
- var req_params = {
- jsonp: false,
- data: o.data,
- headers: $.extend({Password:getPassword()}, o.headers),
- url: neighbours_status[ind].url + req_url,
- xhr: function () {
- var xhr = $.ajaxSettings.xhr();
- // Download progress
- if (req_url !== "neighbours") {
- xhr.addEventListener("progress", function (e) {
- if (e.lengthComputable) {
- neighbours_status[ind].percentComplete = e.loaded / e.total;
- var percentComplete = neighbours_status.reduce(function (prev, curr) {
- return curr.percentComplete ? curr.percentComplete + prev : prev;
- }, 0);
- NProgress.set(percentComplete / neighbours_status.length);
- }
- }, false);
- }
- return xhr;
- },
- success: function (json) {
- neighbours_status[ind].checked = true;
- neighbours_status[ind].status = true;
- neighbours_status[ind].data = json;
- },
- error: function (jqXHR, textStatus, errorThrown) {
- neighbours_status[ind].checked = true;
- function errorMessage() {
- alertMessage("alert-error", neighbours_status[ind].name + " > " +
- (o.errorMessage ? o.errorMessage : "Request failed") +
- (errorThrown ? ": " + errorThrown : ""));
- }
- if (o.error) {
- o.error(neighbours_status[ind],
- jqXHR, textStatus, errorThrown);
- } else if (o.errorOnceId) {
- var alert_status = o.errorOnceId + neighbours_status[ind].name;
- if (!(alert_status in sessionStorage)) {
- sessionStorage.setItem(alert_status, true);
- errorMessage();
- }
- } else {
- errorMessage();
- }
- },
- complete: function (jqXHR) {
- if (neighbours_status.every(function (elt) { return elt.checked; })) {
- if (neighbours_status.some(function (elt) { return elt.status; })) {
- if (o.success) {
- o.success(neighbours_status, jqXHR);
- } else {
- alertMessage("alert-success", "Request completed");
- }
- } else {
- alertMessage("alert-error", "Request failed");
- }
- NProgress.done();
- }
- },
- statusCode: o.statusCode
- };
- if (o.method) {
- req_params.method = o.method;
- }
- if (o.params) {
- $.each(o.params, function (k, v) {
- req_params[k] = v;
- });
- }
- $.ajax(req_params);
- }
-
- // Public functions
- ui.alertMessage = alertMessage;
- ui.setup = function () {
- $("#selData").change(function () {
- selData = this.value;
- tabClick("#throughput_nav");
- });
- $.ajaxSetup({
- timeout: 20000,
- jsonp: false
- });
-
- $(document).ajaxStart(function () {
- $("#navBar").addClass("loading");
- });
- $(document).ajaxComplete(function () {
- setTimeout(function () {
- $("#navBar").removeClass("loading");
- }, 1000);
- });
-
- $("a[data-toggle=\"tab\"]").on("shown.bs.tab", function (e) {
- var tab_id = "#" + $(e.target).attr("id");
- tabClick(tab_id);
- });
- $("a[data-toggle=\"button\"]").on("click", function (e) {
- var tab_id = "#" + $(e.target).attr("id");
- tabClick(tab_id);
- });
-
- $("#selSrv").change(function () {
- checked_server = this.value;
- $("#selSrv [value=\"" + checked_server + "\"]").prop("checked", true);
- tabClick("#" + $("#navBar ul li.active > a").attr("id"));
- });
-
- // Radio buttons
- $(document).on("click", "input:radio[name=\"clusterName\"]", function () {
- if (!this.disabled) {
- checked_server = this.value;
- tabClick("#status_nav");
- }
- });
- tab_config.setup(ui);
- tab_history.setup(ui, tables);
- tab_symbols.setup(ui, tables);
- tab_upload.setup(ui, tables);
- selData = tab_graph.setup(ui);
- };
-
- ui.connect = function () {
- // Query "/stat" to check if user is already logged in or client ip matches "secure_ip"
- $.ajax({
- type: "GET",
- url: "stat",
- async: false,
- success: function () {
- displayUI();
- },
- error: function () {
- var dialog = $("#connectDialog");
- var backdrop = $("#backDrop");
- $("#mainUI").hide();
- $(dialog).show();
- $(backdrop).show();
- $("#connectPassword").focus();
- $("#connectForm").off("submit");
-
- $("#connectForm").on("submit", function (e) {
- e.preventDefault();
- var password = $("#connectPassword").val();
- if (!(/^[\u0020-\u007e]*$/).test(password)) {
- alertMessage("alert-modal alert-error", "Invalid characters in the password");
- $("#connectPassword").focus();
- return;
- }
-
- ui.query("auth", {
- headers: {
- Password: password
- },
- success: function (json) {
- var data = json[0].data;
- $("#connectPassword").val("");
- if (data.auth === "ok") {
- sessionStorage.setItem("read_only", data.read_only);
- saveCredentials(password);
- $(dialog).hide();
- $(backdrop).hide();
- displayUI();
- }
- },
- error: function (jqXHR) {
- ui.alertMessage("alert-modal alert-error", jqXHR.statusText);
- $("#connectPassword").val("");
- $("#connectPassword").focus();
- },
- params: {
- global: false,
- },
- server: "local"
- });
- });
- }
- });
- };
-
- ui.drawPie = function (object, id, data, conf) {
- var obj = object;
- if (obj) {
- obj.updateProp("data.content",
- data.filter(function (elt) {
- return elt.value > 0;
- })
- );
- } else {
- obj = new D3pie(id,
- $.extend({}, {
- header: {
- title: {
- text: "Rspamd filter stats",
- fontSize: 24,
- font: "open sans"
- },
- subtitle: {
- color: "#999999",
- fontSize: 12,
- font: "open sans"
- },
- titleSubtitlePadding: 9
- },
- footer: {
- color: "#999999",
- fontSize: 10,
- font: "open sans",
- location: "bottom-left"
- },
- size: {
- canvasWidth: 600,
- canvasHeight: 400,
- pieInnerRadius: "20%",
- pieOuterRadius: "85%"
- },
- data: {
- // "sortOrder": "value-desc",
- content: data.filter(function (elt) {
- return elt.value > 0;
- })
- },
- labels: {
- outer: {
- hideWhenLessThanPercentage: 1,
- pieDistance: 30
- },
- inner: {
- hideWhenLessThanPercentage: 4
- },
- mainLabel: {
- fontSize: 14
- },
- percentage: {
- color: "#eeeeee",
- fontSize: 14,
- decimalPlaces: 0
- },
- lines: {
- enabled: true
- },
- truncation: {
- enabled: true
- }
- },
- tooltips: {
- enabled: true,
- type: "placeholder",
- string: "{label}: {value} ({percentage}%)"
- },
- effects: {
- pullOutSegmentOnClick: {
- effect: "back",
- speed: 400,
- size: 8
- },
- load: {
- effect: "none"
- }
- },
- misc: {
- gradient: {
- enabled: true,
- percentage: 100
- }
- }
- }, conf));
- }
- return obj;
- };
-
- ui.getPassword = getPassword;
- ui.getSelector = getSelector;
-
- /**
- * @param {string} url - A string containing the URL to which the request is sent
- * @param {Object} [options] - A set of key/value pairs that configure the Ajax request. All settings are optional.
- *
- * @param {Object|string|Array} [options.data] - Data to be sent to the server.
- * @param {Function} [options.error] - A function to be called if the request fails.
- * @param {string} [options.errorMessage] - Text to display in the alert message if the request fails.
- * @param {string} [options.errorOnceId] - A prefix of the alert ID to be added to the session storage. If the
- * parameter is set, the error for each server will be displayed only once per session.
- * @param {Object} [options.headers] - An object of additional header key/value pairs to send along with requests
- * using the XMLHttpRequest transport.
- * @param {string} [options.method] - The HTTP method to use for the request.
- * @param {Object} [options.params] - An object of additional jQuery.ajax() settings key/value pairs.
- * @param {string} [options.server] - A server to which send the request.
- * @param {Function} [options.success] - A function to be called if the request succeeds.
- *
- * @returns {undefined}
- */
- ui.query = function (url, options) {
- // Force options to be an object
- var o = options || {};
- Object.keys(o).forEach(function (option) {
- if (["data", "error", "errorMessage", "errorOnceId", "headers", "method", "params", "server", "statusCode",
- "success"]
- .indexOf(option) < 0) {
- throw new Error("Unknown option: " + option);
- }
- });
-
- var neighbours_status = [{
- name: "local",
- host: "local",
- url: "",
- }];
- o.server = o.server || checked_server;
- if (o.server === "All SERVERS") {
- queryServer(neighbours_status, 0, "neighbours", {
- success: function (json) {
- var data = json[0].data;
- if (jQuery.isEmptyObject(data)) {
- neighbours = {
- local: {
- host: window.location.host,
- url: window.location.origin + window.location.pathname
- }
- };
- } else {
- neighbours = data;
- }
- neighbours_status = [];
- $.each(neighbours, function (ind) {
- neighbours_status.push({
- name: ind,
- host: neighbours[ind].host,
- url: neighbours[ind].url,
- });
- });
- $.each(neighbours_status, function (ind) {
- queryServer(neighbours_status, ind, url, o);
- });
- },
- errorMessage: "Cannot receive neighbours data"
- });
- } else {
- if (o.server !== "local") {
- neighbours_status = [{
- name: o.server,
- host: neighbours[o.server].host,
- url: neighbours[o.server].url,
- }];
- }
- queryServer(neighbours_status, 0, url, o);
- }
- };
-
- // Scan and History shared functions
-
- ui.drawTooltips = drawTooltips;
- ui.unix_time_format = unix_time_format;
- ui.set_page_size = set_page_size;
-
- ui.bindHistoryTableEventHandlers = function (table, symbolsCol) {
- function change_symbols_order(order) {
- $(".btn-sym-" + table + "-" + order).addClass("active").siblings().removeClass("active");
- var compare_function = get_compare_function(table);
- $.each(tables[table].rows.all, function (i, row) {
- var cell_val = sort_symbols(ui.symbols[table][i], compare_function);
- row.cells[symbolsCol].val(cell_val, false, true);
- });
- drawTooltips();
- }
-
- $("#selSymOrder_" + table).unbind().change(function () {
- var order = this.value;
- change_symbols_order(order);
- });
- $("#" + table + "_page_size").change(function () {
- set_page_size(table, this.value, function (n) { tables[table].pageSize(n); });
- });
- $(document).on("click", ".btn-sym-order-" + table + " button", function () {
- var order = this.value;
- $("#selSymOrder_" + table).val(order);
- change_symbols_order(order);
- });
- };
-
- ui.destroyTable = function (table) {
- if (tables[table]) {
- tables[table].destroy();
- delete tables[table];
- }
- };
-
-
- ui.initHistoryTable = function (rspamd, data, items, table, columns, expandFirst) {
- /* eslint-disable consistent-this, no-underscore-dangle, one-var-declaration-per-line */
- FooTable.actionFilter = FooTable.Filtering.extend({
- construct: function (instance) {
- this._super(instance);
- this.actions = ["reject", "add header", "greylist",
- "no action", "soft reject", "rewrite subject"];
- this.def = "Any action";
- this.$action = null;
- },
- $create: function () {
- this._super();
- var self = this, $form_grp = $("<div/>", {
- class: "form-group"
- }).append($("<label/>", {
- class: "sr-only",
- text: "Action"
- })).prependTo(self.$form);
-
- self.$action = $("<select/>", {
- class: "form-control"
- }).on("change", {
- self: self
- }, self._onStatusDropdownChanged).append(
- $("<option/>", {
- text: self.def
- })).appendTo($form_grp);
-
- $.each(self.actions, function (i, action) {
- self.$action.append($("<option/>").text(action));
- });
- },
- _onStatusDropdownChanged: function (e) {
- var self = e.data.self, selected = $(this).val();
- if (selected !== self.def) {
- if (selected === "reject") {
- self.addFilter("action", "reject -soft", ["action"]);
- } else {
- self.addFilter("action", selected, ["action"]);
- }
- } else {
- self.removeFilter("action");
- }
- self.filter();
- },
- draw: function () {
- this._super();
- var action = this.find("action");
- if (action instanceof FooTable.Filter) {
- if (action.query.val() === "reject -soft") {
- this.$action.val("reject");
- } else {
- this.$action.val(action.query.val());
- }
- } else {
- this.$action.val(this.def);
- }
- }
- });
- /* eslint-enable consistent-this, no-underscore-dangle, one-var-declaration-per-line */
-
- tables[table] = FooTable.init("#historyTable_" + table, {
- columns: columns,
- rows: items,
- expandFirst: expandFirst,
- paging: {
- enabled: true,
- limit: 5,
- size: ui.page_size[table]
- },
- filtering: {
- enabled: true,
- position: "left",
- connectors: false
- },
- sorting: {
- enabled: true
- },
- components: {
- filtering: FooTable.actionFilter
- },
- on: {
- "ready.ft.table": drawTooltips,
- "after.ft.sorting": drawTooltips,
- "after.ft.paging": drawTooltips,
- "after.ft.filtering": drawTooltips,
- "expand.ft.row": function (e, ft, row) {
- setTimeout(function () {
- var detail_row = row.$el.next();
- var order = getSelector("selSymOrder_" + table);
- detail_row.find(".btn-sym-" + table + "-" + order)
- .addClass("active").siblings().removeClass("active");
- }, 5);
- }
- }
- });
- };
-
- ui.preprocess_item = function (rspamd, item) {
- function escapeHTML(string) {
- var htmlEscaper = /[&<>"'/`=]/g;
- var htmlEscapes = {
- "&": "&",
- "<": "<",
- ">": ">",
- "\"": """,
- "'": "'",
- "/": "/",
- "`": "`",
- "=": "="
- };
- return String(string).replace(htmlEscaper, function (match) {
- return htmlEscapes[match];
- });
- }
- function escape_HTML_array(arr) {
- arr.forEach(function (d, i) { arr[i] = escapeHTML(d); });
- }
-
- for (var prop in item) {
- if (!{}.hasOwnProperty.call(item, prop)) continue;
- switch (prop) {
- case "rcpt_mime":
- case "rcpt_smtp":
- escape_HTML_array(item[prop]);
- break;
- case "symbols":
- Object.keys(item.symbols).forEach(function (key) {
- var sym = item.symbols[key];
- if (!sym.name) {
- sym.name = key;
- }
- sym.name = escapeHTML(sym.name);
- if (sym.description) {
- sym.description = escapeHTML(sym.description);
- }
-
- if (sym.options) {
- escape_HTML_array(sym.options);
- }
- });
- break;
- default:
- if (typeof item[prop] === "string") {
- item[prop] = escapeHTML(item[prop]);
- }
- }
- }
-
- if (item.action === "clean" || item.action === "no action") {
- item.action = "<div style='font-size:11px' class='label label-success'>" + item.action + "</div>";
- } else if (item.action === "rewrite subject" || item.action === "add header" || item.action === "probable spam") {
- item.action = "<div style='font-size:11px' class='label label-warning'>" + item.action + "</div>";
- } else if (item.action === "spam" || item.action === "reject") {
- item.action = "<div style='font-size:11px' class='label label-danger'>" + item.action + "</div>";
- } else {
- item.action = "<div style='font-size:11px' class='label label-info'>" + item.action + "</div>";
- }
-
- var score_content = (item.score < item.required_score)
- ? "<span class='text-success'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>"
- : "<span class='text-danger'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>";
-
- item.score = {
- options: {
- sortValue: item.score
- },
- value: score_content
- };
- };
-
- ui.process_history_v2 = function (rspamd, data, table) {
- // Display no more than rcpt_lim recipients
- var rcpt_lim = 3;
- var items = [];
- var unsorted_symbols = [];
- var compare_function = get_compare_function(table);
-
- $("#selSymOrder_" + table + ", label[for='selSymOrder_" + table + "']").show();
-
- $.each(data.rows,
- function (i, item) {
- function more(p) {
- var l = item[p].length;
- return (l > rcpt_lim) ? " … (" + l + ")" : "";
- }
- function format_rcpt(smtp, mime) {
- var full = "";
- var shrt = "";
- if (smtp) {
- full = "[" + item.rcpt_smtp.join(", ") + "] ";
- shrt = "[" + item.rcpt_smtp.slice(0, rcpt_lim).join(",​") + more("rcpt_smtp") + "]";
- if (mime) {
- full += " ";
- shrt += " ";
- }
- }
- if (mime) {
- full += item.rcpt_mime.join(", ");
- shrt += item.rcpt_mime.slice(0, rcpt_lim).join(",​") + more("rcpt_mime");
- }
- return {full:full, shrt:shrt};
- }
-
- function get_symbol_class(name, score) {
- if (name.match(/^GREYLIST$/)) {
- return "symbol-special";
- }
-
- if (score < 0) {
- return "symbol-negative";
- } else if (score > 0) {
- return "symbol-positive";
- }
- return null;
- }
-
- rspamd.preprocess_item(rspamd, item);
- Object.keys(item.symbols).forEach(function (key) {
- var sym = item.symbols[key];
- sym.str = '<span class="symbol-default ' + get_symbol_class(sym.name, sym.score) + '"><strong>';
-
- if (sym.description) {
- sym.str += '<abbr data-sym-key="' + key + '">' +
- sym.name + "</abbr></strong> (" + sym.score + ")</span>";
- // Store description for tooltip
- symbolDescriptions[key] = sym.description;
- } else {
- sym.str += sym.name + "</strong> (" + sym.score + ")</span>";
- }
-
- if (sym.options) {
- sym.str += " [" + sym.options.join(",") + "]";
- }
- });
- unsorted_symbols.push(item.symbols);
- item.symbols = sort_symbols(item.symbols, compare_function);
- if (table === "scan") {
- item.unix_time = (new Date()).getTime() / 1000;
- }
- item.time = {
- value: unix_time_format(item.unix_time),
- options: {
- sortValue: item.unix_time
- }
- };
- item.time_real = item.time_real.toFixed(3);
- item.id = item["message-id"];
-
- if (table === "history") {
- var rcpt = {};
- if (!item.rcpt_mime.length) {
- rcpt = format_rcpt(true, false);
- } else if ($(item.rcpt_mime).not(item.rcpt_smtp).length !== 0 || $(item.rcpt_smtp).not(item.rcpt_mime).length !== 0) {
- rcpt = format_rcpt(true, true);
- } else {
- rcpt = format_rcpt(false, true);
- }
- item.rcpt_mime_short = rcpt.shrt;
- item.rcpt_mime = rcpt.full;
-
- if (item.sender_mime !== item.sender_smtp) {
- item.sender_mime = "[" + item.sender_smtp + "] " + item.sender_mime;
- }
- }
- items.push(item);
- });
-
- return {items:items, symbols:unsorted_symbols};
- };
-
- ui.waitForRowsDisplayed = function (table, rows_total, callback, iteration) {
- var i = (typeof iteration === "undefined") ? 10 : iteration;
- var num_rows = $("#historyTable_" + table + " > tbody > tr:not(.footable-detail-row)").length;
- if (num_rows === ui.page_size[table] ||
- num_rows === rows_total) {
- return callback();
- } else if (--i) {
- setTimeout(function () {
- ui.waitForRowsDisplayed(table, rows_total, callback, i);
- }, 500);
- }
- return null;
- };
-
- return ui;
- });
|