github.com/Ne0nd0g/gophish@v0.7.1-0.20190220040016-11493024a07d/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({ 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 () { 75 swal( 76 'Landing Page Deleted!', 77 'This landing page has been deleted!', 78 'success' 79 ); 80 $('button:contains("OK")').on('click', function () { 81 location.reload() 82 }) 83 }) 84 } 85 86 function importSite() { 87 url = $("#url").val() 88 if (!url) { 89 modalError("No URL Specified!") 90 } else { 91 api.clone_site({ 92 url: url, 93 include_resources: false 94 }) 95 .success(function (data) { 96 $("#html_editor").val(data.html) 97 CKEDITOR.instances["html_editor"].setMode('wysiwyg') 98 $("#importSiteModal").modal("hide") 99 }) 100 .error(function (data) { 101 modalError(data.responseJSON.message) 102 }) 103 } 104 } 105 106 function edit(idx) { 107 $("#modalSubmit").unbind('click').click(function () { 108 save(idx) 109 }) 110 $("#html_editor").ckeditor() 111 setupAutocomplete(CKEDITOR.instances["html_editor"]) 112 var page = {} 113 if (idx != -1) { 114 page = pages[idx] 115 $("#name").val(page.name) 116 $("#html_editor").val(page.html) 117 $("#capture_credentials_checkbox").prop("checked", page.capture_credentials) 118 $("#capture_passwords_checkbox").prop("checked", page.capture_passwords) 119 $("#redirect_url_input").val(page.redirect_url) 120 if (page.capture_credentials) { 121 $("#capture_passwords").show() 122 $("#redirect_url").show() 123 } 124 } 125 } 126 127 function copy(idx) { 128 $("#modalSubmit").unbind('click').click(function () { 129 save(-1) 130 }) 131 $("#html_editor").ckeditor() 132 var page = pages[idx] 133 $("#name").val("Copy of " + page.name) 134 $("#html_editor").val(page.html) 135 } 136 137 function load() { 138 /* 139 load() - Loads the current pages using the API 140 */ 141 $("#pagesTable").hide() 142 $("#emptyMessage").hide() 143 $("#loading").show() 144 api.pages.get() 145 .success(function (ps) { 146 pages = ps 147 $("#loading").hide() 148 if (pages.length > 0) { 149 $("#pagesTable").show() 150 pagesTable = $("#pagesTable").DataTable({ 151 destroy: true, 152 columnDefs: [{ 153 orderable: false, 154 targets: "no-sort" 155 }] 156 }); 157 pagesTable.clear() 158 $.each(pages, function (i, page) { 159 pagesTable.row.add([ 160 escapeHtml(page.name), 161 moment(page.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 162 "<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 + ")'>\ 163 <i class='fa fa-pencil'></i>\ 164 </button></span>\ 165 <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Page' onclick='copy(" + i + ")'>\ 166 <i class='fa fa-copy'></i>\ 167 </button></span>\ 168 <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Page' onclick='deletePage(" + i + ")'>\ 169 <i class='fa fa-trash-o'></i>\ 170 </button></div>" 171 ]).draw() 172 }) 173 $('[data-toggle="tooltip"]').tooltip() 174 } else { 175 $("#emptyMessage").show() 176 } 177 }) 178 .error(function () { 179 $("#loading").hide() 180 errorFlash("Error fetching pages") 181 }) 182 } 183 184 $(document).ready(function () { 185 // Setup multiple modals 186 // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html 187 $('.modal').on('hidden.bs.modal', function (event) { 188 $(this).removeClass('fv-modal-stack'); 189 $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1); 190 }); 191 $('.modal').on('shown.bs.modal', function (event) { 192 // Keep track of the number of open modals 193 if (typeof ($('body').data('fv_open_modals')) == 'undefined') { 194 $('body').data('fv_open_modals', 0); 195 } 196 // if the z-index of this modal has been set, ignore. 197 if ($(this).hasClass('fv-modal-stack')) { 198 return; 199 } 200 $(this).addClass('fv-modal-stack'); 201 // Increment the number of open modals 202 $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1); 203 // Setup the appropriate z-index 204 $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals'))); 205 $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals'))); 206 $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 207 }); 208 $.fn.modal.Constructor.prototype.enforceFocus = function () { 209 $(document) 210 .off('focusin.bs.modal') // guard against infinite focus loop 211 .on('focusin.bs.modal', $.proxy(function (e) { 212 if ( 213 this.$element[0] !== e.target && !this.$element.has(e.target).length 214 // CKEditor compatibility fix start. 215 && 216 !$(e.target).closest('.cke_dialog, .cke').length 217 // CKEditor compatibility fix end. 218 ) { 219 this.$element.trigger('focus'); 220 } 221 }, this)); 222 }; 223 // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay 224 $(document).on('hidden.bs.modal', '.modal', function () { 225 $('.modal:visible').length && $(document.body).addClass('modal-open'); 226 }); 227 $('#modal').on('hidden.bs.modal', function (event) { 228 dismiss() 229 }); 230 $("#capture_credentials_checkbox").change(function () { 231 $("#capture_passwords").toggle() 232 $("#redirect_url").toggle() 233 }) 234 CKEDITOR.on('dialogDefinition', function (ev) { 235 // Take the dialog name and its definition from the event data. 236 var dialogName = ev.data.name; 237 var dialogDefinition = ev.data.definition; 238 239 // Check if the definition is from the dialog window you are interested in (the "Link" dialog window). 240 if (dialogName == 'link') { 241 dialogDefinition.minWidth = 500 242 dialogDefinition.minHeight = 100 243 244 // Remove the linkType field 245 var infoTab = dialogDefinition.getContents('info'); 246 infoTab.get('linkType').hidden = true; 247 } 248 }); 249 250 load() 251 })