mirror of https://github.com/gophish/gophish
Delete static/js/dist/app/campaign_results.min.js
parent
897a6ffcc4
commit
d74eec9b25
|
@ -1,879 +0,0 @@
|
||||||
var map = null;
|
|
||||||
var doPoll = true;
|
|
||||||
var statuses = {
|
|
||||||
"Email Sent": {
|
|
||||||
color: "#1abc9c",
|
|
||||||
label: "label-success",
|
|
||||||
icon: "fa-envelope",
|
|
||||||
point: "ct-point-sent",
|
|
||||||
},
|
|
||||||
"Emails Sent": {
|
|
||||||
color: "#1abc9c",
|
|
||||||
label: "label-success",
|
|
||||||
icon: "fa-envelope",
|
|
||||||
point: "ct-point-sent",
|
|
||||||
},
|
|
||||||
"In progress": { label: "label-primary" },
|
|
||||||
Queued: { label: "label-info" },
|
|
||||||
Completed: { label: "label-success" },
|
|
||||||
"Email Opened": {
|
|
||||||
color: "#f9bf3b",
|
|
||||||
label: "label-warning",
|
|
||||||
icon: "fa-envelope-open",
|
|
||||||
point: "ct-point-opened",
|
|
||||||
},
|
|
||||||
"Clicked Link": {
|
|
||||||
color: "#F39C12",
|
|
||||||
label: "label-clicked",
|
|
||||||
icon: "fa-mouse-pointer",
|
|
||||||
point: "ct-point-clicked",
|
|
||||||
},
|
|
||||||
Success: {
|
|
||||||
color: "#f05b4f",
|
|
||||||
label: "label-danger",
|
|
||||||
icon: "fa-exclamation",
|
|
||||||
point: "ct-point-clicked",
|
|
||||||
},
|
|
||||||
"Email Reported": {
|
|
||||||
color: "#45d6ef",
|
|
||||||
label: "label-info",
|
|
||||||
icon: "fa-bullhorn",
|
|
||||||
point: "ct-point-reported",
|
|
||||||
},
|
|
||||||
Error: {
|
|
||||||
color: "#6c7a89",
|
|
||||||
label: "label-default",
|
|
||||||
icon: "fa-times",
|
|
||||||
point: "ct-point-error",
|
|
||||||
},
|
|
||||||
"Error Sending Email": {
|
|
||||||
color: "#6c7a89",
|
|
||||||
label: "label-default",
|
|
||||||
icon: "fa-times",
|
|
||||||
point: "ct-point-error",
|
|
||||||
},
|
|
||||||
"Submitted Data": {
|
|
||||||
color: "#f05b4f",
|
|
||||||
label: "label-danger",
|
|
||||||
icon: "fa-exclamation",
|
|
||||||
point: "ct-point-clicked",
|
|
||||||
},
|
|
||||||
Unknown: {
|
|
||||||
color: "#6c7a89",
|
|
||||||
label: "label-default",
|
|
||||||
icon: "fa-question",
|
|
||||||
point: "ct-point-error",
|
|
||||||
},
|
|
||||||
Sending: {
|
|
||||||
color: "#428bca",
|
|
||||||
label: "label-primary",
|
|
||||||
icon: "fa-spinner",
|
|
||||||
point: "ct-point-sending",
|
|
||||||
},
|
|
||||||
Retrying: {
|
|
||||||
color: "#6c7a89",
|
|
||||||
label: "label-default",
|
|
||||||
icon: "fa-clock-o",
|
|
||||||
point: "ct-point-error",
|
|
||||||
},
|
|
||||||
Scheduled: {
|
|
||||||
color: "#428bca",
|
|
||||||
label: "label-primary",
|
|
||||||
icon: "fa-clock-o",
|
|
||||||
point: "ct-point-sending",
|
|
||||||
},
|
|
||||||
"Campaign Created": { label: "label-success", icon: "fa-rocket" },
|
|
||||||
};
|
|
||||||
var statusMapping = {
|
|
||||||
"Email Sent": "sent",
|
|
||||||
"Email Opened": "opened",
|
|
||||||
"Clicked Link": "clicked",
|
|
||||||
"Submitted Data": "submitted_data",
|
|
||||||
"Email Reported": "reported",
|
|
||||||
};
|
|
||||||
var progressListing = [
|
|
||||||
"Email Sent",
|
|
||||||
"Email Opened",
|
|
||||||
"Clicked Link",
|
|
||||||
"Submitted Data",
|
|
||||||
];
|
|
||||||
var campaign = {};
|
|
||||||
var bubbles = [];
|
|
||||||
function dismiss() {
|
|
||||||
$("#modal\\.flashes").empty();
|
|
||||||
$("#modal").modal("hide");
|
|
||||||
$("#resultsTable").dataTable().DataTable().clear().draw();
|
|
||||||
}
|
|
||||||
function deleteCampaign() {
|
|
||||||
Swal.fire({
|
|
||||||
title: "Are you sure?",
|
|
||||||
text: "This will delete the campaign. This can't be undone!",
|
|
||||||
type: "warning",
|
|
||||||
animation: false,
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: "Delete Campaign",
|
|
||||||
confirmButtonColor: "#428bca",
|
|
||||||
reverseButtons: true,
|
|
||||||
allowOutsideClick: false,
|
|
||||||
showLoaderOnConfirm: true,
|
|
||||||
preConfirm: function () {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
api.campaignId
|
|
||||||
.delete(campaign.id)
|
|
||||||
.success(function (msg) {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.error(function (data) {
|
|
||||||
reject(data.responseJSON.message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.value) {
|
|
||||||
Swal.fire(
|
|
||||||
"Campaign Deleted!",
|
|
||||||
"This campaign has been deleted!",
|
|
||||||
"success"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$('button:contains("OK")').on("click", function () {
|
|
||||||
location.href = "/campaigns";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function completeCampaign() {
|
|
||||||
Swal.fire({
|
|
||||||
title: "Are you sure?",
|
|
||||||
text: "Gophish will stop processing events for this campaign",
|
|
||||||
type: "warning",
|
|
||||||
animation: false,
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: "Complete Campaign",
|
|
||||||
confirmButtonColor: "#428bca",
|
|
||||||
reverseButtons: true,
|
|
||||||
allowOutsideClick: false,
|
|
||||||
showLoaderOnConfirm: true,
|
|
||||||
preConfirm: function () {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
api.campaignId
|
|
||||||
.complete(campaign.id)
|
|
||||||
.success(function (msg) {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.error(function (data) {
|
|
||||||
reject(data.responseJSON.message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.value) {
|
|
||||||
Swal.fire(
|
|
||||||
"Campaign Completed!",
|
|
||||||
"This campaign has been completed!",
|
|
||||||
"success"
|
|
||||||
);
|
|
||||||
$("#complete_button")[0].disabled = true;
|
|
||||||
$("#complete_button").text("Completed!");
|
|
||||||
doPoll = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function exportAsCSV(scope) {
|
|
||||||
exportHTML = $("#exportButton").html();
|
|
||||||
var csvScope = null;
|
|
||||||
var filename = campaign.name + " - " + capitalize(scope) + ".csv";
|
|
||||||
switch (scope) {
|
|
||||||
case "results":
|
|
||||||
csvScope = campaign.results;
|
|
||||||
break;
|
|
||||||
case "events":
|
|
||||||
csvScope = campaign.timeline;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!csvScope) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$("#exportButton").html('<i class="fa fa-spinner fa-spin"></i>');
|
|
||||||
var csvString = Papa.unparse(csvScope, { escapeFormulae: true });
|
|
||||||
var csvData = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
||||||
if (navigator.msSaveBlob) {
|
|
||||||
navigator.msSaveBlob(csvData, filename);
|
|
||||||
} else {
|
|
||||||
var csvURL = window.URL.createObjectURL(csvData);
|
|
||||||
var dlLink = document.createElement("a");
|
|
||||||
dlLink.href = csvURL;
|
|
||||||
dlLink.setAttribute("download", filename);
|
|
||||||
document.body.appendChild(dlLink);
|
|
||||||
dlLink.click();
|
|
||||||
document.body.removeChild(dlLink);
|
|
||||||
}
|
|
||||||
$("#exportButton").html(exportHTML);
|
|
||||||
}
|
|
||||||
function replay(event_idx) {
|
|
||||||
request = campaign.timeline[event_idx];
|
|
||||||
details = JSON.parse(request.details);
|
|
||||||
url = null;
|
|
||||||
form = $("<form>").attr({ method: "POST", target: "_blank" });
|
|
||||||
$.each(Object.keys(details.payload), function (i, param) {
|
|
||||||
if (param == "rid") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (param == "__original_url") {
|
|
||||||
url = details.payload[param];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$("<input>")
|
|
||||||
.attr({ name: param })
|
|
||||||
.val(details.payload[param])
|
|
||||||
.appendTo(form);
|
|
||||||
});
|
|
||||||
Swal.fire({
|
|
||||||
title: "Where do you want the credentials submitted to?",
|
|
||||||
input: "text",
|
|
||||||
showCancelButton: true,
|
|
||||||
inputPlaceholder: "http://example.com/login",
|
|
||||||
inputValue: url || "",
|
|
||||||
inputValidator: function (value) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
if (value) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject("Invalid URL.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.value) {
|
|
||||||
url = result.value;
|
|
||||||
submitForm();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
submitForm();
|
|
||||||
function submitForm() {
|
|
||||||
form.attr({ action: url });
|
|
||||||
form.appendTo("body").submit().remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var renderDevice = function (event_details) {
|
|
||||||
var ua = UAParser(details.browser["user-agent"]);
|
|
||||||
var detailsString = '<div class="timeline-device-details">';
|
|
||||||
var deviceIcon = "laptop";
|
|
||||||
if (ua.device.type) {
|
|
||||||
if (ua.device.type == "tablet" || ua.device.type == "mobile") {
|
|
||||||
deviceIcon = ua.device.type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var deviceVendor = "";
|
|
||||||
if (ua.device.vendor) {
|
|
||||||
deviceVendor = ua.device.vendor.toLowerCase();
|
|
||||||
if (deviceVendor == "microsoft") deviceVendor = "windows";
|
|
||||||
}
|
|
||||||
var deviceName = "Unknown";
|
|
||||||
if (ua.os.name) {
|
|
||||||
deviceName = ua.os.name;
|
|
||||||
if (deviceName == "Mac OS") {
|
|
||||||
deviceVendor = "apple";
|
|
||||||
} else if (deviceName == "Windows") {
|
|
||||||
deviceVendor = "windows";
|
|
||||||
}
|
|
||||||
if (ua.device.vendor && ua.device.model) {
|
|
||||||
deviceName = ua.device.vendor + " " + ua.device.model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ua.os.version) {
|
|
||||||
deviceName = deviceName + " (OS Version: " + ua.os.version + ")";
|
|
||||||
}
|
|
||||||
deviceString =
|
|
||||||
'<div class="timeline-device-os"><span class="fa fa-stack">' +
|
|
||||||
'<i class="fa fa-' +
|
|
||||||
escapeHtml(deviceIcon) +
|
|
||||||
' fa-stack-2x"></i>' +
|
|
||||||
'<i class="fa fa-vendor-icon fa-' +
|
|
||||||
escapeHtml(deviceVendor) +
|
|
||||||
' fa-stack-1x"></i>' +
|
|
||||||
"</span> " +
|
|
||||||
escapeHtml(deviceName) +
|
|
||||||
"</div>";
|
|
||||||
detailsString += deviceString;
|
|
||||||
var deviceBrowser = "Unknown";
|
|
||||||
var browserIcon = "info-circle";
|
|
||||||
var browserVersion = "";
|
|
||||||
if (ua.browser && ua.browser.name) {
|
|
||||||
deviceBrowser = ua.browser.name;
|
|
||||||
deviceBrowser = deviceBrowser.replace("Mobile ", "");
|
|
||||||
if (deviceBrowser) {
|
|
||||||
browserIcon = deviceBrowser.toLowerCase();
|
|
||||||
if (browserIcon == "ie") browserIcon = "internet-explorer";
|
|
||||||
}
|
|
||||||
browserVersion = "(Version: " + ua.browser.version + ")";
|
|
||||||
}
|
|
||||||
var browserString =
|
|
||||||
'<div class="timeline-device-browser"><span class="fa fa-stack">' +
|
|
||||||
'<i class="fa fa-' +
|
|
||||||
escapeHtml(browserIcon) +
|
|
||||||
' fa-stack-1x"></i></span> ' +
|
|
||||||
deviceBrowser +
|
|
||||||
" " +
|
|
||||||
browserVersion +
|
|
||||||
"</div>";
|
|
||||||
detailsString += browserString;
|
|
||||||
detailsString += "</div>";
|
|
||||||
return detailsString;
|
|
||||||
};
|
|
||||||
function renderTimeline(data) {
|
|
||||||
record = {
|
|
||||||
id: data[0],
|
|
||||||
first_name: data[2],
|
|
||||||
last_name: data[3],
|
|
||||||
email: data[4],
|
|
||||||
position: data[5],
|
|
||||||
status: data[6],
|
|
||||||
reported: data[7],
|
|
||||||
send_date: data[8],
|
|
||||||
};
|
|
||||||
results =
|
|
||||||
'<div class="timeline col-sm-12 well well-lg">' +
|
|
||||||
"<h6>Timeline for " +
|
|
||||||
escapeHtml(record.first_name) +
|
|
||||||
" " +
|
|
||||||
escapeHtml(record.last_name) +
|
|
||||||
'</h6><span class="subtitle">Email: ' +
|
|
||||||
escapeHtml(record.email) +
|
|
||||||
"<br>Result ID: " +
|
|
||||||
escapeHtml(record.id) +
|
|
||||||
"</span>" +
|
|
||||||
'<div class="timeline-graph col-sm-6">';
|
|
||||||
$.each(campaign.timeline, function (i, event) {
|
|
||||||
if (!event.email || event.email == record.email) {
|
|
||||||
results +=
|
|
||||||
'<div class="timeline-entry">' + ' <div class="timeline-bar"></div>';
|
|
||||||
results +=
|
|
||||||
' <div class="timeline-icon ' +
|
|
||||||
statuses[event.message].label +
|
|
||||||
'">' +
|
|
||||||
' <i class="fa ' +
|
|
||||||
statuses[event.message].icon +
|
|
||||||
'"></i></div>' +
|
|
||||||
' <div class="timeline-message">' +
|
|
||||||
escapeHtml(event.message) +
|
|
||||||
' <span class="timeline-date">' +
|
|
||||||
moment.utc(event.time).local().format("MMMM Do YYYY h:mm:ss a") +
|
|
||||||
"</span>";
|
|
||||||
if (event.details) {
|
|
||||||
details = JSON.parse(event.details);
|
|
||||||
if (
|
|
||||||
event.message == "Clicked Link" ||
|
|
||||||
event.message == "Submitted Data"
|
|
||||||
) {
|
|
||||||
deviceView = renderDevice(details);
|
|
||||||
if (deviceView) {
|
|
||||||
results += deviceView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.message == "Submitted Data") {
|
|
||||||
results +=
|
|
||||||
'<div class="timeline-replay-button"><button onclick="replay(' +
|
|
||||||
i +
|
|
||||||
')" class="btn btn-success">';
|
|
||||||
results +=
|
|
||||||
'<i class="fa fa-refresh"></i> Replay Credentials</button></div>';
|
|
||||||
results +=
|
|
||||||
'<div class="timeline-event-details"><i class="fa fa-caret-right"></i> View Details</div>';
|
|
||||||
}
|
|
||||||
if (details.payload) {
|
|
||||||
results += '<div class="timeline-event-results">';
|
|
||||||
results +=
|
|
||||||
' <table class="table table-condensed table-bordered table-striped">';
|
|
||||||
results +=
|
|
||||||
" <thead><tr><th>Parameter</th><th>Value(s)</tr></thead><tbody>";
|
|
||||||
$.each(Object.keys(details.payload), function (i, param) {
|
|
||||||
if (param == "rid") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
results += " <tr>";
|
|
||||||
results += " <td>" + escapeHtml(param) + "</td>";
|
|
||||||
results +=
|
|
||||||
" <td>" + escapeHtml(details.payload[param]) + "</td>";
|
|
||||||
results += " </tr>";
|
|
||||||
});
|
|
||||||
results += " </tbody></table>";
|
|
||||||
results += "</div>";
|
|
||||||
}
|
|
||||||
if (details.error) {
|
|
||||||
results +=
|
|
||||||
'<div class="timeline-event-details"><i class="fa fa-caret-right"></i> View Details</div>';
|
|
||||||
results += '<div class="timeline-event-results">';
|
|
||||||
results +=
|
|
||||||
'<span class="label label-default">Error</span> ' + details.error;
|
|
||||||
results += "</div>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results += "</div></div>";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (record.status == "Scheduled" || record.status == "Retrying") {
|
|
||||||
results +=
|
|
||||||
'<div class="timeline-entry">' + ' <div class="timeline-bar"></div>';
|
|
||||||
results +=
|
|
||||||
' <div class="timeline-icon ' +
|
|
||||||
statuses[record.status].label +
|
|
||||||
'">' +
|
|
||||||
' <i class="fa ' +
|
|
||||||
statuses[record.status].icon +
|
|
||||||
'"></i></div>' +
|
|
||||||
' <div class="timeline-message">' +
|
|
||||||
"Scheduled to send at " +
|
|
||||||
record.send_date +
|
|
||||||
"</span>";
|
|
||||||
}
|
|
||||||
results += "</div></div>";
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
var renderTimelineChart = function (chartopts) {
|
|
||||||
return Highcharts.chart("timeline_chart", {
|
|
||||||
chart: { zoomType: "x", type: "line", height: "200px" },
|
|
||||||
title: { text: "Campaign Timeline" },
|
|
||||||
xAxis: {
|
|
||||||
type: "datetime",
|
|
||||||
dateTimeLabelFormats: {
|
|
||||||
second: "%l:%M:%S",
|
|
||||||
minute: "%l:%M",
|
|
||||||
hour: "%l:%M",
|
|
||||||
day: "%b %d, %Y",
|
|
||||||
week: "%b %d, %Y",
|
|
||||||
month: "%b %Y",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
min: 0,
|
|
||||||
max: 2,
|
|
||||||
visible: false,
|
|
||||||
tickInterval: 1,
|
|
||||||
labels: { enabled: false },
|
|
||||||
title: { text: "" },
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter: function () {
|
|
||||||
return (
|
|
||||||
Highcharts.dateFormat("%A, %b %d %l:%M:%S %P", new Date(this.x)) +
|
|
||||||
"<br>Event: " +
|
|
||||||
this.point.message +
|
|
||||||
"<br>Email: <b>" +
|
|
||||||
this.point.email +
|
|
||||||
"</b>"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: { enabled: false },
|
|
||||||
plotOptions: {
|
|
||||||
series: {
|
|
||||||
marker: { enabled: true, symbol: "circle", radius: 3 },
|
|
||||||
cursor: "pointer",
|
|
||||||
},
|
|
||||||
line: { states: { hover: { lineWidth: 1 } } },
|
|
||||||
},
|
|
||||||
credits: { enabled: false },
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: chartopts["data"],
|
|
||||||
dashStyle: "shortdash",
|
|
||||||
color: "#cccccc",
|
|
||||||
lineWidth: 1,
|
|
||||||
turboThreshold: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var renderPieChart = function (chartopts) {
|
|
||||||
return Highcharts.chart(chartopts["elemId"], {
|
|
||||||
chart: {
|
|
||||||
type: "pie",
|
|
||||||
events: {
|
|
||||||
load: function () {
|
|
||||||
var chart = this,
|
|
||||||
rend = chart.renderer,
|
|
||||||
pie = chart.series[0],
|
|
||||||
left = chart.plotLeft + pie.center[0],
|
|
||||||
top = chart.plotTop + pie.center[1];
|
|
||||||
this.innerText = rend
|
|
||||||
.text(chartopts["data"][0].count, left, top)
|
|
||||||
.attr({
|
|
||||||
"text-anchor": "middle",
|
|
||||||
"font-size": "24px",
|
|
||||||
"font-weight": "bold",
|
|
||||||
fill: chartopts["colors"][0],
|
|
||||||
"font-family": "Helvetica,Arial,sans-serif",
|
|
||||||
})
|
|
||||||
.add();
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
this.innerText.attr({ text: chartopts["data"][0].count });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
title: { text: chartopts["title"] },
|
|
||||||
plotOptions: { pie: { innerSize: "80%", dataLabels: { enabled: false } } },
|
|
||||||
credits: { enabled: false },
|
|
||||||
tooltip: {
|
|
||||||
formatter: function () {
|
|
||||||
if (this.key == undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
'<span style="color:' +
|
|
||||||
this.color +
|
|
||||||
'">●</span>' +
|
|
||||||
this.point.name +
|
|
||||||
": <b>" +
|
|
||||||
this.y +
|
|
||||||
"%</b><br/>"
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: [{ data: chartopts["data"], colors: chartopts["colors"] }],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var updateMap = function (results) {
|
|
||||||
if (!map) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bubbles = [];
|
|
||||||
$.each(campaign.results, function (i, result) {
|
|
||||||
if (result.latitude == 0 && result.longitude == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
newIP = true;
|
|
||||||
$.each(bubbles, function (i, bubble) {
|
|
||||||
if (bubble.ip == result.ip) {
|
|
||||||
bubbles[i].radius += 1;
|
|
||||||
newIP = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (newIP) {
|
|
||||||
bubbles.push({
|
|
||||||
latitude: result.latitude,
|
|
||||||
longitude: result.longitude,
|
|
||||||
name: result.ip,
|
|
||||||
fillKey: "point",
|
|
||||||
radius: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
map.bubbles(bubbles);
|
|
||||||
};
|
|
||||||
function createStatusLabel(status, send_date) {
|
|
||||||
var label = statuses[status].label || "label-default";
|
|
||||||
var statusColumn = '<span class="label ' + label + '">' + status + "</span>";
|
|
||||||
if (status == "Scheduled" || status == "Retrying") {
|
|
||||||
var sendDateMessage = "Scheduled to send at " + send_date;
|
|
||||||
statusColumn =
|
|
||||||
'<span class="label ' +
|
|
||||||
label +
|
|
||||||
'" data-toggle="tooltip" data-placement="top" data-html="true" title="' +
|
|
||||||
sendDateMessage +
|
|
||||||
'">' +
|
|
||||||
status +
|
|
||||||
"</span>";
|
|
||||||
}
|
|
||||||
return statusColumn;
|
|
||||||
}
|
|
||||||
function poll() {
|
|
||||||
api.campaignId.results(campaign.id).success(function (c) {
|
|
||||||
campaign = c;
|
|
||||||
var timeline_series_data = [];
|
|
||||||
$.each(campaign.timeline, function (i, event) {
|
|
||||||
var event_date = moment.utc(event.time).local();
|
|
||||||
timeline_series_data.push({
|
|
||||||
email: event.email,
|
|
||||||
message: event.message,
|
|
||||||
x: event_date.valueOf(),
|
|
||||||
y: 1,
|
|
||||||
marker: { fillColor: statuses[event.message].color },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var timeline_chart = $("#timeline_chart").highcharts();
|
|
||||||
timeline_chart.series[0].update({ data: timeline_series_data });
|
|
||||||
var email_series_data = {};
|
|
||||||
Object.keys(statusMapping).forEach(function (k) {
|
|
||||||
email_series_data[k] = 0;
|
|
||||||
});
|
|
||||||
$.each(campaign.results, function (i, result) {
|
|
||||||
email_series_data[result.status]++;
|
|
||||||
if (result.reported) {
|
|
||||||
email_series_data["Email Reported"]++;
|
|
||||||
}
|
|
||||||
var step = progressListing.indexOf(result.status);
|
|
||||||
for (var i = 0; i < step; i++) {
|
|
||||||
email_series_data[progressListing[i]]++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$.each(email_series_data, function (status, count) {
|
|
||||||
var email_data = [];
|
|
||||||
if (!(status in statusMapping)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
email_data.push({
|
|
||||||
name: status,
|
|
||||||
y: Math.floor((count / campaign.results.length) * 100),
|
|
||||||
count: count,
|
|
||||||
});
|
|
||||||
email_data.push({
|
|
||||||
name: "",
|
|
||||||
y: 100 - Math.floor((count / campaign.results.length) * 100),
|
|
||||||
});
|
|
||||||
var chart = $("#" + statusMapping[status] + "_chart").highcharts();
|
|
||||||
chart.series[0].update({ data: email_data });
|
|
||||||
});
|
|
||||||
resultsTable = $("#resultsTable").DataTable();
|
|
||||||
resultsTable.rows().every(function (i, tableLoop, rowLoop) {
|
|
||||||
var row = this.row(i);
|
|
||||||
var rowData = row.data();
|
|
||||||
var rid = rowData[0];
|
|
||||||
$.each(campaign.results, function (j, result) {
|
|
||||||
if (result.id == rid) {
|
|
||||||
rowData[8] = moment(result.send_date).format(
|
|
||||||
"MMMM Do YYYY, h:mm:ss a"
|
|
||||||
);
|
|
||||||
rowData[7] = result.reported;
|
|
||||||
rowData[6] = result.status;
|
|
||||||
resultsTable.row(i).data(rowData);
|
|
||||||
if (row.child.isShown()) {
|
|
||||||
$(row.node()).find("#caret").removeClass("fa-caret-right");
|
|
||||||
$(row.node()).find("#caret").addClass("fa-caret-down");
|
|
||||||
row.child(renderTimeline(row.data()));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
resultsTable.draw(false);
|
|
||||||
updateMap(campaign.results);
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
$("#refresh_message").hide();
|
|
||||||
$("#refresh_btn").show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function load() {
|
|
||||||
campaign.id = window.location.pathname.split("/").slice(-1)[0];
|
|
||||||
var use_map = JSON.parse(localStorage.getItem("gophish.use_map"));
|
|
||||||
api.campaignId
|
|
||||||
.results(campaign.id)
|
|
||||||
.success(function (c) {
|
|
||||||
campaign = c;
|
|
||||||
if (campaign) {
|
|
||||||
$("title").text(c.name + " - Gophish");
|
|
||||||
$("#loading").hide();
|
|
||||||
$("#campaignResults").show();
|
|
||||||
$("#page-title").text("Results for " + c.name);
|
|
||||||
if (c.status == "Completed") {
|
|
||||||
$("#complete_button")[0].disabled = true;
|
|
||||||
$("#complete_button").text("Completed!");
|
|
||||||
doPoll = false;
|
|
||||||
}
|
|
||||||
$("#resultsTable").on("click", ".timeline-event-details", function () {
|
|
||||||
payloadResults = $(this).parent().find(".timeline-event-results");
|
|
||||||
if (payloadResults.is(":visible")) {
|
|
||||||
$(this).find("i").removeClass("fa-caret-down");
|
|
||||||
$(this).find("i").addClass("fa-caret-right");
|
|
||||||
payloadResults.hide();
|
|
||||||
} else {
|
|
||||||
$(this).find("i").removeClass("fa-caret-right");
|
|
||||||
$(this).find("i").addClass("fa-caret-down");
|
|
||||||
payloadResults.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
resultsTable = $("#resultsTable").DataTable({
|
|
||||||
destroy: true,
|
|
||||||
order: [[2, "asc"]],
|
|
||||||
columnDefs: [
|
|
||||||
{ orderable: false, targets: "no-sort" },
|
|
||||||
{ className: "details-control", targets: [1] },
|
|
||||||
{ visible: false, targets: [0, 8] },
|
|
||||||
{
|
|
||||||
render: function (data, type, row) {
|
|
||||||
return createStatusLabel(data, row[8]);
|
|
||||||
},
|
|
||||||
targets: [6],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: "text-center",
|
|
||||||
render: function (reported, type, row) {
|
|
||||||
if (type == "display") {
|
|
||||||
if (reported) {
|
|
||||||
return "<i class='fa fa-check-circle text-center text-success'></i>";
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
"<i role='button' class='fa fa-times-circle text-center text-muted' onclick='report_mail(\"" +
|
|
||||||
row[0] +
|
|
||||||
'", "' +
|
|
||||||
campaign.id +
|
|
||||||
"\");'></i>"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return reported;
|
|
||||||
},
|
|
||||||
targets: [7],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
resultsTable.clear();
|
|
||||||
var email_series_data = {};
|
|
||||||
var timeline_series_data = [];
|
|
||||||
Object.keys(statusMapping).forEach(function (k) {
|
|
||||||
email_series_data[k] = 0;
|
|
||||||
});
|
|
||||||
$.each(campaign.results, function (i, result) {
|
|
||||||
resultsTable.row.add([
|
|
||||||
result.id,
|
|
||||||
'<i id="caret" class="fa fa-caret-right"></i>',
|
|
||||||
escapeHtml(result.first_name) || "",
|
|
||||||
escapeHtml(result.last_name) || "",
|
|
||||||
escapeHtml(result.email) || "",
|
|
||||||
escapeHtml(result.position) || "",
|
|
||||||
result.status,
|
|
||||||
result.reported,
|
|
||||||
moment(result.send_date).format("MMMM Do YYYY, h:mm:ss a"),
|
|
||||||
]);
|
|
||||||
email_series_data[result.status]++;
|
|
||||||
if (result.reported) {
|
|
||||||
email_series_data["Email Reported"]++;
|
|
||||||
}
|
|
||||||
var step = progressListing.indexOf(result.status);
|
|
||||||
for (var i = 0; i < step; i++) {
|
|
||||||
email_series_data[progressListing[i]]++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
resultsTable.draw();
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
$("#resultsTable tbody").on("click", "td.details-control", function () {
|
|
||||||
var tr = $(this).closest("tr");
|
|
||||||
var row = resultsTable.row(tr);
|
|
||||||
if (row.child.isShown()) {
|
|
||||||
row.child.hide();
|
|
||||||
tr.removeClass("shown");
|
|
||||||
$(this).find("i").removeClass("fa-caret-down");
|
|
||||||
$(this).find("i").addClass("fa-caret-right");
|
|
||||||
} else {
|
|
||||||
$(this).find("i").removeClass("fa-caret-right");
|
|
||||||
$(this).find("i").addClass("fa-caret-down");
|
|
||||||
row.child(renderTimeline(row.data())).show();
|
|
||||||
tr.addClass("shown");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$.each(campaign.timeline, function (i, event) {
|
|
||||||
if (event.message == "Campaign Created") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
var event_date = moment.utc(event.time).local();
|
|
||||||
timeline_series_data.push({
|
|
||||||
email: event.email,
|
|
||||||
message: event.message,
|
|
||||||
x: event_date.valueOf(),
|
|
||||||
y: 1,
|
|
||||||
marker: { fillColor: statuses[event.message].color },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
renderTimelineChart({ data: timeline_series_data });
|
|
||||||
$.each(email_series_data, function (status, count) {
|
|
||||||
var email_data = [];
|
|
||||||
if (!(status in statusMapping)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
email_data.push({
|
|
||||||
name: status,
|
|
||||||
y: Math.floor((count / campaign.results.length) * 100),
|
|
||||||
count: count,
|
|
||||||
});
|
|
||||||
email_data.push({
|
|
||||||
name: "",
|
|
||||||
y: 100 - Math.floor((count / campaign.results.length) * 100),
|
|
||||||
});
|
|
||||||
var chart = renderPieChart({
|
|
||||||
elemId: statusMapping[status] + "_chart",
|
|
||||||
title: status,
|
|
||||||
name: status,
|
|
||||||
data: email_data,
|
|
||||||
colors: [statuses[status].color, "#dddddd"],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (use_map) {
|
|
||||||
$("#resultsMapContainer").show();
|
|
||||||
map = new Datamap({
|
|
||||||
element: document.getElementById("resultsMap"),
|
|
||||||
responsive: true,
|
|
||||||
fills: { defaultFill: "#ffffff", point: "#283F50" },
|
|
||||||
geographyConfig: {
|
|
||||||
highlightFillColor: "#1abc9c",
|
|
||||||
borderColor: "#283F50",
|
|
||||||
},
|
|
||||||
bubblesConfig: { borderColor: "#283F50" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
updateMap(campaign.results);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.error(function () {
|
|
||||||
$("#loading").hide();
|
|
||||||
errorFlash(" Campaign not found!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var setRefresh;
|
|
||||||
function refresh() {
|
|
||||||
if (!doPoll) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$("#refresh_message").show();
|
|
||||||
$("#refresh_btn").hide();
|
|
||||||
poll();
|
|
||||||
clearTimeout(setRefresh);
|
|
||||||
setRefresh = setTimeout(refresh, 6e4);
|
|
||||||
}
|
|
||||||
function report_mail(rid, cid) {
|
|
||||||
Swal.fire({
|
|
||||||
title: "Are you sure?",
|
|
||||||
text: "This result will be flagged as reported (RID: " + rid + ")",
|
|
||||||
type: "question",
|
|
||||||
animation: false,
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: "Continue",
|
|
||||||
confirmButtonColor: "#428bca",
|
|
||||||
reverseButtons: true,
|
|
||||||
allowOutsideClick: false,
|
|
||||||
showLoaderOnConfirm: true,
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.value) {
|
|
||||||
api.campaignId.get(cid).success(function (c) {
|
|
||||||
report_url = new URL(c.url);
|
|
||||||
report_url.pathname = "/report";
|
|
||||||
report_url.search = "?rid=" + rid;
|
|
||||||
fetch(report_url)
|
|
||||||
.then((response) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
||||||
}
|
|
||||||
refresh();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
let errorMessage = error.message;
|
|
||||||
if (error.message === "Failed to fetch") {
|
|
||||||
errorMessage =
|
|
||||||
"This might be due to Mixed Content issues or network problems.";
|
|
||||||
}
|
|
||||||
Swal.fire({
|
|
||||||
title: "Error",
|
|
||||||
text: errorMessage,
|
|
||||||
type: "error",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$(document).ready(function () {
|
|
||||||
Highcharts.setOptions({ global: { useUTC: false } });
|
|
||||||
load();
|
|
||||||
setRefresh = setTimeout(refresh, 6e4);
|
|
||||||
});
|
|
Loading…
Reference in New Issue