mirror of
https://github.com/gophish/gophish
synced 2024-11-14 16:27:23 +00:00
Added autocomplete for template tags to the editor for email templates and landing pages.
This commit is contained in:
parent
60133b45e8
commit
b4ff771b3a
10 changed files with 133 additions and 3 deletions
2
static/css/dist/gophish.css
vendored
2
static/css/dist/gophish.css
vendored
File diff suppressed because one or more lines are too long
8
static/css/main.css
vendored
8
static/css/main.css
vendored
|
@ -713,4 +713,12 @@ table.dataTable {
|
|||
|
||||
.cke_chrome {
|
||||
border-top: 0 !important;
|
||||
}
|
||||
|
||||
.cke_autocomplete_panel {
|
||||
width: 400px !important;
|
||||
}
|
||||
|
||||
.cke_autocomplete_panel>li {
|
||||
padding: 10px 5px !important;
|
||||
}
|
1
static/js/dist/app/autocomplete.min.js
vendored
Normal file
1
static/js/dist/app/autocomplete.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
var TEMPLATE_TAGS=[{id:1,name:"RId",description:"The unique ID for the recipient."},{id:2,name:"FirstName",description:"The recipient's first name."},{id:3,name:"LastName",description:"The recipient's last name."},{id:4,name:"Position",description:"The recipient's position."},{id:5,name:"From",description:"The address emails are sent from."},{id:6,name:"TrackingURL",description:"The URL to track emails being opened."},{id:7,name:"Tracker",description:"An HTML tag that adds a hidden tracking image (recommended instead of TrackingURL)."},{id:8,name:"URL",description:"The URL to your Gophish listener."},{id:9,name:"BaseURL",description:"The base URL with the path and rid parameter stripped. Useful for making links to static files."}],textTestCallback=function(e){return e.collapsed?CKEDITOR.plugins.textMatch.match(e,matchCallback):null},matchCallback=function(e,t){var i=/\{{2}\.?([A-z]|\})*$/,a=e.slice(0,t).match(i);return a?{start:a.index,end:t}:null},dataCallback=function(e,t){t(TEMPLATE_TAGS.filter(function(t){return 0==("{{."+t.name.toLowerCase()+"}}").indexOf(e.query.toLowerCase())}))},setupAutocomplete=function(e){e.on("instanceReady",function(e){new CKEDITOR.plugins.autocomplete(e.editor,{textTestCallback:textTestCallback,dataCallback:dataCallback,itemTemplate:'<li data-id="{id}"><div><strong class="item-title">{name}</strong></div><div><i>{description}</i></div></li>',outputTemplate:"[[.{name}]]"}).getHtmlToInsert=function(e){var t=this.outputTemplate.output(e);return t=t.replace("[[","{{").replace("]]","}}")}})};
|
2
static/js/dist/app/landing_pages.min.js
vendored
2
static/js/dist/app/landing_pages.min.js
vendored
File diff suppressed because one or more lines are too long
2
static/js/dist/app/templates.min.js
vendored
2
static/js/dist/app/templates.min.js
vendored
File diff suppressed because one or more lines are too long
115
static/js/src/app/autocomplete.js
Normal file
115
static/js/src/app/autocomplete.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
var TEMPLATE_TAGS = [{
|
||||
id: 1,
|
||||
name: 'RId',
|
||||
description: 'The unique ID for the recipient.'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'FirstName',
|
||||
description: 'The recipient\'s first name.'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'LastName',
|
||||
description: 'The recipient\'s last name.'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Position',
|
||||
description: 'The recipient\'s position.'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'From',
|
||||
description: 'The address emails are sent from.'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'TrackingURL',
|
||||
description: 'The URL to track emails being opened.'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Tracker',
|
||||
description: 'An HTML tag that adds a hidden tracking image (recommended instead of TrackingURL).'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'URL',
|
||||
description: 'The URL to your Gophish listener.'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'BaseURL',
|
||||
description: 'The base URL with the path and rid parameter stripped. Useful for making links to static files.'
|
||||
}
|
||||
];
|
||||
|
||||
var textTestCallback = function (range) {
|
||||
if (!range.collapsed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CKEDITOR.plugins.textMatch.match(range, matchCallback);
|
||||
}
|
||||
|
||||
var matchCallback = function (text, offset) {
|
||||
var pattern = /\{{2}\.?([A-z]|\})*$/,
|
||||
match = text.slice(0, offset)
|
||||
.match(pattern);
|
||||
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
start: match.index,
|
||||
end: offset
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {regex} matchInfo - The matched text object
|
||||
* @param {function} callback - The callback to execute with the matched data
|
||||
*/
|
||||
var dataCallback = function (matchInfo, callback) {
|
||||
var data = TEMPLATE_TAGS.filter(function (item) {
|
||||
var itemName = '{{.' + item.name.toLowerCase() + '}}';
|
||||
return itemName.indexOf(matchInfo.query.toLowerCase()) == 0;
|
||||
});
|
||||
|
||||
callback(data);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {CKEditor} editor - The CKEditor instance.
|
||||
*
|
||||
* Installs the autocomplete plugin to the CKEditor.
|
||||
*/
|
||||
var setupAutocomplete = function (editor) {
|
||||
editor.on('instanceReady', function (evt) {
|
||||
var itemTemplate = '<li data-id="{id}">' +
|
||||
'<div><strong class="item-title">{name}</strong></div>' +
|
||||
'<div><i>{description}</i></div>' +
|
||||
'</li>',
|
||||
outputTemplate = '[[.{name}]]';
|
||||
|
||||
var autocomplete = new CKEDITOR.plugins.autocomplete(evt.editor, {
|
||||
textTestCallback: textTestCallback,
|
||||
dataCallback: dataCallback,
|
||||
itemTemplate: itemTemplate,
|
||||
outputTemplate: outputTemplate
|
||||
});
|
||||
|
||||
// We have to use brackets for the output template tag and
|
||||
// then manually replace them due to the way CKEditor's
|
||||
// templating works.
|
||||
autocomplete.getHtmlToInsert = function (item) {
|
||||
var parsedTemplate = this.outputTemplate.output(item);
|
||||
parsedTemplate = parsedTemplate.replace("[[", "{{").replace("]]", "}}")
|
||||
return parsedTemplate
|
||||
}
|
||||
});
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
var pages = []
|
||||
|
||||
|
||||
// Save attempts to POST to /templates/
|
||||
function save(idx) {
|
||||
var page = {}
|
||||
|
@ -107,6 +108,7 @@ function edit(idx) {
|
|||
save(idx)
|
||||
})
|
||||
$("#html_editor").ckeditor()
|
||||
setupAutocomplete(CKEDITOR.instances["html_editor"])
|
||||
var page = {}
|
||||
if (idx != -1) {
|
||||
page = pages[idx]
|
||||
|
@ -244,5 +246,6 @@ $(document).ready(function () {
|
|||
infoTab.get('linkType').hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
load()
|
||||
})
|
|
@ -165,6 +165,7 @@ function edit(idx) {
|
|||
this.value = null
|
||||
})
|
||||
$("#html_editor").ckeditor()
|
||||
setupAutocomplete(CKEDITOR.instances["html_editor"])
|
||||
$("#attachmentsTable").show()
|
||||
attachmentsTable = $('#attachmentsTable').DataTable({
|
||||
destroy: true,
|
||||
|
|
|
@ -148,5 +148,6 @@
|
|||
{{define "scripts"}}
|
||||
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
||||
<script src="/js/src/vendor/ckeditor/adapters/jquery.js"></script>
|
||||
<script src="/js/dist/app/autocomplete.min.js"></script>
|
||||
<script src="/js/dist/app/landing_pages.min.js"></script>
|
||||
{{end}}
|
|
@ -165,5 +165,6 @@
|
|||
{{define "scripts"}}
|
||||
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
||||
<script src="/js/src/vendor/ckeditor/adapters/jquery.js"></script>
|
||||
<script src="/js/dist/app/autocomplete.min.js"></script>
|
||||
<script src="/js/dist/app/templates.min.js"></script>
|
||||
{{end}}
|
Loading…
Reference in a new issue