github.com/topsteplocal/gophish@v0.6.0/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 api.import_email({ 244 content: raw, 245 convert_links: convert_links 246 }) 247 .success(function (data) { 248 $("#text_editor").val(data.text) 249 $("#html_editor").val(data.html) 250 $("#subject").val(data.subject) 251 $("#importEmailModal").modal("hide") 252 }) 253 .error(function (data) { 254 modalError(data.responseJSON.message) 255 }) 256 } 257 } 258 259 function load() { 260 $("#templateTable").hide() 261 $("#emptyMessage").hide() 262 $("#loading").show() 263 api.templates.get() 264 .success(function (ts) { 265 templates = ts 266 $("#loading").hide() 267 if (templates.length > 0) { 268 $("#templateTable").show() 269 templateTable = $("#templateTable").DataTable({ 270 destroy: true, 271 columnDefs: [{ 272 orderable: false, 273 targets: "no-sort" 274 }] 275 }); 276 templateTable.clear() 277 $.each(templates, function (i, template) { 278 templateTable.row.add([ 279 escapeHtml(template.name), 280 moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 281 "<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 + ")'>\ 282 <i class='fa fa-pencil'></i>\ 283 </button></span>\ 284 <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Template' onclick='copy(" + i + ")'>\ 285 <i class='fa fa-copy'></i>\ 286 </button></span>\ 287 <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Template' onclick='deleteTemplate(" + i + ")'>\ 288 <i class='fa fa-trash-o'></i>\ 289 </button></div>" 290 ]).draw() 291 }) 292 $('[data-toggle="tooltip"]').tooltip() 293 } else { 294 $("#emptyMessage").show() 295 } 296 }) 297 .error(function () { 298 $("#loading").hide() 299 errorFlash("Error fetching templates") 300 }) 301 } 302 303 $(document).ready(function () { 304 // Setup multiple modals 305 // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html 306 $('.modal').on('hidden.bs.modal', function (event) { 307 $(this).removeClass('fv-modal-stack'); 308 $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1); 309 }); 310 $('.modal').on('shown.bs.modal', function (event) { 311 // Keep track of the number of open modals 312 if (typeof ($('body').data('fv_open_modals')) == 'undefined') { 313 $('body').data('fv_open_modals', 0); 314 } 315 // if the z-index of this modal has been set, ignore. 316 if ($(this).hasClass('fv-modal-stack')) { 317 return; 318 } 319 $(this).addClass('fv-modal-stack'); 320 // Increment the number of open modals 321 $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1); 322 // Setup the appropriate z-index 323 $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals'))); 324 $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals'))); 325 $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 326 }); 327 $.fn.modal.Constructor.prototype.enforceFocus = function () { 328 $(document) 329 .off('focusin.bs.modal') // guard against infinite focus loop 330 .on('focusin.bs.modal', $.proxy(function (e) { 331 if ( 332 this.$element[0] !== e.target && !this.$element.has(e.target).length 333 // CKEditor compatibility fix start. 334 && 335 !$(e.target).closest('.cke_dialog, .cke').length 336 // CKEditor compatibility fix end. 337 ) { 338 this.$element.trigger('focus'); 339 } 340 }, this)); 341 }; 342 // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay 343 $(document).on('hidden.bs.modal', '.modal', function () { 344 $('.modal:visible').length && $(document.body).addClass('modal-open'); 345 }); 346 $('#modal').on('hidden.bs.modal', function (event) { 347 dismiss() 348 }); 349 $("#importEmailModal").on('hidden.bs.modal', function (event) { 350 $("#email_content").val("") 351 }) 352 load() 353 354 })