diff --git a/blash.css b/blash.css
index c4f3b13..73b7ee5 100644
--- a/blash.css
+++ b/blash.css
@@ -49,6 +49,11 @@ span.directory
color : #2553ee;
}
+span.link
+{
+ color : #46a4ef;
+}
+
a
{
color : green;
diff --git a/commands/cat.json b/commands/cat.json
index fe7d212..6b65b49 100644
--- a/commands/cat.json
+++ b/commands/cat.json
@@ -32,6 +32,8 @@
if ( dir[i].href )
{
window.open ( dir[i].href );
+ } else if ( dir[i].link_to && dir[i].link_to.length > 0 ) {
+ return this.action ( dir[i].link_to );
} else if ( dir[i].content ) {
return '
' + dir[i].content + "
";
}
diff --git a/commands/cd.json b/commands/cd.json
index 5a85489..2ecf1cc 100644
--- a/commands/cd.json
+++ b/commands/cd.json
@@ -55,8 +55,9 @@
{
found = true;
- if ( shell.files[i].type != 'directory' )
- {
+ if ( shell.files[i].link_to && shell.files[i].link_to.length > 0 ) {
+ return this.action ( shell.files[i].link_to );
+ } else if ( shell.files[i].type != 'directory' ) {
return "cd: not a directory: " + arg + "
\n";
}
}
diff --git a/commands/ln.json b/commands/ln.json
new file mode 100644
index 0000000..09fbf34
--- /dev/null
+++ b/commands/ln.json
@@ -0,0 +1,120 @@
+{
+ "name" : "ln",
+
+ "info" : {
+ "syntax" : "ln <path or URL> <link name>",
+ "brief" : "Link a specified path inside the system or a URL to a new link file",
+ },
+
+ "action" : function ( arg )
+ {
+ var res = null;
+ var link = null;
+
+ if ( !arg || arg.length == 0 )
+ {
+ return "Usage: " + this.info.syntax + "
\n";
+ }
+
+ if ( arg.match ( /^\s*('|")([^'|"]+)('|")/ ))
+ {
+ res = RegExp.$2;
+ arg = arg.replace ( new RegExp ( '^\s*' + RegExp.$1 + RegExp.$2 + RegExp.$3 + '\s*' ), '' );
+ } else if ( arg.match ( /^\s*([^\s]+)/ )) {
+ res = RegExp.$1;
+ arg = arg.replace ( new RegExp ( '^\s*' + RegExp.$1 + '\s*' ), '' );
+ } else {
+ return "Usage: " + this.info.syntax + "
\n";
+ }
+
+ if ( !res || arg.length == 0 )
+ {
+ return "Usage: " + this.info.syntax + "
\n";
+ }
+
+ if ( arg.match ( /^\s*('|")([^'|"]+)('|")/ ))
+ {
+ link = RegExp.$2;
+ } else {
+ arg.match ( /^\s*(.*)$/ );
+ link = RegExp.$1;
+ }
+
+ var link_type = null;
+
+ if ( res.match ( /^[a-z0-9]+:\/\// ))
+ {
+ link_type = 'href';
+ } else {
+ link_type = 'local';
+ }
+
+ var users_php = window.location.href;
+ users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+ shell.auto_prompt_refresh = false;
+ link = shell.expandPath ( link );
+ params = 'action=link&resource=' + escape ( res ) + '&link=' + escape ( link ) + '&type=' + escape ( link_type );
+
+ 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;
+ }
+
+ 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.auto_prompt_refresh = true;
+ shell.refreshPrompt ( false, false );
+ }
+ }
+
+ http.send ( params );
+ shell.cmdOut.innerHTML = '';
+ }
+}
+
diff --git a/commands/ls.json b/commands/ls.json
index 56e421b..e79377a 100644
--- a/commands/ls.json
+++ b/commands/ls.json
@@ -51,6 +51,7 @@
"path" : RegExp.$1,
"type" : dir.type,
"href" : dir.href,
+ "link" : dir.link_to
});
}
}
@@ -114,6 +115,8 @@
if ( dirs[i].href && dirs[i].href.length > 0 )
{
out += '' + dirs[i].path + '*
';
+ } else if ( dirs[i].link && dirs[i].link.length > 0 ) {
+ out += '' + dirs[i].path + '@ -> ' + dirs[i].link + '
';
} else {
out += dirs[i].path + '
';
}
diff --git a/commands/users.json b/commands/users.json
new file mode 100644
index 0000000..c8ecbef
--- /dev/null
+++ b/commands/users.json
@@ -0,0 +1,40 @@
+{
+ "name" : "users",
+
+ "info" : {
+ "syntax" : "users",
+ "brief" : "Show the users on the system"
+ },
+
+ "action" : function ( arg )
+ {
+ var users_php = window.location.href;
+ users_php = users_php.replace ( /\/([a-zA-Z\.]+)$/, '/modules/users/users.php' );
+ params = 'action=list';
+ shell.auto_prompt_refresh = false;
+
+ 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;
+ }
+
+ shell.auto_prompt_refresh = true;
+ shell.refreshPrompt ( false, false );
+ }
+ }
+
+ http.send ( params );
+ shell.cmdOut.innerHTML = '';
+ }
+}
+
diff --git a/modules/users/user_utils.php b/modules/users/user_utils.php
index 03efa68..f89689f 100644
--- a/modules/users/user_utils.php
+++ b/modules/users/user_utils.php
@@ -259,6 +259,65 @@ function getPerms ( $resource )
return $response;
}
+function __link ( $resource, $link, $type )
+{
+ $ret = __touch ( $link, null );
+
+ if ( strlen ( $ret ) > 0 )
+ {
+ return $ret;
+ }
+
+ include "../../system/files_json.php";
+
+ if ( !$files_json || strlen ( $files_json ) == 0 )
+ {
+ return 'Error: Empty JSON file container';
+ }
+
+ $json = json_decode ( $files_json, true );
+
+ if ( !$json )
+ {
+ return 'Error: Empty JSON file container';
+ }
+
+ for ( $i=0; $i < count ( $json ); $i++ )
+ {
+ $path = $json[$i]['path'];
+
+ if ( !$path || strlen ( $path ) == 0 )
+ {
+ continue;
+ }
+
+ if ( $path == $link )
+ {
+ unset ( $json[$i]['content'] );
+
+ if ( $type == 'href' )
+ {
+ $json[$i]['href'] = $resource;
+ } else if ( $type == 'local' ) {
+ $json[$i]['link_to'] = $resource;
+ } else {
+ return "No link type specified (href|local)\n";
+ }
+
+ if ( !( $fp = fopen ( "../../system/files_json.php", "w" )))
+ {
+ return "Unable to write on directories file\n";
+ }
+
+ fwrite ( $fp, "");
+ fclose ( $fp );
+ return false;
+ }
+ }
+
+ return "Unable to link the resource";
+}
+
function __json_encode( $data ) {
if ( is_array ($data) || is_object ($data) ) {
$islist = is_array ($data) && ( empty ($data) || array_keys ($data) === range (0,count($data)-1) );
diff --git a/modules/users/users.php b/modules/users/users.php
index f354781..363992a 100644
--- a/modules/users/users.php
+++ b/modules/users/users.php
@@ -381,6 +381,19 @@ switch ( $action )
break;
+ case 'link':
+ $resource = $_REQUEST['resource'];
+ $link = $_REQUEST['link'];
+ $type = $_REQUEST['type'];
+
+ if ( !( $resource && $link && $type ))
+ {
+ return false;
+ }
+
+ print __link ( $resource, $link, $type );
+ break;
+
default :
print "Unallowed action\n";
break;
diff --git a/system/blash.js b/system/blash.js
index 2644fbb..7fcc977 100644
--- a/system/blash.js
+++ b/system/blash.js
@@ -392,7 +392,20 @@ function blash ()
} else if ( key == 76 && evt.ctrlKey ) {
// CTRL-l clears the screen
evt.preventDefault();
- this.refreshPrompt ( true, false );
+ this.refreshPrompt ( true, true );
+ this.cmdOut.innerHTML = '';
+
+ var text = ( this.json.promptText ) ? this.json.promptText : "[%n@%m %W] $ ";
+ text = this.unescapePrompt ( text, this.json.promptSequences );
+
+ var outDiv = document.createElement ( 'span' );
+ outDiv.innerHTML = text;
+ //outDiv.innerHTML = ((value.length > 0) ? value : '') +
+ // ( value.match ( /
\s*$/ ) ? '' : '
' ) + ((out.length > 0) ? (out + '
') : '') + text + (( shell.__first_cmd ) ? '
' : '' );
+ //outDiv.innerHTML = outDiv.innerHTML.replace ( /
\s*$/, '' );
+ this.window.insertBefore ( outDiv, document.getElementsByName ( "blashPrompt" )[0] );
+ // this.window.appendChild ( outDiv );
+
return false;
} else if ( key == 13 || key == 10 || ( key == 67 && evt.ctrlKey )) {
if ( this.prompt.value.length != 0 && ( key != 67 || !evt.ctrlKey ))
diff --git a/system/blash.json b/system/blash.json
index 73f265d..b420595 100644
--- a/system/blash.json
+++ b/system/blash.json
@@ -62,6 +62,7 @@
"find",
"grep",
"logout",
+ "ln",
"ls",
"man",
"mkdir",
diff --git a/system/default_stylerc.css b/system/default_stylerc.css
index 12a4c0f..73b7ee5 100644
--- a/system/default_stylerc.css
+++ b/system/default_stylerc.css
@@ -1,7 +1,3 @@
-/**
- * Default style for blash
- */
-
body
{
background-color : black;
@@ -53,6 +49,11 @@ span.directory
color : #2553ee;
}
+span.link
+{
+ color : #46a4ef;
+}
+
a
{
color : green;
diff --git a/system/files_json.php b/system/files_json.php
index 3f25ef4..0e395a7 100644
--- a/system/files_json.php
+++ b/system/files_json.php
@@ -10,7 +10,6 @@ $files_json = <<