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