diff --git a/blash.css b/blash.css
index 024fbfa..11bb6dd 100644
--- a/blash.css
+++ b/blash.css
@@ -29,11 +29,11 @@ input.password
div#blashWindow
{
- width : 800px;
- height : 400px;
+ /* width : 800px; */
+ /* height : 400px; */
margin : auto;
- padding : 10px;
- border : 1px solid #888;
+ /* padding : 10px; */
+ /* border : 1px solid #888; */
overflow : auto;
tabindex : -1;
}
diff --git a/commands/mkdir.json b/commands/mkdir.json
new file mode 100644
index 0000000..938038e
--- /dev/null
+++ b/commands/mkdir.json
@@ -0,0 +1,89 @@
+{
+ "name" : "mkdir",
+
+ "info" : {
+ "syntax" : "mkdir <directory name>",
+ "brief" : "Create a new directory",
+ },
+
+ "action" : function ( arg )
+ {
+ if ( !arg || arg.length == 0 )
+ {
+ return "mkdir: Parameter expected
\n";
+ }
+
+ shell.auto_prompt_focus = false;
+ shell.auto_prompt_refresh = false;
+ arg = shell.expandPath ( arg );
+
+ var users_php = window.location.href;
+ users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+ params = 'action=mkdir&dir=' + escape ( arg );
+
+ 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 {
+ var files_config = window.location.href;
+ files_config = files_config.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/files.php' );
+
+ var http2 = new XMLHttpRequest();
+ http2.open ( "GET", files_config, true );
+
+ http2.onreadystatechange = function ()
+ {
+ if ( http2.readyState == 4 && http2.status == 200 )
+ {
+ shell.files = eval ( '(' + http2.responseText + ')' );
+
+ // Remove duplicates
+ var tmp = new Array();
+
+ for ( var i in shell.files )
+ {
+ var contains = false;
+
+ for ( var j=0; j < tmp.length && !contains; j++ )
+ {
+ if ( shell.files[i].path == tmp[j].path )
+ {
+ contains = true;
+ }
+ }
+
+ if ( !contains )
+ {
+ tmp.push ( shell.files[i] );
+ }
+ }
+
+ shell.files = tmp;
+ }
+ }
+
+ http2.send ( null );
+ shell.cmdOut.innerHTML = '';
+ }
+
+ shell.refreshPrompt ( false, false );
+ shell.auto_prompt_focus = true;
+ shell.auto_prompt_refresh = true;
+ }
+ }
+
+ http.send ( params );
+ shell.cmdOut.innerHTML = '';
+ }
+}
+
diff --git a/commands/rmdir.json b/commands/rmdir.json
new file mode 100644
index 0000000..861bee7
--- /dev/null
+++ b/commands/rmdir.json
@@ -0,0 +1,89 @@
+{
+ "name" : "rmdir",
+
+ "info" : {
+ "syntax" : "rmdir <directory name>",
+ "brief" : "Remove a directory (recursively if the directory is not empty)",
+ },
+
+ "action" : function ( arg )
+ {
+ if ( !arg || arg.length == 0 )
+ {
+ return "mkdir: Parameter expected
\n";
+ }
+
+ shell.auto_prompt_focus = false;
+ shell.auto_prompt_refresh = false;
+ arg = shell.expandPath ( arg );
+
+ var users_php = window.location.href;
+ users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+ params = 'action=rmdir&dir=' + escape ( arg );
+
+ 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 {
+ var files_config = window.location.href;
+ files_config = files_config.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/files.php' );
+
+ var http2 = new XMLHttpRequest();
+ http2.open ( "GET", files_config, true );
+
+ http2.onreadystatechange = function ()
+ {
+ if ( http2.readyState == 4 && http2.status == 200 )
+ {
+ shell.files = eval ( '(' + http2.responseText + ')' );
+
+ // Remove duplicates
+ var tmp = new Array();
+
+ for ( var i in shell.files )
+ {
+ var contains = false;
+
+ for ( var j=0; j < tmp.length && !contains; j++ )
+ {
+ if ( shell.files[i].path == tmp[j].path )
+ {
+ contains = true;
+ }
+ }
+
+ if ( !contains )
+ {
+ tmp.push ( shell.files[i] );
+ }
+ }
+
+ shell.files = tmp;
+ }
+ }
+
+ http2.send ( null );
+ shell.cmdOut.innerHTML = '';
+ }
+
+ shell.refreshPrompt ( false, false );
+ shell.auto_prompt_focus = true;
+ shell.auto_prompt_refresh = true;
+ }
+ }
+
+ http.send ( params );
+ shell.cmdOut.innerHTML = '';
+ }
+}
+
diff --git a/commands/su.json b/commands/su.json
index b1fc6f9..f5916ea 100644
--- a/commands/su.json
+++ b/commands/su.json
@@ -22,18 +22,22 @@
if ( shell.__first_cmd )
{
- shell.cmdOut.innerHTML = '
';
+ shell.cmdOut.innerHTML = '
Password: ' +
+ '
';
+
shell.__first_cmd = false;
+ } else {
+ shell.cmdOut.innerHTML = 'Password: ' +
+ '
';
}
shell.getPassword = this.getPassword;
shell.newuser = arg;
- shell.cmdOut.innerHTML += 'Password: ' +
- '
';
-
shell.auto_prompt_focus = false;
shell.auto_prompt_refresh = false;
diff --git a/commands/useradd.json b/commands/useradd.json
index b218b2f..15c9e76 100644
--- a/commands/useradd.json
+++ b/commands/useradd.json
@@ -39,6 +39,12 @@
{
shell.cmdOut.innerHTML = 'The passwords do not match';
} else {
+ if ( shell.newuser.match ( /[^0-9a-zA-Z_]/ ))
+ {
+ shell.cmdOut.innerHTML = 'The username contains invalid characters, out of the charset [0-9a-zA-Z_]';
+ return false;
+ }
+
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 );
@@ -60,6 +66,8 @@
shell.cmdOut.innerHTML = '';
}
+ shell.auto_prompt_focus = true;
+ shell.auto_prompt_refresh = true;
shell.refreshPrompt ( false, false );
}
}
@@ -67,10 +75,6 @@
http.send ( params );
shell.cmdOut.innerHTML = '';
}
-
- shell.auto_prompt_focus = true;
- shell.auto_prompt_refresh = true;
- shell.refreshPrompt ( false, false );
}
},
@@ -89,23 +93,35 @@
return "Usage: " + this.name + " <username>
\n";
}
+ if ( arg.match ( /[^0-9a-zA-Z_]/ ))
+ {
+ return "Invalid character(s) in the username, range [0-9a-zA-Z_] allowed
\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.cmdOut.innerHTML += 'Password: ' +
- '
' +
- 'Repeat password: ' +
- '
';
+ shell.__first_cmd = false;
+ } else {
+ shell.cmdOut.innerHTML = 'Password: ' +
+ '
' +
+ 'Repeat password: ' +
+ '
';
+ }
shell.auto_prompt_focus = false;
shell.auto_prompt_refresh = false;
diff --git a/modules/users/user_utils.php b/modules/users/user_utils.php
index b73bda1..95cb9a9 100644
--- a/modules/users/user_utils.php
+++ b/modules/users/user_utils.php
@@ -1,5 +1,7 @@
$value ) {
+ $items[] = __json_encode("$key") . ': ' . __json_encode($value);
+ }
+
+ $json = '{' . implode(', ', $items) . '}'."\n";
+ }
+ } elseif ( is_string ( $data )) {
+ # Escape non-printable or Non-ASCII characters.
+ # I also put the \\ character first, as suggested in comments on the 'addclashes' page.
+ #$string = '"' . addcslashes($data, "\\\"\n\r\t/" . chr(8) . chr(12)) . '"';
+ $string = '"' . $data . '"';
+ $json = '';
+ $len = strlen ($string);
+
+ # Convert UTF-8 to Hexadecimal Codepoints.
+ for ( $i = 0; $i < $len; $i++ ) {
+ $char = $string[$i];
+ $c1 = ord($char);
+
+ # Single byte;
+ if( $c1 <128 ) {
+ $json .= ($c1 > 31) ? $char : sprintf("\\u%04x", $c1);
+ continue;
+ }
+
+ # Double byte
+ $c2 = ord($string[++$i]);
+ if ( ($c1 & 32) === 0 ) {
+ $json .= sprintf("\\u%04x", ($c1 - 192) * 64 + $c2 - 128);
+ continue;
+ }
+
+ # Triple
+ $c3 = ord($string[++$i]);
+ if( ($c1 & 16) === 0 ) {
+ $json .= sprintf("\\u%04x", (($c1 - 224) <<12) + (($c2 - 128) << 6) + ($c3 - 128));
+ continue;
+ }
+
+ # Quadruple
+ $c4 = ord($string[++$i]);
+ if( ($c1 & 8 ) === 0 ) {
+ $u = (($c1 & 15) << 2) + (($c2>>4) & 3) - 1;
+
+ $w1 = (54<<10) + ($u<<6) + (($c2 & 15) << 2) + (($c3>>4) & 3);
+ $w2 = (55<<10) + (($c3 & 15)<<6) + ($c4-128);
+ $json .= sprintf("\\u%04x\\u%04x", $w1, $w2);
+ }
+ }
+ } else {
+ # int, floats, bools, null
+ $json = strtolower(var_export( $data, true ));
+ }
+
+ return $json;
+}
+
+function __mkdir ( $dir, $own_perms )
+{
+ include "../../system/files_json.php";
+
+ if ( !$files_json || strlen ( $files_json ) == 0 )
+ {
+ return 'mkdir: Error: Empty JSON file container';
+ }
+
+ if ( preg_match ( "@[^0-9a-zA-Z_\./\ ]@", $dir ))
+ {
+ return "mkdir: Invalid character(s) for a directory name out of range '[0-9a-zA-Z_./ ]'\n";
+ }
+
+ $has_perms = false;
+
+ if ( $own_perms )
+ {
+ if ( is_array ( $own_perms ))
+ {
+ $has_perms = true;
+ }
+ }
+
+ $user = getUser();
+ $json = json_decode ( $files_json, true );
+ $parent_dir = preg_replace ( '@/[^/]+$@', '', $dir );
+ $parent_dir_found = false;
+
+ if ( preg_match ( "/^\s*$/", $parent_dir ))
+ {
+ $parent_dir = '/';
+ }
+
+ for ( $i=0; $i < count ( $json ); $i++ )
+ {
+ $path = $json[$i]['path'];
+
+ if ( !$path || strlen ( $path ) == 0 )
+ {
+ continue;
+ }
+
+ if ( $path == $parent_dir )
+ {
+ $parent_dir_found = true;
+ $perms = getPerms ( $parent_dir );
+ $perms = json_decode ( $perms, true );
+
+ if ( $perms['write'] == false )
+ {
+ $dir = str_replace ( '<', '<', $dir );
+ $dir = str_replace ( '>', '>', $dir );
+ return "mkdir: Could not create directory $dir: Permission denied\n";
+ }
+ }
+
+ if ( $path == $dir )
+ {
+ $dir = str_replace ( '<', '<', $dir );
+ $dir = str_replace ( '>', '>', $dir );
+ return "mkdir: Could not create directory $dir: The file already exists\n";
+ }
+ }
+
+ if ( !$parent_dir_found )
+ {
+ $dir = str_replace ( '<', '<', $dir );
+ $dir = str_replace ( '>', '>', $dir );
+ return "mkdir: Could not create directory $dir: Parent directory not found\n";
+ }
+
+ $newdir = array();
+ $newdir['path'] = "$dir";
+ $newdir['type'] = 'directory';
+ $newdir['owner'] = ($has_perms) ? $own_perms['owner'] : "$user";
+ $newdir['can_read'] = ($has_perms) ? $own_perms['can_read'] : '@all';
+ $newdir['can_write'] = ($has_perms) ? $own_perms['can_write'] : "$user";
+
+ array_push ( $json, $newdir );
+
+ if ( !( $fp = fopen ( "../../system/files_json.php", "w" )))
+ {
+ return "mkdir: Unable to write on directories file\n";
+ }
+
+ fwrite ( $fp, "");
+ fclose ( $fp );
+ return "";
+}
+
+function __rmdir ( $dir )
+{
+ include "../../system/files_json.php";
+
+ if ( !$files_json || strlen ( $files_json ) == 0 )
+ {
+ return 'mkdir: Error: Empty JSON file container';
+ }
+
+ $user = getUser();
+ $json = json_decode ( $files_json, true );
+ $dir_found = false;
+
+ for ( $i=0; $i < count ( $json ) && !$dir_found; $i++ )
+ {
+ $path = $json[$i]['path'];
+
+ if ( !$path || strlen ( $path ) == 0 )
+ {
+ continue;
+ }
+
+ if ( $path == $dir )
+ {
+ $dir_found = true;
+ $perms = getPerms ( $dir );
+ $perms = json_decode ( $perms, true );
+
+ if ( $perms['write'] == false )
+ {
+ $dir = str_replace ( '<', '<', $dir );
+ $dir = str_replace ( '>', '>', $dir );
+ return "rmdir: Could not remove directory $dir: Permission denied\n";
+ } else {
+ array_splice ( $json, $i, 1 );
+ }
+ }
+ }
+
+ if ( !$dir_found )
+ {
+ $dir = str_replace ( '<', '<', $dir );
+ $dir = str_replace ( '>', '>', $dir );
+ return "mkdir: Could not remove directory $dir: File not found\n";
+ }
+
+ if ( !( $fp = fopen ( "../../system/files_json.php", "w" )))
+ {
+ return "mkdir: Unable to write on directories file\n";
+ }
+
+ fwrite ( $fp, "");
+ fclose ( $fp );
+ return "";
+}
+
?>
diff --git a/modules/users/users.php b/modules/users/users.php
index e31b4a3..0edf75f 100644
--- a/modules/users/users.php
+++ b/modules/users/users.php
@@ -3,6 +3,8 @@
include 'userlist.php';
include 'user_utils.php';
+global $sudo_cmd;
+
$action = $_REQUEST['action'];
if ( $action == null )
@@ -24,19 +26,19 @@ switch ( $action )
if ( preg_match ( '/[^a-zA-Z0-9_]/', $username ))
{
print "The username can only contain characters in the charset '[a-zA-Z0-9_]'\n";
- return 1;
+ return '';
}
- if ( preg_match ( '/[^a-zA-Z0-9]/', $password ) || strlen ( $password ) != 32 )
+ if ( preg_match ( '/[^a-fA-F0-9]/', $password ) || strlen ( $password ) != 32 )
{
print "The provided password is not a valid hash\n";
- return 1;
+ return '';
}
if ( !( $xml = new SimpleXMLElement ( $xmlcontent )))
{
print "Unable to open the users XML file\n";
- return 1;
+ return '';
}
for ( $i = 0; $i < count ( $xml->user ); $i++ )
@@ -44,7 +46,7 @@ switch ( $action )
if ( !strcasecmp ( $xml->user[$i]['name'], $username ))
{
print "The specified user already exists\n";
- return 1;
+ return '';
}
}
@@ -56,13 +58,22 @@ switch ( $action )
if ( !( $fp = fopen ( 'userlist.php', 'w' )))
{
print "Unable to add the specified user, unknown error\n";
- return 1;
+ return '';
}
fwrite ( $fp, 'asXML() . "\nXML;\n\n?>\n" );
fclose ( $fp );
- print 'User "'.$username.' successfully added, home directory set to "/home/'.$username."\"\n";
+ $perms = array();
+ $perms['owner'] = $username;
+ $perms['can_read'] = $username;
+ $perms['can_write'] = $username;
+
+ $GLOBALS['sudo_cmd'] = true;
+ print __mkdir ( '/home/'.$username, $perms )."
\n";
+ $GLOBALS['sudo_cmd'] = false;
+
+ print 'User "'.$username.'" successfully added, home directory set to "/home/'.$username."\"\n";
break;
case 'login':
@@ -77,13 +88,13 @@ switch ( $action )
if ( preg_match ( '/[^a-zA-Z0-9_]/', $username ))
{
print "The username can only contain characters in the charset '[a-zA-Z0-9_]'\n";
- return 1;
+ return '';
}
if ( !( $xml = new SimpleXMLElement ( $xmlcontent )))
{
print "Unable to open the users XML file\n";
- return 1;
+ return '';
}
for ( $i = 0; $i < count ( $xml->user ) && !$found; $i++ )
@@ -93,7 +104,7 @@ switch ( $action )
if ( strcasecmp ( $xml->user[$i]['pass'], $password ))
{
print "Wrong password provided for user '$username'\n";
- return 1;
+ return '';
} else {
$auth = md5 ( $xml->user[$i]['name'] . $xml->user[$i]['pass'] );
setcookie ( 'username', $xml->user[$i]['name'], 0, "/" );
@@ -106,7 +117,7 @@ switch ( $action )
}
print "Username not found: '$username'\n";
- return 1;
+ return '';
break;
case 'getuser':
@@ -129,13 +140,13 @@ switch ( $action )
if ( $cur_user != 'root' && $cur_user != $user )
{
print "You cannot change the password for the user '$user'\n";
- return 1;
+ return '';
}
if ( !( $xml = new SimpleXMLElement ( $xmlcontent )))
{
print "Unable to open the users XML file\n";
- return 1;
+ return '';
}
for ( $i = 0; $i < count ( $xml->user ); $i++ )
@@ -151,7 +162,7 @@ switch ( $action )
if ( $xml->user[$i]['pass'] != $old_pass )
{
print "The provided current password is wrong\n";
- return 1;
+ return '';
}
}
@@ -160,7 +171,7 @@ switch ( $action )
if ( !( $fp = fopen ( 'userlist.php', 'w' )))
{
print "Unable to change the password for the specified user, unknown error\n";
- return 1;
+ return '';
}
fwrite ( $fp, "asXML() . "\nXML;\n\n?>\n" );
@@ -183,7 +194,28 @@ switch ( $action )
print getPerms ( $res );
break;
+
+ case 'mkdir':
+ $dir = $_REQUEST['dir'];
+
+ if ( !$dir )
+ {
+ return false;
+ }
+
+ print __mkdir ( $dir, null );
+ break;
+
+ case 'rmdir':
+ $dir = $_REQUEST['dir'];
+
+ if ( !$dir )
+ {
+ return false;
+ }
+
+ print __rmdir ( $dir );
+ break;
}
?>
-
diff --git a/system/blash.json b/system/blash.json
index b247238..3883f99 100644
--- a/system/blash.json
+++ b/system/blash.json
@@ -63,8 +63,10 @@
"logout",
"ls",
"man",
+ "mkdir",
"passwd",
"pwd",
+ "rmdir",
"su",
"useradd",
"whoami"
diff --git a/system/files_json.php b/system/files_json.php
index c0c879e..b7b4026 100644
--- a/system/files_json.php
+++ b/system/files_json.php
@@ -2,157 +2,38 @@
$files_json = <<
+?>
\ No newline at end of file