mirror of
https://github.com/gophish/gophish
synced 2024-11-15 00:37:14 +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
|
@ -714,3 +714,11 @@ table.dataTable {
|
||||||
.cke_chrome {
|
.cke_chrome {
|
||||||
border-top: 0 !important;
|
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 = []
|
var pages = []
|
||||||
|
|
||||||
|
|
||||||
// Save attempts to POST to /templates/
|
// Save attempts to POST to /templates/
|
||||||
function save(idx) {
|
function save(idx) {
|
||||||
var page = {}
|
var page = {}
|
||||||
|
@ -107,6 +108,7 @@ function edit(idx) {
|
||||||
save(idx)
|
save(idx)
|
||||||
})
|
})
|
||||||
$("#html_editor").ckeditor()
|
$("#html_editor").ckeditor()
|
||||||
|
setupAutocomplete(CKEDITOR.instances["html_editor"])
|
||||||
var page = {}
|
var page = {}
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
page = pages[idx]
|
page = pages[idx]
|
||||||
|
@ -244,5 +246,6 @@ $(document).ready(function () {
|
||||||
infoTab.get('linkType').hidden = true;
|
infoTab.get('linkType').hidden = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
load()
|
load()
|
||||||
})
|
})
|
|
@ -165,6 +165,7 @@ function edit(idx) {
|
||||||
this.value = null
|
this.value = null
|
||||||
})
|
})
|
||||||
$("#html_editor").ckeditor()
|
$("#html_editor").ckeditor()
|
||||||
|
setupAutocomplete(CKEDITOR.instances["html_editor"])
|
||||||
$("#attachmentsTable").show()
|
$("#attachmentsTable").show()
|
||||||
attachmentsTable = $('#attachmentsTable').DataTable({
|
attachmentsTable = $('#attachmentsTable').DataTable({
|
||||||
destroy: true,
|
destroy: true,
|
||||||
|
|
|
@ -148,5 +148,6 @@
|
||||||
{{define "scripts"}}
|
{{define "scripts"}}
|
||||||
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
||||||
<script src="/js/src/vendor/ckeditor/adapters/jquery.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>
|
<script src="/js/dist/app/landing_pages.min.js"></script>
|
||||||
{{end}}
|
{{end}}
|
|
@ -165,5 +165,6 @@
|
||||||
{{define "scripts"}}
|
{{define "scripts"}}
|
||||||
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
<script src="/js/src/vendor/ckeditor/ckeditor.js"></script>
|
||||||
<script src="/js/src/vendor/ckeditor/adapters/jquery.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>
|
<script src="/js/dist/app/templates.min.js"></script>
|
||||||
{{end}}
|
{{end}}
|
Loading…
Reference in a new issue