2018-05-15 17:36:45 +00:00
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
2019-07-09 12:23:59 +01:00
import HTMLIngredient from "./HTMLIngredient.mjs" ;
2021-02-10 13:13:19 +00:00
import Utils from "../core/Utils.mjs" ;
2021-02-10 17:41:39 +00:00
import url from "url" ;
2018-05-15 17:36:45 +00:00
/**
* Object to handle the creation of operations.
*/
class HTMLOperation {
/**
* HTMLOperation constructor.
*
* @param {string} name - The name of the operation.
* @param {Object} config - The configuration object for this operation.
* @param {App} app - The main view object for CyberChef.
* @param {Manager} manager - The CyberChef event manager.
*/
constructor ( name , config , app , manager ) {
this . app = app ;
this . manager = manager ;
this . name = name ;
this . description = config . description ;
2018-08-21 19:07:13 +01:00
this . infoURL = config . infoURL ;
2018-05-15 17:36:45 +00:00
this . manualBake = config . manualBake || false ;
this . config = config ;
this . ingList = [];
for ( let i = 0 ; i < config . args . length ; i ++ ) {
const ing = new HTMLIngredient ( config . args [ i ], this . app , this . manager );
this . ingList . push ( ing );
}
}
/**
* Renders the operation in HTML as a stub operation with no ingredients.
*
* @returns {string}
*/
toStubHtml ( removeIcon ) {
let html = "<li class='operation'" ;
if ( this . description ) {
2018-08-21 19:07:13 +01:00
const infoLink = this . infoURL ? `<hr> ${ titleFromWikiLink ( this . infoURL ) } ` : "" ;
2018-06-09 10:43:36 +01:00
html += ` data-container='body' data-toggle='popover' data-placement='right'
2018-08-21 19:07:13 +01:00
data-content=" ${ this . description }${ infoLink } " data-html='true' data-trigger='hover'
2018-06-09 10:43:36 +01:00
data-boundary='viewport'` ;
2018-05-15 17:36:45 +00:00
}
html += ">" + this . name ;
if ( removeIcon ) {
2018-06-10 14:55:15 +01:00
html += "<i class='material-icons remove-icon op-icon'>delete</i>" ;
2018-05-15 17:36:45 +00:00
}
html += "</li>" ;
return html ;
}
/**
* Renders the operation in HTML as a full operation with ingredients.
*
* @returns {string}
*/
toFullHtml () {
2021-02-10 13:13:19 +00:00
let html = `<div class="op-title"> ${ Utils . escapeHtml ( this . name ) } </div>
2018-06-19 00:55:08 +01:00
<div class="ingredients">` ;
2018-05-15 17:36:45 +00:00
for ( let i = 0 ; i < this . ingList . length ; i ++ ) {
html += this . ingList [ i ]. toHtml ();
}
2018-06-19 00:55:08 +01:00
html += `</div>
<div class="recip-icons">
2023-03-17 17:46:13 +00:00
<i class="material-icons breakpoint" title="Set breakpoint" break="false" data-help-title="Setting breakpoints" data-help="Setting a breakpoint on an operation will cause execution of the Recipe to pause when it reaches that operation.">pause</i>
<i class="material-icons disable-icon" title="Disable operation" disabled="false" data-help-title="Disabling operations" data-help="Disabling an operation will prevent it from being executed when the Recipe is baked. Execution will skip over the disabled operation and continue with subsequent operations.">not_interested</i>
2018-06-09 10:43:36 +01:00
</div>
<div class="clearfix"> </div>` ;
2018-05-15 17:36:45 +00:00
return html ;
}
/**
2021-02-05 17:54:57 +00:00
* Highlights searched strings in the name and description of the operation.
2018-05-15 17:36:45 +00:00
*
2021-02-05 17:54:57 +00:00
* @param {[[number]]} nameIdxs - Indexes of the search strings in the operation name [[start, length]]
* @param {[[number]]} descIdxs - Indexes of the search strings in the operation description [[start, length]]
2018-05-15 17:36:45 +00:00
*/
2021-02-05 17:54:57 +00:00
highlightSearchStrings ( nameIdxs , descIdxs ) {
2021-02-09 11:50:20 +00:00
if ( nameIdxs . length && typeof nameIdxs [ 0 ][ 0 ] === "number" ) {
2021-02-05 17:54:57 +00:00
let opName = "" ,
pos = 0 ;
nameIdxs . forEach ( idxs => {
const [ start , length ] = idxs ;
2021-02-09 11:50:20 +00:00
if ( typeof start !== "number" ) return ;
2021-02-05 17:54:57 +00:00
opName += this . name . slice ( pos , start ) + "<b>" +
this . name . slice ( start , start + length ) + "</b>" ;
pos = start + length ;
});
opName += this . name . slice ( pos , this . name . length );
this . name = opName ;
2018-05-15 17:36:45 +00:00
}
2021-02-09 11:37:25 +00:00
if ( this . description && descIdxs . length && descIdxs [ 0 ][ 0 ] >= 0 ) {
2018-05-15 17:36:45 +00:00
// Find HTML tag offsets
const re = /<[^>]+>/g ;
let match ;
while (( match = re . exec ( this . description ))) {
// If the search string occurs within an HTML tag, return without highlighting it.
2021-02-05 17:54:57 +00:00
const inHTMLTag = descIdxs . reduce (( acc , idxs ) => {
const start = idxs [ 0 ];
return start >= match . index && start <= ( match . index + match [ 0 ]. length );
}, false );
if ( inHTMLTag ) return ;
2018-05-15 17:36:45 +00:00
}
2021-02-05 17:54:57 +00:00
let desc = "" ,
pos = 0 ;
descIdxs . forEach ( idxs => {
const [ start , length ] = idxs ;
desc += this . description . slice ( pos , start ) + "<b><u>" +
this . description . slice ( start , start + length ) + "</u></b>" ;
pos = start + length ;
});
desc += this . description . slice ( pos , this . description . length );
this . description = desc ;
2018-05-15 17:36:45 +00:00
}
}
}
2018-08-21 19:07:13 +01:00
/**
* Given a URL for a Wikipedia (or other wiki) page, this function returns a link to that page.
*
2021-02-10 17:41:39 +00:00
* @param {string} urlStr
2018-08-21 19:07:13 +01:00
* @returns {string}
*/
2021-02-10 17:41:39 +00:00
function titleFromWikiLink ( urlStr ) {
const urlObj = url . parse ( urlStr );
let wikiName = "" ,
pageTitle = "" ;
switch ( urlObj . host ) {
case "forensicswiki.xyz" :
wikiName = "Forensics Wiki" ;
pageTitle = urlObj . query . substr ( 6 ). replace ( /_/g , " " ); // Chop off 'title='
break ;
case "wikipedia.org" :
wikiName = "Wikipedia" ;
pageTitle = urlObj . pathname . substr ( 6 ). replace ( /_/g , " " ); // Chop off '/wiki/'
break ;
default :
// Not a wiki link, return full URL
return `<a href=' ${ urlStr } ' target='_blank'>More Information<i class='material-icons inline-icon'>open_in_new</i></a>` ;
2018-08-21 19:07:13 +01:00
}
2021-02-10 17:41:39 +00:00
return `<a href=' ${ urlObj . href } ' target='_blank'> ${ pageTitle } <i class='material-icons inline-icon'>open_in_new</i></a> on ${ wikiName } ` ;
2018-08-21 19:07:13 +01:00
}
2018-05-15 17:36:45 +00:00
export default HTMLOperation ;