github.com/merlinepedra/gophish1@v0.9.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  var deleteTemplate = function (idx) {
    82      Swal.fire({
    83          title: "Are you sure?",
    84          text: "This will delete the template. This can't be undone!",
    85          type: "warning",
    86          animation: false,
    87          showCancelButton: true,
    88          confirmButtonText: "Delete " + escapeHtml(templates[idx].name),
    89          confirmButtonColor: "#428bca",
    90          reverseButtons: true,
    91          allowOutsideClick: false,
    92          preConfirm: function () {
    93              return new Promise(function (resolve, reject) {
    94                  api.templateId.delete(templates[idx].id)
    95                      .success(function (msg) {
    96                          resolve()
    97                      })
    98                      .error(function (data) {
    99                          reject(data.responseJSON.message)
   100                      })
   101              })
   102          }
   103      }).then(function (result) {
   104          if(result.value) {
   105              Swal.fire(
   106                  'Template Deleted!',
   107                  'This template has been deleted!',
   108                  'success'
   109              );
   110          }
   111          $('button:contains("OK")').on('click', function () {
   112              location.reload()
   113          })
   114      })
   115  }
   116  
   117  function deleteTemplate(idx) {
   118      if (confirm("Delete " + templates[idx].name + "?")) {
   119          api.templateId.delete(templates[idx].id)
   120              .success(function (data) {
   121                  successFlash(data.message)
   122                  load()
   123              })
   124      }
   125  }
   126  
   127  function attach(files) {
   128      attachmentsTable = $("#attachmentsTable").DataTable({
   129          destroy: true,
   130          "order": [
   131              [1, "asc"]
   132          ],
   133          columnDefs: [{
   134              orderable: false,
   135              targets: "no-sort"
   136          }, {
   137              sClass: "datatable_hidden",
   138              targets: [3, 4]
   139          }]
   140      });
   141      $.each(files, function (i, file) {
   142          var reader = new FileReader();
   143          /* Make this a datatable */
   144          reader.onload = function (e) {
   145              var icon = icons[file.type] || "fa-file-o"
   146              // Add the record to the modal
   147              attachmentsTable.row.add([
   148                  '<i class="fa ' + icon + '"></i>',
   149                  escapeHtml(file.name),
   150                  '<span class="remove-row"><i class="fa fa-trash-o"></i></span>',
   151                  reader.result.split(",")[1],
   152                  file.type || "application/octet-stream"
   153              ]).draw()
   154          }
   155          reader.onerror = function (e) {
   156              console.log(e)
   157          }
   158          reader.readAsDataURL(file)
   159      })
   160  }
   161  
   162  function edit(idx) {
   163      $("#modalSubmit").unbind('click').click(function () {
   164          save(idx)
   165      })
   166      $("#attachmentUpload").unbind('click').click(function () {
   167          this.value = null
   168      })
   169      $("#html_editor").ckeditor()
   170      setupAutocomplete(CKEDITOR.instances["html_editor"])
   171      $("#attachmentsTable").show()
   172      attachmentsTable = $('#attachmentsTable').DataTable({
   173          destroy: true,
   174          "order": [
   175              [1, "asc"]
   176          ],
   177          columnDefs: [{
   178              orderable: false,
   179              targets: "no-sort"
   180          }, {
   181              sClass: "datatable_hidden",
   182              targets: [3, 4]
   183          }]
   184      });
   185      var template = {
   186          attachments: []
   187      }
   188      if (idx != -1) {
   189          template = templates[idx]
   190          $("#name").val(template.name)
   191          $("#subject").val(template.subject)
   192          $("#html_editor").val(template.html)
   193          $("#text_editor").val(template.text)
   194          $.each(template.attachments, function (i, file) {
   195              var icon = icons[file.type] || "fa-file-o"
   196              // Add the record to the modal
   197              attachmentsTable.row.add([
   198                  '<i class="fa ' + icon + '"></i>',
   199                  escapeHtml(file.name),
   200                  '<span class="remove-row"><i class="fa fa-trash-o"></i></span>',
   201                  file.content,
   202                  file.type || "application/octet-stream"
   203              ]).draw()
   204          })
   205          if (template.html.indexOf("{{.Tracker}}") != -1) {
   206              $("#use_tracker_checkbox").prop("checked", true)
   207          } else {
   208              $("#use_tracker_checkbox").prop("checked", false)
   209          }
   210  
   211      }
   212      // Handle Deletion
   213      $("#attachmentsTable").unbind('click').on("click", "span>i.fa-trash-o", function () {
   214          attachmentsTable.row($(this).parents('tr'))
   215              .remove()
   216              .draw();
   217      })
   218  }
   219  
   220  function copy(idx) {
   221      $("#modalSubmit").unbind('click').click(function () {
   222          save(-1)
   223      })
   224      $("#attachmentUpload").unbind('click').click(function () {
   225          this.value = null
   226      })
   227      $("#html_editor").ckeditor()
   228      $("#attachmentsTable").show()
   229      attachmentsTable = $('#attachmentsTable').DataTable({
   230          destroy: true,
   231          "order": [
   232              [1, "asc"]
   233          ],
   234          columnDefs: [{
   235              orderable: false,
   236              targets: "no-sort"
   237          }, {
   238              sClass: "datatable_hidden",
   239              targets: [3, 4]
   240          }]
   241      });
   242      var template = {
   243          attachments: []
   244      }
   245      template = templates[idx]
   246      $("#name").val("Copy of " + template.name)
   247      $("#subject").val(template.subject)
   248      $("#html_editor").val(template.html)
   249      $("#text_editor").val(template.text)
   250      $.each(template.attachments, function (i, file) {
   251          var icon = icons[file.type] || "fa-file-o"
   252          // Add the record to the modal
   253          attachmentsTable.row.add([
   254              '<i class="fa ' + icon + '"></i>',
   255              escapeHtml(file.name),
   256              '<span class="remove-row"><i class="fa fa-trash-o"></i></span>',
   257              file.content,
   258              file.type || "application/octet-stream"
   259          ]).draw()
   260      })
   261      // Handle Deletion
   262      $("#attachmentsTable").unbind('click').on("click", "span>i.fa-trash-o", function () {
   263          attachmentsTable.row($(this).parents('tr'))
   264              .remove()
   265              .draw();
   266      })
   267      if (template.html.indexOf("{{.Tracker}}") != -1) {
   268          $("#use_tracker_checkbox").prop("checked", true)
   269      } else {
   270          $("#use_tracker_checkbox").prop("checked", false)
   271      }
   272  }
   273  
   274  function importEmail() {
   275      raw = $("#email_content").val()
   276      convert_links = $("#convert_links_checkbox").prop("checked")
   277      if (!raw) {
   278          modalError("No Content Specified!")
   279      } else {
   280          api.import_email({
   281                  content: raw,
   282                  convert_links: convert_links
   283              })
   284              .success(function (data) {
   285                  $("#text_editor").val(data.text)
   286                  $("#html_editor").val(data.html)
   287                  $("#subject").val(data.subject)
   288                  // If the HTML is provided, let's open that view in the editor
   289                  if (data.html) {
   290                      CKEDITOR.instances["html_editor"].setMode('wysiwyg')
   291                      $('.nav-tabs a[href="#html"]').click()
   292                  }
   293                  $("#importEmailModal").modal("hide")
   294              })
   295              .error(function (data) {
   296                  modalError(data.responseJSON.message)
   297              })
   298      }
   299  }
   300  
   301  function load() {
   302      $("#templateTable").hide()
   303      $("#emptyMessage").hide()
   304      $("#loading").show()
   305      api.templates.get()
   306          .success(function (ts) {
   307              templates = ts
   308              $("#loading").hide()
   309              if (templates.length > 0) {
   310                  $("#templateTable").show()
   311                  templateTable = $("#templateTable").DataTable({
   312                      destroy: true,
   313                      columnDefs: [{
   314                          orderable: false,
   315                          targets: "no-sort"
   316                      }]
   317                  });
   318                  templateTable.clear()
   319                  $.each(templates, function (i, template) {
   320                      templateTable.row.add([
   321                          escapeHtml(template.name),
   322                          moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
   323                          "<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 Template' onclick='edit(" + i + ")'>\
   324                      <i class='fa fa-pencil'></i>\
   325                      </button></span>\
   326  		    <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Template' onclick='copy(" + i + ")'>\
   327                      <i class='fa fa-copy'></i>\
   328                      </button></span>\
   329                      <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Template' onclick='deleteTemplate(" + i + ")'>\
   330                      <i class='fa fa-trash-o'></i>\
   331                      </button></div>"
   332                      ]).draw()
   333                  })
   334                  $('[data-toggle="tooltip"]').tooltip()
   335              } else {
   336                  $("#emptyMessage").show()
   337              }
   338          })
   339          .error(function () {
   340              $("#loading").hide()
   341              errorFlash("Error fetching templates")
   342          })
   343  }
   344  
   345  $(document).ready(function () {
   346      // Setup multiple modals
   347      // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html
   348      $('.modal').on('hidden.bs.modal', function (event) {
   349          $(this).removeClass('fv-modal-stack');
   350          $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1);
   351      });
   352      $('.modal').on('shown.bs.modal', function (event) {
   353          // Keep track of the number of open modals
   354          if (typeof ($('body').data('fv_open_modals')) == 'undefined') {
   355              $('body').data('fv_open_modals', 0);
   356          }
   357          // if the z-index of this modal has been set, ignore.
   358          if ($(this).hasClass('fv-modal-stack')) {
   359              return;
   360          }
   361          $(this).addClass('fv-modal-stack');
   362          // Increment the number of open modals
   363          $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1);
   364          // Setup the appropriate z-index
   365          $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals')));
   366          $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
   367          $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack');
   368      });
   369      $.fn.modal.Constructor.prototype.enforceFocus = function () {
   370          $(document)
   371              .off('focusin.bs.modal') // guard against infinite focus loop
   372              .on('focusin.bs.modal', $.proxy(function (e) {
   373                  if (
   374                      this.$element[0] !== e.target && !this.$element.has(e.target).length
   375                      // CKEditor compatibility fix start.
   376                      &&
   377                      !$(e.target).closest('.cke_dialog, .cke').length
   378                      // CKEditor compatibility fix end.
   379                  ) {
   380                      this.$element.trigger('focus');
   381                  }
   382              }, this));
   383      };
   384      // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay
   385      $(document).on('hidden.bs.modal', '.modal', function () {
   386          $('.modal:visible').length && $(document.body).addClass('modal-open');
   387      });
   388      $('#modal').on('hidden.bs.modal', function (event) {
   389          dismiss()
   390      });
   391      $("#importEmailModal").on('hidden.bs.modal', function (event) {
   392          $("#email_content").val("")
   393      })
   394      CKEDITOR.on('dialogDefinition', function (ev) {
   395          // Take the dialog name and its definition from the event data.
   396          var dialogName = ev.data.name;
   397          var dialogDefinition = ev.data.definition;
   398  
   399          // Check if the definition is from the dialog window you are interested in (the "Link" dialog window).
   400          if (dialogName == 'link') {
   401              dialogDefinition.minWidth = 500
   402              dialogDefinition.minHeight = 100
   403  
   404              // Remove the linkType field
   405              var infoTab = dialogDefinition.getContents('info');
   406              infoTab.get('linkType').hidden = true;
   407          }
   408      });
   409      load()
   410  
   411  })