var map = null var doPoll = true; // statuses is a helper map to point result statuses to ui classes 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" }, //not a status, but is used for the campaign timeline and user timeline "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", } // This is an underwhelming attempt at an enum // until I have time to refactor this appropriately. 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() } // Deletes a campaign after prompting the user 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' }) }) } // Completes a campaign after prompting the user 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 exportAsCleanCSV(scope) { var csvScope = null; var filename = campaign.name + ' - ' + capitalize(scope) + '.csv'; switch (scope) { case "results": csvScope = campaign.results; break; case "events": csvScope = campaign.timeline; break; case "cleanresults": csvScope = campaign.cleanResults; // Replace with your clean results data break; } if (!csvScope) { return; } // Create an array to hold the CSV data var csvData = []; // Add the CSV header var header = ['Email', 'Email Opened', 'Clicked Link', 'Submitted Data']; csvData.push(header); // Define a helper function to convert boolean to string function boolToString(value) { return value ? 'true' : 'false'; } // Add CSV rows for each entry in csvScope csvScope.forEach(function (entry) { var email = entry.email; var status = entry.status; // Initialize status flags var emailOpened = false; var clickedLink = false; var submittedData = false; // Update status flags based on the status value switch (status) { case 'Email Opened': emailOpened = true; break; case 'Clicked Link': emailOpened = true; // If clicked link, email is also opened clickedLink = true; break; case 'Submitted Data': emailOpened = true; // If submitted data, email is also opened clickedLink = true; // If submitted data, link is also clicked submittedData = true; break; } // Add the CSV row var csvRow = [email, boolToString(emailOpened), boolToString(clickedLink), boolToString(submittedData)]; csvData.push(csvRow); }); // Convert the CSV data array to a CSV string var csvString = csvData.map(function (row) { return row.join(','); }).join('\n'); // Create a Blob with the CSV string var csvBlob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' }); // Create a download link var csvURL = window.URL.createObjectURL(csvBlob); var dlLink = document.createElement('a'); dlLink.href = csvURL; dlLink.setAttribute('download', filename); // Trigger the download dlLink.click(); // Clean up window.URL.revokeObjectURL(csvURL); } // Example usage: // exportAsCSV('results'); // exportAsCSV('events'); // exportAsCSV('cleanresults'); // Add this line to export clean results // Exports campaign results as a CSV file 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(''); 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 = $('