github.com/jonathaningram/gophish@v0.3.1-0.20170829042651-ac3fe6aeae6c/static/js/src/app/templates.js (about) 1 var templates = [] 2 var icons = { 3 "application/vnd.ms-excel": "fa-file-excel-o", 4 "text/plain": "fa-file-text-o", 5 "image/gif": "fa-file-image-o", 6 "image/png": "fa-file-image-o", 7 "application/pdf": "fa-file-pdf-o", 8 "application/x-zip-compressed": "fa-file-archive-o", 9 "application/x-gzip": "fa-file-archive-o", 10 "application/vnd.openxmlformats-officedocument.presentationml.presentation": "fa-file-powerpoint-o", 11 "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "fa-file-word-o", 12 "application/octet-stream": "fa-file-o", 13 "application/x-msdownload": "fa-file-o" 14 } 15 16 // Save attempts to POST to /templates/ 17 function save(idx) { 18 var template = { 19 attachments: [] 20 } 21 template.name = $("#name").val() 22 template.subject = $("#subject").val() 23 template.html = CKEDITOR.instances["html_editor"].getData(); 24 // Fix the URL Scheme added by CKEditor (until we can remove it from the plugin) 25 template.html = template.html.replace(/https?:\/\/{{\.URL}}/gi, "{{.URL}}") 26 // If the "Add Tracker Image" checkbox is checked, add the tracker 27 if ($("#use_tracker_checkbox").prop("checked")) { 28 if (template.html.indexOf("{{.Tracker}}") == -1 && 29 template.html.indexOf("{{.TrackingUrl}}") == -1) { 30 template.html = template.html.replace("</body>", "{{.Tracker}}</body>") 31 } 32 } else { 33 // Otherwise, remove the tracker 34 template.html = template.html.replace("{{.Tracker}}</body>", "</body>") 35 } 36 template.text = $("#text_editor").val() 37 // Add the attachments 38 $.each($("#attachmentsTable").DataTable().rows().data(), function (i, target) { 39 template.attachments.push({ 40 name: unescapeHtml(target[1]), 41 content: target[3], 42 type: target[4], 43 }) 44 }) 45 46 if (idx != -1) { 47 template.id = templates[idx].id 48 api.templateId.put(template) 49 .success(function (data) { 50 successFlash("Template edited successfully!") 51 load() 52 dismiss() 53 }) 54 .error(function (data) { 55 modalError(data.responseJSON.message) 56 }) 57 } else { 58 // Submit the template 59 api.templates.post(template) 60 .success(function (data) { 61 successFlash("Template added successfully!") 62 load() 63 dismiss() 64 }) 65 .error(function (data) { 66 modalError(data.responseJSON.message) 67 }) 68 } 69 } 70 71 function dismiss() { 72 $("#modal\\.flashes").empty() 73 $("#attachmentsTable").dataTable().DataTable().clear().draw() 74 $("#name").val("") 75 $("#subject").val("") 76 $("#text_editor").val("") 77 $("#html_editor").val("") 78 $("#modal").modal('hide') 79 } 80 81 function deleteTemplate(idx) { 82 if (confirm("Delete " + templates[idx].name + "?")) { 83 api.templateId.delete(templates[idx].id) 84 .success(function (data) { 85 successFlash(data.message) 86 load() 87 }) 88 } 89 } 90 91 function attach(files) { 92 attachmentsTable = $("#attachmentsTable").DataTable({ 93 destroy: true, 94 "order": [ 95 [1, "asc"] 96 ], 97 columnDefs: [{ 98 orderable: false, 99 targets: "no-sort" 100 }, { 101 sClass: "datatable_hidden", 102 targets: [3, 4] 103 }] 104 }); 105 $.each(files, function (i, file) { 106 var reader = new FileReader(); 107 /* Make this a datatable */ 108 reader.onload = function (e) { 109 var icon = icons[file.type] || "fa-file-o" 110 // Add the record to the modal 111 attachmentsTable.row.add([ 112 '<i class="fa ' + icon + '"></i>', 113 escapeHtml(file.name), 114 '<span class="remove-row"><i class="fa fa-trash-o"></i></span>', 115 reader.result.split(",")[1], 116 file.type || "application/octet-stream" 117 ]).draw() 118 } 119 reader.onerror = function (e) { 120 console.log(e) 121 } 122 reader.readAsDataURL(file) 123 }) 124 } 125 126 function edit(idx) { 127 $("#modalSubmit").unbind('click').click(function () { 128 save(idx) 129 }) 130 $("#attachmentUpload").unbind('click').click(function () { 131 this.value = null 132 }) 133 $("#html_editor").ckeditor() 134 $("#attachmentsTable").show() 135 attachmentsTable = $('#attachmentsTable').DataTable({ 136 destroy: true, 137 "order": [ 138 [1, "asc"] 139 ], 140 columnDefs: [{ 141 orderable: false, 142 targets: "no-sort" 143 }, { 144 sClass: "datatable_hidden", 145 targets: [3, 4] 146 }] 147 }); 148 var template = { 149 attachments: [] 150 } 151 if (idx != -1) { 152 template = templates[idx] 153 $("#name").val(template.name) 154 $("#subject").val(template.subject) 155 $("#html_editor").val(template.html) 156 $("#text_editor").val(template.text) 157 $.each(template.attachments, function (i, file) { 158 var icon = icons[file.type] || "fa-file-o" 159 // Add the record to the modal 160 attachmentsTable.row.add([ 161 '<i class="fa ' + icon + '"></i>', 162 escapeHtml(file.name), 163 '<span class="remove-row"><i class="fa fa-trash-o"></i></span>', 164 file.content, 165 file.type || "application/octet-stream" 166 ]).draw() 167 }) 168 if (template.html.indexOf("{{.Tracker}}") != -1) { 169 $("#use_tracker_checkbox").prop("checked", true) 170 } else { 171 $("#use_tracker_checkbox").prop("checked", false) 172 } 173 174 } 175 // Handle Deletion 176 $("#attachmentsTable").unbind('click').on("click", "span>i.fa-trash-o", function () { 177 attachmentsTable.row($(this).parents('tr')) 178 .remove() 179 .draw(); 180 }) 181 } 182 183 function copy(idx) { 184 $("#modalSubmit").unbind('click').click(function () { 185 save(-1) 186 }) 187 $("#attachmentUpload").unbind('click').click(function () { 188 this.value = null 189 }) 190 $("#html_editor").ckeditor() 191 $("#attachmentsTable").show() 192 attachmentsTable = $('#attachmentsTable').DataTable({ 193 destroy: true, 194 "order": [ 195 [1, "asc"] 196 ], 197 columnDefs: [{ 198 orderable: false, 199 targets: "no-sort" 200 }, { 201 sClass: "datatable_hidden", 202 targets: [3, 4] 203 }] 204 }); 205 var template = { 206 attachments: [] 207 } 208 template = templates[idx] 209 $("#name").val("Copy of " + template.name) 210 $("#subject").val(template.subject) 211 $("#html_editor").val(template.html) 212 $("#text_editor").val(template.text) 213 $.each(template.attachments, function (i, file) { 214 var icon = icons[file.type] || "fa-file-o" 215 // Add the record to the modal 216 attachmentsTable.row.add([ 217 '<i class="fa ' + icon + '"></i>', 218 escapeHtml(file.name), 219 '<span class="remove-row"><i class="fa fa-trash-o"></i></span>', 220 file.content, 221 file.type || "application/octet-stream" 222 ]).draw() 223 }) 224 // Handle Deletion 225 $("#attachmentsTable").unbind('click').on("click", "span>i.fa-trash-o", function () { 226 attachmentsTable.row($(this).parents('tr')) 227 .remove() 228 .draw(); 229 }) 230 if (template.html.indexOf("{{.Tracker}}") != -1) { 231 $("#use_tracker_checkbox").prop("checked", true) 232 } else { 233 $("#use_tracker_checkbox").prop("checked", false) 234 } 235 } 236 237 function importEmail() { 238 raw = $("#email_content").val() 239 convert_links = $("#convert_links_checkbox").prop("checked") 240 if (!raw) { 241 modalError("No Content Specified!") 242 } else { 243 $.ajax({ 244 method: "POST", 245 url: "/api/import/email", 246 data: JSON.stringify({ 247 content: raw, 248 convert_links: convert_links 249 }), 250 dataType: "json", 251 contentType: "application/json" 252 }) 253 .success(function (data) { 254 $("#text_editor").val(data.text) 255 $("#html_editor").val(data.html) 256 $("#subject").val(data.subject) 257 $("#importEmailModal").modal("hide") 258 }) 259 .error(function (data) { 260 modalError(data.responseJSON.message) 261 }) 262 } 263 } 264 265 function load() { 266 $("#templateTable").hide() 267 $("#emptyMessage").hide() 268 $("#loading").show() 269 api.templates.get() 270 .success(function (ts) { 271 templates = ts 272 $("#loading").hide() 273 if (templates.length > 0) { 274 $("#templateTable").show() 275 templateTable = $("#templateTable").DataTable({ 276 destroy: true, 277 columnDefs: [{ 278 orderable: false, 279 targets: "no-sort" 280 }] 281 }); 282 templateTable.clear() 283 $.each(templates, function (i, template) { 284 templateTable.row.add([ 285 escapeHtml(template.name), 286 moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 287 "<div class='pull-right'><span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Template' onclick='edit(" + i + ")'>\ 288 <i class='fa fa-pencil'></i>\ 289 </button></span>\ 290 <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Template' onclick='copy(" + i + ")'>\ 291 <i class='fa fa-copy'></i>\ 292 </button></span>\ 293 <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Template' onclick='deleteTemplate(" + i + ")'>\ 294 <i class='fa fa-trash-o'></i>\ 295 </button></div>" 296 ]).draw() 297 }) 298 $('[data-toggle="tooltip"]').tooltip() 299 } else { 300 $("#emptyMessage").show() 301 } 302 }) 303 .error(function () { 304 $("#loading").hide() 305 errorFlash("Error fetching templates") 306 }) 307 } 308 309 $(document).ready(function () { 310 // Setup multiple modals 311 // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html 312 $('.modal').on('hidden.bs.modal', function (event) { 313 $(this).removeClass('fv-modal-stack'); 314 $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1); 315 }); 316 $('.modal').on('shown.bs.modal', function (event) { 317 // Keep track of the number of open modals 318 if (typeof ($('body').data('fv_open_modals')) == 'undefined') { 319 $('body').data('fv_open_modals', 0); 320 } 321 // if the z-index of this modal has been set, ignore. 322 if ($(this).hasClass('fv-modal-stack')) { 323 return; 324 } 325 $(this).addClass('fv-modal-stack'); 326 // Increment the number of open modals 327 $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1); 328 // Setup the appropriate z-index 329 $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals'))); 330 $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals'))); 331 $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 332 }); 333 $.fn.modal.Constructor.prototype.enforceFocus = function () { 334 $(document) 335 .off('focusin.bs.modal') // guard against infinite focus loop 336 .on('focusin.bs.modal', $.proxy(function (e) { 337 if ( 338 this.$element[0] !== e.target && !this.$element.has(e.target).length 339 // CKEditor compatibility fix start. 340 && !$(e.target).closest('.cke_dialog, .cke').length 341 // CKEditor compatibility fix end. 342 ) { 343 this.$element.trigger('focus'); 344 } 345 }, this)); 346 }; 347 $('#modal').on('hidden.bs.modal', function (event) { 348 dismiss() 349 }); 350 $("#importEmailModal").on('hidden.bs.modal', function (event) { 351 $("#email_content").val("") 352 }) 353 load() 354 355 })