diff --git a/blash.css b/blash.css
index da09cb0..da4f52e 100644
--- a/blash.css
+++ b/blash.css
@@ -17,6 +17,16 @@ input.promptInput
width : 500px;
}
+input.password
+{
+ background-color : black;
+ border : 0;
+ color : #888;
+ font-family : Terminus, courier, monospace, fixed;
+ font-size : 13px;
+ width : 500px;
+}
+
div#blashWindow
{
width : 800px;
diff --git a/blash.js b/blash.js
index b2d1cce..bc46107 100644
--- a/blash.js
+++ b/blash.js
@@ -48,6 +48,12 @@ function blash ()
/** Check if this is the first command given in this session (for fixing
stuff) */
this.__first_cmd = true;
+
+ /** Variable set if the prompt is re-generated automatically after a command was given */
+ this.auto_prompt_refresh = true;
+
+ /** Variable set if the focus should be automatically set to the prompt line after a command */
+ this.auto_prompt_focus = true;
/**************************************/
this.loadCommand = function ( cmd )
@@ -139,48 +145,55 @@ function blash ()
}
}
- var value = this.prompt.value;
- var out = this.cmdOut.innerHTML;
-
- var text = ( shell.json.promptText ) ? shell.json.promptText : "[%n@%m %W] $ ";
- text = shell.unescapePrompt ( text, shell.json.promptSequences );
-
- this.window.removeChild ( this.prompt );
- this.window.removeChild ( this.cmdOut );
-
- if ( this.__first_cmd && this.prompt.value.length > 0 )
+ if ( this.auto_prompt_refresh )
{
- this.window.innerHTML += value + '
' + out + text;
- this.__first_cmd = false;
- } else {
- if ( out )
+ var value = this.prompt.value;
+ var out = this.cmdOut.innerHTML;
+
+ var text = ( shell.json.promptText ) ? shell.json.promptText : "[%n@%m %W] $ ";
+ text = shell.unescapePrompt ( text, shell.json.promptSequences );
+
+ this.window.removeChild ( this.prompt );
+ this.window.removeChild ( this.cmdOut );
+
+ if ( this.__first_cmd && this.prompt.value.length > 0 )
{
- if ( out.match ( /^\s*\s*/ ))
+ this.window.innerHTML += value + '
' + out + text;
+ this.__first_cmd = false;
+ } else {
+ if ( out )
{
- out = '';
+ if ( out.match ( /^\s*\s*/ ))
+ {
+ out = '';
+ }
}
+
+ this.window.innerHTML += value + '
' + out + text;
}
- this.window.innerHTML += value + '
' + out + text;
+ this.prompt = document.createElement ( 'input' );
+ this.prompt.setAttribute ( 'name', 'blashPrompt' );
+ this.prompt.setAttribute ( 'type', 'text' );
+ this.prompt.setAttribute ( 'class', 'promptInput' );
+ this.prompt.setAttribute ( 'autocomplete', 'off' );
+ this.prompt.setAttribute ( 'onkeydown', 'shell.getKey ( event )' );
+ this.prompt.setAttribute ( 'onkeyup', 'this.focus()' );
+ this.prompt.setAttribute ( 'onblur', 'return false' );
+
+ this.cmdOut = document.createElement ( 'div' );
+ this.cmdOut.setAttribute ( 'id', 'blashCmdOut' );
+ this.cmdOut.setAttribute ( 'class', 'blashCmdOut' );
+ this.cmdOut.innerHTML = '
';
+
+ this.window.appendChild ( this.prompt );
+ this.window.appendChild ( this.cmdOut );
+
+ if ( this.auto_prompt_focus )
+ {
+ this.prompt.focus();
+ }
}
-
- this.prompt = document.createElement ( 'input' );
- this.prompt.setAttribute ( 'name', 'blashPrompt' );
- this.prompt.setAttribute ( 'type', 'text' );
- this.prompt.setAttribute ( 'class', 'promptInput' );
- this.prompt.setAttribute ( 'autocomplete', 'off' );
- this.prompt.setAttribute ( 'onkeydown', 'shell.getKey ( event )' );
- this.prompt.setAttribute ( 'onkeyup', 'this.focus()' );
- this.prompt.setAttribute ( 'onblur', 'return false' );
-
- this.cmdOut = document.createElement ( 'div' );
- this.cmdOut.setAttribute ( 'id', 'blashCmdOut' );
- this.cmdOut.setAttribute ( 'class', 'blashCmdOut' );
- this.cmdOut.innerHTML = '
';
-
- this.window.appendChild ( this.prompt );
- this.window.appendChild ( this.cmdOut );
- this.prompt.focus();
} else if ( key == 38 || key == 40 ) {
if ( key == 38 )
{
@@ -332,18 +345,24 @@ function blash ()
}
}
- this.prompt.focus();
- setTimeout ( function() { shell.prompt.focus(); }, 1 );
-
- if ( this.prompt.setSelectionRange )
+ if ( this.auto_prompt_focus )
{
- this.prompt.setSelectionRange ( this.prompt.value.length, this.prompt.value.length );
+ this.prompt.focus();
+ setTimeout ( function() { shell.prompt.focus(); }, 1 );
+
+ if ( this.prompt.setSelectionRange )
+ {
+ this.prompt.setSelectionRange ( this.prompt.value.length, this.prompt.value.length );
+ }
}
return false;
}
- this.prompt.focus();
+ if ( this.auto_prompt_focus )
+ {
+ this.prompt.focus();
+ }
}
this.unescapePrompt = function ( prompt, sequences )
@@ -374,6 +393,54 @@ function blash ()
return prompt;
}
+ /**
+ * \brief Refresh the shell prompt
+ * \param clearTerm Set this variable as true if you want also to clear the terminal screen
+ * \param clearOut Set this variable as true if you want to clear the latest output command
+ */
+ this.refreshPrompt = function ( clearTerm, clearOut )
+ {
+ var value = this.prompt.value;
+ var out = this.cmdOut.innerHTML;
+ var text = ( this.json.promptText ) ? this.json.promptText : "[%n@%m %W] $ ";
+ text = this.unescapePrompt ( text, this.json.promptSequences );
+
+ this.window.removeChild ( this.prompt );
+ this.window.removeChild ( this.cmdOut );
+
+ if ( clearTerm )
+ {
+ this.window.innerHTML = '';
+ }
+
+ if ( !clearOut )
+ {
+ if ( out.length > 0 )
+ {
+ var outDiv = document.createElement ( 'span' );
+ outDiv.innerHTML = '
' + out + '
' + text;
+ this.window.appendChild ( outDiv );
+ }
+ }
+
+ this.prompt = document.createElement ( 'input' );
+ this.prompt.setAttribute ( 'name', 'blashPrompt' );
+ this.prompt.setAttribute ( 'type', 'text' );
+ this.prompt.setAttribute ( 'class', 'promptInput' );
+ this.prompt.setAttribute ( 'autocomplete', 'off' );
+ this.prompt.setAttribute ( 'onkeydown', 'shell.getKey ( event )' );
+ this.prompt.setAttribute ( 'onkeyup', 'this.focus()' );
+ this.prompt.setAttribute ( 'onblur', 'return false' );
+
+ this.cmdOut = document.createElement ( 'div' );
+ this.cmdOut.setAttribute ( 'id', 'blashCmdOut' );
+ this.cmdOut.setAttribute ( 'class', 'blashCmdOut' );
+
+ this.window.appendChild ( this.prompt );
+ this.window.appendChild ( this.cmdOut );
+ this.prompt.focus();
+ }
+
this.unescapePromptSequence = function ( prompt, sequence, text, default_text )
{
var re = new RegExp ( "([^\]?)" + sequence, "g" );
diff --git a/blash.json b/blash.json
index 327eb11..974ff6c 100644
--- a/blash.json
+++ b/blash.json
@@ -189,11 +189,13 @@
"cat",
"cd",
"clear",
+ "echo",
"eval",
"find",
"ls",
"man",
"pwd",
+ "useradd",
"whoami",
],
}
diff --git a/commands/clear.json b/commands/clear.json
index c049011..5e9fff6 100644
--- a/commands/clear.json
+++ b/commands/clear.json
@@ -9,30 +9,7 @@
"action" : function ( arg )
{
var out = '';
- var text = ( shell.json.promptText ) ? shell.json.promptText : "[%n@%m %W] $ ";
- text = shell.unescapePrompt ( text, shell.json.promptSequences );
-
- shell.window.removeChild ( shell.prompt );
- shell.window.removeChild ( shell.cmdOut );
- shell.window.innerHTML = '';
-
- shell.prompt = document.createElement ( 'input' );
- shell.prompt.setAttribute ( 'name', 'blashPrompt' );
- shell.prompt.setAttribute ( 'type', 'text' );
- shell.prompt.setAttribute ( 'class', 'promptInput' );
- shell.prompt.setAttribute ( 'autocomplete', 'off' );
- shell.prompt.setAttribute ( 'onkeydown', 'shell.getKey ( event )' );
- shell.prompt.setAttribute ( 'onkeyup', 'this.focus()' );
- shell.prompt.setAttribute ( 'onblur', 'return false' );
-
- shell.cmdOut = document.createElement ( 'div' );
- shell.cmdOut.setAttribute ( 'id', 'blashCmdOut' );
- shell.cmdOut.setAttribute ( 'class', 'blashCmdOut' );
-
- shell.window.appendChild ( shell.prompt );
- shell.window.appendChild ( shell.cmdOut );
- shell.prompt.focus();
-
+ shell.refreshPrompt ( true );
return out;
},
}
diff --git a/commands/echo.json b/commands/echo.json
new file mode 100644
index 0000000..2acfa33
--- /dev/null
+++ b/commands/echo.json
@@ -0,0 +1,15 @@
+{
+ "name" : "echo",
+
+ "info" : {
+ "syntax" : "echo [text]",
+ "brief" : "Display a line of text",
+ },
+
+ "action" : function ( arg )
+ {
+ var out = arg + "
\n";
+ return out;
+ },
+}
+
diff --git a/commands/useradd.json b/commands/useradd.json
new file mode 100644
index 0000000..c1dc323
--- /dev/null
+++ b/commands/useradd.json
@@ -0,0 +1,113 @@
+{
+ "name" : "useradd",
+
+ "info" : {
+ "syntax" : "useradd <username>",
+ "brief" : "Create a new user on the system",
+ },
+
+ "password" : '',
+ "repeatPassword" : '',
+
+ "keyPassword" : function ( e )
+ {
+ var evt = ( window.event ) ? window.event : e;
+ var key = ( evt.charCode ) ? evt.charCode : evt.keyCode;
+ var password = document.getElementsByName ( "password" )[0];
+ var repeatPassword = document.getElementsByName ( "repeatPassword" )[0];
+ var repeatPasswordText = document.getElementById ( "repeatPasswordText" );
+
+ if ( key == 13 && password.value.length > 0 )
+ {
+ repeatPassword.style.visibility = 'visible';
+ repeatPasswordText.style.visibility = 'visible';
+ repeatPassword.focus();
+ }
+ },
+
+ "keyRepeatPassword" : function ( e )
+ {
+ var evt = ( window.event ) ? window.event : e;
+ var key = ( evt.charCode ) ? evt.charCode : evt.keyCode;
+ var password = document.getElementsByName ( "password" )[0];
+ var repeatPassword = document.getElementsByName ( "repeatPassword" )[0];
+ var repeatPasswordText = document.getElementById ( "repeatPasswordText" );
+
+ if ( key == 13 && password.value.length > 0 )
+ {
+ if ( password.value != repeatPassword.value )
+ {
+ shell.cmdOut.innerHTML = 'The passwords do not match';
+ } else {
+ var users_php = window.location.href;
+ users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+ params = 'action=add&user=' + escape ( shell.newuser ) + '&pass=' + md5 ( password.value );
+
+ var http = new XMLHttpRequest();
+ http.open ( "POST", users_php, true );
+ http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ http.setRequestHeader("Content-length", params.length);
+ http.setRequestHeader("Connection", "close");
+
+ http.onreadystatechange = function ()
+ {
+ if ( http.readyState == 4 && http.status == 200 )
+ {
+ if ( http.responseText.length > 0 )
+ {
+ shell.cmdOut.innerHTML = http.responseText;
+ } else {
+ shell.cmdOut.innerHTML = '';
+ }
+
+ shell.refreshPrompt ( false, false );
+ }
+ }
+
+ http.send ( params );
+ shell.cmdOut.innerHTML = '';
+ }
+
+ shell.auto_prompt_focus = true;
+ shell.auto_prompt_refresh = true;
+ shell.refreshPrompt ( false, false );
+ }
+ },
+
+ "action" : function ( arg )
+ {
+ var out = '';
+
+ if ( !arg || arg.length == 0 )
+ {
+ return "Usage: " + this.name + " <username>
\n";
+ }
+
+ shell.keyPassword = this.keyPassword;
+ shell.keyRepeatPassword = this.keyRepeatPassword;
+ shell.newuser = arg;
+
+ if ( shell.__first_cmd )
+ {
+ shell.cmdOut.innerHTML = '
';
+ shell.__first_cmd = false;
+ }
+
+ shell.cmdOut.innerHTML += 'Password: ' +
+ '
' +
+ 'Repeat password: ' +
+ '
';
+
+ shell.auto_prompt_focus = false;
+ shell.auto_prompt_refresh = false;
+
+ this.password = document.getElementsByName ( "password" )[0];
+ this.password.focus();
+
+ return out;
+ },
+}
+
diff --git a/index.html b/index.html
index aad07ae..5c6f0b4 100644
--- a/index.html
+++ b/index.html
@@ -2,6 +2,7 @@
Blash - An AJAX interactive shell emulator for web browsing
+
diff --git a/md5.js b/md5.js
new file mode 100644
index 0000000..e09c081
--- /dev/null
+++ b/md5.js
@@ -0,0 +1,209 @@
+/**
+*
+* MD5 (Message-Digest Algorithm)
+* http://www.webtoolkit.info/
+*
+**/
+
+function md5 (string)
+{
+
+ function RotateLeft(lValue, iShiftBits) {
+ return (lValue<>>(32-iShiftBits));
+ }
+
+ function AddUnsigned(lX,lY) {
+ var lX4,lY4,lX8,lY8,lResult;
+ lX8 = (lX & 0x80000000);
+ lY8 = (lY & 0x80000000);
+ lX4 = (lX & 0x40000000);
+ lY4 = (lY & 0x40000000);
+ lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+ if (lX4 & lY4) {
+ return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+ }
+ if (lX4 | lY4) {
+ if (lResult & 0x40000000) {
+ return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+ } else {
+ return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+ }
+ } else {
+ return (lResult ^ lX8 ^ lY8);
+ }
+ }
+
+ function F(x,y,z) { return (x & y) | ((~x) & z); }
+ function G(x,y,z) { return (x & z) | (y & (~z)); }
+ function H(x,y,z) { return (x ^ y ^ z); }
+ function I(x,y,z) { return (y ^ (x | (~z))); }
+
+ function FF(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function GG(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function HH(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function II(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ };
+
+ function ConvertToWordArray(string) {
+ var lWordCount;
+ var lMessageLength = string.length;
+ var lNumberOfWords_temp1=lMessageLength + 8;
+ var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+ var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+ var lWordArray=Array(lNumberOfWords-1);
+ var lBytePosition = 0;
+ var lByteCount = 0;
+ while ( lByteCount < lMessageLength ) {
+ lWordCount = (lByteCount-(lByteCount % 4))/4;
+ lBytePosition = (lByteCount % 4)*8;
+ lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
+ return lWordArray;
+ };
+
+ function WordToHex(lValue) {
+ var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+ for (lCount = 0;lCount<=3;lCount++) {
+ lByte = (lValue>>>(lCount*8)) & 255;
+ WordToHexValue_temp = "0" + lByte.toString(16);
+ WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+ }
+ return WordToHexValue;
+ };
+
+ function Utf8Encode(string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ };
+
+ var x=Array();
+ var k,AA,BB,CC,DD,a,b,c,d;
+ var S11=7, S12=12, S13=17, S14=22;
+ var S21=5, S22=9 , S23=14, S24=20;
+ var S31=4, S32=11, S33=16, S34=23;
+ var S41=6, S42=10, S43=15, S44=21;
+
+ string = Utf8Encode(string);
+
+ x = ConvertToWordArray(string);
+
+ a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+
+ for (k=0;k
+
+
+
+XML;
+
+?>
diff --git a/modules/users/users.php b/modules/users/users.php
new file mode 100644
index 0000000..e381134
--- /dev/null
+++ b/modules/users/users.php
@@ -0,0 +1,68 @@
+user ); $i++ )
+ {
+ if ( !strcasecmp ( $xml->user[$i]['name'], $username ))
+ {
+ print "The specified user already exists\n";
+ return 1;
+ }
+ }
+
+ $newuser = $xml->addChild ( 'user' );
+ $newuser->addAttribute ( 'name', $username );
+ $newuser->addAttribute ( 'pass', $password );
+ $newuser->addAttribute ( 'home', '/home/' . $username );
+
+ if ( !( $fp = fopen ( 'userlist.php', 'w' )))
+ {
+ print "Unable to add the specified user, unknown error\n";
+ return 1;
+ }
+
+ fwrite ( $fp, "asXML() . "\nXML;\n\n?>\n" );
+ fclose ( $fp );
+
+ print 'User "'.$username.' successfully added, home directory set to "/home/'.$username."\"\n";
+ break;
+}
+
+?>
+