github.com/lunarobliq/gophish@v0.8.1-0.20230523153303-93511002234d/static/js/src/app/landing_pages.js (about) 1 /* 2 landing_pages.js 3 Handles the creation, editing, and deletion of landing pages 4 Author: Jordan Wright <github.com/jordan-wright> 5 */ 6 var pages = [] 7 8 9 // Save attempts to POST to /templates/ 10 function save(idx) { 11 var page = {} 12 page.name = $("#name").val() 13 editor = CKEDITOR.instances["html_editor"] 14 page.html = editor.getData() 15 page.capture_credentials = $("#capture_credentials_checkbox").prop("checked") 16 page.capture_passwords = $("#capture_passwords_checkbox").prop("checked") 17 page.redirect_url = $("#redirect_url_input").val() 18 if (idx != -1) { 19 page.id = pages[idx].id 20 api.pageId.put(page) 21 .success(function (data) { 22 successFlash("Page edited successfully!") 23 load() 24 dismiss() 25 }) 26 } else { 27 // Submit the page 28 api.pages.post(page) 29 .success(function (data) { 30 successFlash("Page added successfully!") 31 load() 32 dismiss() 33 }) 34 .error(function (data) { 35 modalError(data.responseJSON.message) 36 }) 37 } 38 } 39 40 function dismiss() { 41 $("#modal\\.flashes").empty() 42 $("#name").val("") 43 $("#html_editor").val("") 44 $("#url").val("") 45 $("#redirect_url_input").val("") 46 $("#modal").find("input[type='checkbox']").prop("checked", false) 47 $("#capture_passwords").hide() 48 $("#redirect_url").hide() 49 $("#modal").modal('hide') 50 } 51 52 var deletePage = function (idx) { 53 Swal.fire({ 54 title: "Are you sure?", 55 text: "This will delete the landing page. This can't be undone!", 56 type: "warning", 57 animation: false, 58 showCancelButton: true, 59 confirmButtonText: "Delete " + escapeHtml(pages[idx].name), 60 confirmButtonColor: "#428bca", 61 reverseButtons: true, 62 allowOutsideClick: false, 63 preConfirm: function () { 64 return new Promise(function (resolve, reject) { 65 api.pageId.delete(pages[idx].id) 66 .success(function (msg) { 67 resolve() 68 }) 69 .error(function (data) { 70 reject(data.responseJSON.message) 71 }) 72 }) 73 } 74 }).then(function (result) { 75 if (result.value){ 76 Swal.fire( 77 'Landing Page Deleted!', 78 'This landing page has been deleted!', 79 'success' 80 ); 81 } 82 $('button:contains("OK")').on('click', function () { 83 location.reload() 84 }) 85 }) 86 } 87 88 function importSite() { 89 url = $("#url").val() 90 if (!url) { 91 modalError("No URL Specified!") 92 } else { 93 api.clone_site({ 94 url: url, 95 include_resources: false 96 }) 97 .success(function (data) { 98 $("#html_editor").val(data.html) 99 CKEDITOR.instances["html_editor"].setMode('wysiwyg') 100 $("#importSiteModal").modal("hide") 101 }) 102 .error(function (data) { 103 modalError(data.responseJSON.message) 104 }) 105 } 106 } 107 108 function edit(idx) { 109 $("#modalSubmit").unbind('click').click(function () { 110 save(idx) 111 }) 112 $("#html_editor").ckeditor() 113 setupAutocomplete(CKEDITOR.instances["html_editor"]) 114 var page = {} 115 if (idx != -1) { 116 $("#modalLabel").text("Edit Landing Page") 117 page = pages[idx] 118 $("#name").val(page.name) 119 $("#html_editor").val(page.html) 120 $("#capture_credentials_checkbox").prop("checked", page.capture_credentials) 121 $("#capture_passwords_checkbox").prop("checked", page.capture_passwords) 122 $("#redirect_url_input").val(page.redirect_url) 123 if (page.capture_credentials) { 124 $("#capture_passwords").show() 125 $("#redirect_url").show() 126 } 127 } else { 128 $("#modalLabel").text("New Landing Page") 129 } 130 } 131 132 function copy(idx) { 133 $("#modalSubmit").unbind('click').click(function () { 134 save(-1) 135 }) 136 $("#html_editor").ckeditor() 137 var page = pages[idx] 138 $("#name").val("Copy of " + page.name) 139 $("#html_editor").val(page.html) 140 } 141 142 function load() { 143 /* 144 load() - Loads the current pages using the API 145 */ 146 $("#pagesTable").hide() 147 $("#emptyMessage").hide() 148 $("#loading").show() 149 api.pages.get() 150 .success(function (ps) { 151 pages = ps 152 $("#loading").hide() 153 if (pages.length > 0) { 154 $("#pagesTable").show() 155 pagesTable = $("#pagesTable").DataTable({ 156 destroy: true, 157 columnDefs: [{ 158 orderable: false, 159 targets: "no-sort" 160 }] 161 }); 162 pagesTable.clear() 163 pageRows = [] 164 $.each(pages, function (i, page) { 165 pageRows.push([ 166 escapeHtml(page.name), 167 moment(page.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 168 "<div class='pull-right'><span data-toggle='modal' data-backdrop='static' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Page' onclick='edit(" + i + ")'>\ 169 <i class='fa fa-pencil'></i>\ 170 </button></span>\ 171 <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Page' onclick='copy(" + i + ")'>\ 172 <i class='fa fa-copy'></i>\ 173 </button></span>\ 174 <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Page' onclick='deletePage(" + i + ")'>\ 175 <i class='fa fa-trash-o'></i>\ 176 </button></div>" 177 ]) 178 }) 179 pagesTable.rows.add(pageRows).draw() 180 $('[data-toggle="tooltip"]').tooltip() 181 } else { 182 $("#emptyMessage").show() 183 } 184 }) 185 .error(function () { 186 $("#loading").hide() 187 errorFlash("Error fetching pages") 188 }) 189 } 190 191 $(document).ready(function () { 192 // Setup multiple modals 193 // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html 194 $('.modal').on('hidden.bs.modal', function (event) { 195 $(this).removeClass('fv-modal-stack'); 196 $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1); 197 }); 198 $('.modal').on('shown.bs.modal', function (event) { 199 // Keep track of the number of open modals 200 if (typeof ($('body').data('fv_open_modals')) == 'undefined') { 201 $('body').data('fv_open_modals', 0); 202 } 203 // if the z-index of this modal has been set, ignore. 204 if ($(this).hasClass('fv-modal-stack')) { 205 return; 206 } 207 $(this).addClass('fv-modal-stack'); 208 // Increment the number of open modals 209 $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1); 210 // Setup the appropriate z-index 211 $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals'))); 212 $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals'))); 213 $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 214 }); 215 $.fn.modal.Constructor.prototype.enforceFocus = function () { 216 $(document) 217 .off('focusin.bs.modal') // guard against infinite focus loop 218 .on('focusin.bs.modal', $.proxy(function (e) { 219 if ( 220 this.$element[0] !== e.target && !this.$element.has(e.target).length 221 // CKEditor compatibility fix start. 222 && 223 !$(e.target).closest('.cke_dialog, .cke').length 224 // CKEditor compatibility fix end. 225 ) { 226 this.$element.trigger('focus'); 227 } 228 }, this)); 229 }; 230 // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay 231 $(document).on('hidden.bs.modal', '.modal', function () { 232 $('.modal:visible').length && $(document.body).addClass('modal-open'); 233 }); 234 $('#modal').on('hidden.bs.modal', function (event) { 235 dismiss() 236 }); 237 $("#capture_credentials_checkbox").change(function () { 238 $("#capture_passwords").toggle() 239 $("#redirect_url").toggle() 240 }) 241 CKEDITOR.on('dialogDefinition', function (ev) { 242 // Take the dialog name and its definition from the event data. 243 var dialogName = ev.data.name; 244 var dialogDefinition = ev.data.definition; 245 246 // Check if the definition is from the dialog window you are interested in (the "Link" dialog window). 247 if (dialogName == 'link') { 248 dialogDefinition.minWidth = 500 249 dialogDefinition.minHeight = 100 250 251 // Remove the linkType field 252 var infoTab = dialogDefinition.getContents('info'); 253 infoTab.get('linkType').hidden = true; 254 } 255 }); 256 257 load() 258 })