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  })