Merge pull request #8 from coderaiser/dev

Cloud Commander v0.6.0
This commit is contained in:
coderaiser 2013-11-08 02:51:54 -08:00
commit 994171baf7
42 changed files with 1415 additions and 987 deletions

830
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -225,4 +225,4 @@
- Изминен принцип работы функции clickProcessing в меню, теперь он гораздо проще.
- Произведен тотальный рефакторинг в файле commander.js, теперь там только генерация.
структуры каталогов в формате json.
- добавлен обьект RESTfull в DOM модуль для упрощения работы с CloudCmd REST API.
- добавлен обьект RESTful в DOM модуль для упрощения работы с CloudCmd REST API.

49
HELP.md
View file

@ -1,19 +1,25 @@
Cloud Commander v0.5.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
Cloud Commander v0.6.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
===============
###[Main][MainURL] [Blog][BlogURL] [Demo][DemoURL]
###[Main][MainURL] [Blog][BlogURL] Live(![IO][IO_LIVE_IMG] [IO][IOURL], ![JitSu][JitSu_LIVE_IMG] [JitSu][JitSuURL], ![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL] ![RunKite][RunKite_LIVE_IMG] [RunKite][RunKiteURL])
[NPMIMGURL]: https://badge.fury.io/js/cloudcmd.png
[BuildStatusIMGURL]: https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master
[DependencyStatusIMGURL]: https://gemnasium.com/coderaiser/cloudcmd.png
[FlattrIMGURL]: http://api.flattr.com/button/flattr-badge-large.png
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png?downloads=true&&stars
[NPMURL]: https://npmjs.org/package/cloudcmd
[NPMURL]: https://npmjs.org/package/cloudcmd "npm"
[BuildStatusURL]: http://travis-ci.org/coderaiser/cloudcmd "Build Status"
[DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status"
[FlattrURL]: https://flattr.com/submit/auto?user_id=coderaiser&url=github.com/coderaiser/cloudcmd&title=cloudcmd&language=&tags=github&category=software "flattr"
[NPM_INFO_URL]: https://npmjs.org/package/cloudcmd "npm"
[MainURL]: http://cloudcmd.io "Main"
[BlogURL]: http://blog.cloudcmd.io "Blog"
[DemoURL]: http://io.cloudcmd.io "Demo"
[IOURL]: http://io.cloudcmd.io "IO"
[JitSuURL]: http://cloudcmd.jit.su "JitSu"
[HerokuURL]: http://cloudcmd.herokuapp.com/ "Heroku"
[RunKiteURL]: http://cloudcmd.apps.runkite.com/ "RunKite"
[IO_LIVE_IMG]: http://status-ok.cloudcmd.io/host/io.cloudcmd.io "IO"
[JitSu_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.jit.su "JitSu"
[HEROKU_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.herokuapp.com "Heroku"
[RunKite_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.apps.runkite.com/ "RunKite"
**Cloud Commander** - cloud file manager with console and editor.
@ -32,10 +38,11 @@ Benefits
Install
---------------
[![NPM_INFO][NPM_INFO_IMG]][NPM_INFO_URL]
[![NPM_INFO][NPM_INFO_IMG]][NPMURL]
Installing **Cloud Commander** is very simple.
All you need is
- install [node.js](http://nodejs.org/ "node.js")
- [download](https://github.com/coderaiser/cloudcmd/archive/master.zip)
and unpack or just clone repository from github:
@ -46,6 +53,7 @@ and unpack or just clone repository from github:
node cloudcmd
```
or install in npm:
```
npm i cloudcmd -g
cloudcmd
@ -63,6 +71,7 @@ Hot keys
- **F7** - new dir
- **F8, Delete** - remove current file
- **F9** - menu
- **F10** - config
- **Ctrl + r** - reload dir content
- **Ctrl + d** - clear local cache (wich contains dir contents)
- **Alt + q** - disable key bindings
@ -82,7 +91,7 @@ Hot keys
Edit
---------------
[Demo](http://io.cloudcmd.io/fs/etc#/edit/passwd "Edit")
![Edit](/img/screenshot/edit.png "Edit")
![Edit](/img/screen/edit.png "Edit")
###Hot keys
- **F4** - open
@ -94,16 +103,25 @@ For more details see [Ace keyboard shortcuts](https://github.com/ajaxorg/ace/wik
Console
---------------
[Demo](http://io.cloudcmd.io#/console "Console")
![Console](/img/screenshot/console.png "Console")
![Console](/img/screen/console.png "Console")
###Hot keys
- **~** - open
- **Esc** - close
Config
---------------
[Demo](http://io.cloudcmd.io#/config "Config")
![Console](/img/screen/config.png "Config")
###Hot keys
- **F10** - open
- **Esc** - close
Menu
---------------
[Demo](http://io.cloudcmd.io#/menu "Menu")
![Menu](/img/screenshot/menu.png "Menu")
![Menu](/img/screen/menu.png "Menu")
Right mouse click button shows context menu with items:
- View
- Edit
@ -200,7 +218,7 @@ in your list they could differ).
```
###nginx
Get [nginx](http://nginx.org/ "nginx"). On linux it could be done like that
Get [nginx](http://nginx.org/ "nginx"). On linux it could be done this way:
```sh
sudo apt-get install nginx #for ubuntu and debian
@ -324,6 +342,8 @@ so to get it you should type a couple more commands:
Version history
---------------
- *2013.11.08*, **[v0.6.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.6.0.zip)**
- *2013.10.17*, **[v0.5.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.5.0.zip)**
- *2013.09.27*, **[v0.4.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.4.0.zip)**
- *2013.08.01*, **[v0.3.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.3.0.zip)**
@ -337,7 +357,7 @@ Version history
- *2012.07.19*, **[v0.1.3](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.3.zip)**
- *2012.07.14*, **[v0.1.2](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.2.zip)**
- *2012.07.11*, **[v0.1.1](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.1.zip)**
- *2012.00.00*, **[v0.1.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.0.zip)**
- *2012.07.09*, **[v0.1.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.0.zip)**
License
---------------
@ -345,5 +365,8 @@ MIT [license](LICENSE "license").
Special Thanks
---------------
- [Polietilena](http://polietilena.github.io/ "Polietilena") for [logo](img/logo/cloudcmd.png "logo") and [favicon](img/favicon/favicon.png "favicon").
- [Elec-ua](https://github.com/elec-ua) for [ru](http://ru.cloudcmd.io "Cloud Commander in Russian") and [ua](http://ua.cloudcmd.io "Cloud Commander in Ukrainian") translations.
- [Polietilena](http://polietilena.github.io/ "Polietilena") for [logo](img/logo/cloudcmd.png "logo") and [favicon](img/favicon/favicon.png "favicon");
- [Elec-ua](https://github.com/elec-ua)
- [ru](http://ru.cloudcmd.io "Cloud Commander in Russian") and [ua](http://ua.cloudcmd.io "Cloud Commander in Ukrainian") translations;
- config [template](html/config.html) and [style](css/config.css);

1
Procfile Normal file
View file

@ -0,0 +1 @@
web: node cloudcmd.js

View file

@ -1,19 +1,25 @@
Cloud Commander v0.5.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
Cloud Commander v0.6.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
===============
###[Main][MainURL] [Blog][BlogURL] [Demo][DemoURL]
###[Main][MainURL] [Blog][BlogURL] Live(![IO][IO_LIVE_IMG] [IO][IOURL], ![JitSu][JitSu_LIVE_IMG] [JitSu][JitSuURL], ![Heroku][Heroku_LIVE_IMG] [Heroku][HerokuURL] ![RunKite][RunKite_LIVE_IMG] [RunKite][RunKiteURL])
[NPMIMGURL]: https://badge.fury.io/js/cloudcmd.png
[BuildStatusIMGURL]: https://secure.travis-ci.org/coderaiser/cloudcmd.png?branch=master
[DependencyStatusIMGURL]: https://gemnasium.com/coderaiser/cloudcmd.png
[FlattrIMGURL]: http://api.flattr.com/button/flattr-badge-large.png
[NPM_INFO_IMG]: https://nodei.co/npm/cloudcmd.png?downloads=true&&stars
[NPMURL]: https://npmjs.org/package/cloudcmd
[NPMURL]: https://npmjs.org/package/cloudcmd "npm"
[BuildStatusURL]: http://travis-ci.org/coderaiser/cloudcmd "Build Status"
[DependencyStatusURL]: https://gemnasium.com/coderaiser/cloudcmd "Dependency Status"
[FlattrURL]: https://flattr.com/submit/auto?user_id=coderaiser&url=github.com/coderaiser/cloudcmd&title=cloudcmd&language=&tags=github&category=software "flattr"
[NPM_INFO_URL]: https://npmjs.org/package/cloudcmd "npm"
[MainURL]: http://cloudcmd.io "Main"
[BlogURL]: http://blog.cloudcmd.io "Blog"
[DemoURL]: http://io.cloudcmd.io "Demo"
[IOURL]: http://io.cloudcmd.io "IO"
[JitSuURL]: http://cloudcmd.jit.su "JitSu"
[HerokuURL]: http://cloudcmd.herokuapp.com/ "Heroku"
[RunKiteURL]: http://cloudcmd.apps.runkite.com/ "RunKite"
[IO_LIVE_IMG]: http://status-ok.cloudcmd.io/host/io.cloudcmd.io "IO"
[JitSu_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.jit.su "JitSu"
[HEROKU_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.herokuapp.com "Heroku"
[RunKite_LIVE_IMG]: http://status-ok.cloudcmd.io/host/cloudcmd.apps.runkite.com/ "RunKite"
**Cloud Commander** - cloud file manager with console and editor.

View file

@ -1,4 +1,4 @@
(function(){
(function() {
'use strict';
var DIR = __dirname + '/',
@ -49,18 +49,6 @@
lData = pData.data,
lAdditional = pData.additional;
/*
* если выбрана опция минимизировать скрипты
* меняем в index.html обычные css на
* минифицированый
*/
if (Minify.allowed) {
lPath = '/' + Util.removeStr(Minify.MinFolder, DIR);
lReplace = '<link rel=stylesheet href="/css/reset.css">';
lData = Util.removeStr(lData, lReplace)
.replace('/css/style.css', lPath + 'all.min.css');
}
if (!Config.appcache)
lData = Util.removeStr(lData, [
/* min */
@ -86,7 +74,7 @@
/**
* init and process of appcache if it allowed in config
*/
function appCacheProcessing(){
function appCacheProcessing() {
var lFONT_REMOTE = '//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff',
lFONT_LOCAL = './font/DroidSansMono.woff',
lJQUERY_REMOTE = '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js',
@ -96,54 +84,19 @@
lFiles[0][lFONT_REMOTE] = lFONT_LOCAL;
lFiles[1][lJQUERY_REMOTE] = lJQUERY_LOCAL;
if (Config.minify)
lFiles.push('node_modules/minify/min/all.min.css');
AppCache.addFiles(lFiles);
AppCache.createManifest();
}
/**
* Функция минимизирует css/js/html
* если установлены параметры минимизации
*/
function minimize(pAllowed){
var lOptimizeParams = [],
lStyles = [{}, {}],
lStyleCSS = DIR + 'css/style.css',
lResetCSS = DIR + 'css/reset.css',
lCSSOptions = {
img : true,
merge : true
};
if (pAllowed) {
lOptimizeParams.push(LIBDIR + 'client.js');
lOptimizeParams.push(INDEX);
lStyles[0][lStyleCSS] = lCSSOptions;
lStyles[1][lResetCSS] = lCSSOptions;
lOptimizeParams.push(lStyles[0]);
lOptimizeParams.push(lStyles[1]);
}
if (lOptimizeParams.length)
Minify.optimize(lOptimizeParams, {
force: true
});
}
/**
* rest interface
* @pParams pConnectionData {request, responce}
*/
function rest(pConnectionData){
function rest(pConnectionData) {
return Util.exec(main.rest, pConnectionData);
}
function init(){
function init() {
var lServerDir, lArg, lParams, lFiles;
if (update)
@ -161,94 +114,72 @@
process.chdir(lServerDir);
}
Util.log('server dir: ' + lServerDir);
Util.log('reading configuration file config.json...');
Util.log('server dir: ' + lServerDir);
if (Config) {
Util.log('config.json readed');
/* if command line parameter testing resolved
* setting config to testing, so server
* not created, just init and
* all logs writed to screen */
lArg = process.argv;
lArg = lArg[lArg.length - 1];
if ( lArg === 'test' || lArg === 'test\r') {
Util.log(process.argv);
Config.server = false;
}
if (Config.logs) {
Util.log('log param setted up in config.json\n' +
'from now all logs will be writed to log.txt');
writeLogsToFile();
}
if (Config.server)
Util.tryCatchLog(function(){
fs.watch(CONFIG_PATH, function(){
/* every catch up - calling twice */
setTimeout(function() {
readConfig();
}, 1000);
});
});
lParams = {
appcache : appCacheProcessing,
minimize : minimize,
rest : rest,
route : route
},
lFiles = [FILE_TMPL, PATH_TMPL];
if (Config.ssl)
lFiles.push(CA, KEY, CERT);
main.readFiles(lFiles, function(pErrors, pFiles){
if (pErrors)
Util.log(pErrors);
else {
FileTemplate = pFiles[FILE_TMPL].toString();
PathTemplate = pFiles[PATH_TMPL].toString();
if (Config.ssl)
lParams.ssl = {
ca : pFiles[CA],
key : pFiles[KEY],
cert : pFiles[CERT]
};
server.start(lParams);
}
});
/* if command line parameter testing resolved
* setting config to testing, so server
* not created, just init and
* all logs writed to screen */
lArg = process.argv;
lArg = lArg[lArg.length - 1];
if ( lArg === 'test' || lArg === 'test\r') {
Util.log(process.argv);
Config.server = false;
}
else
Util.log('read error: config.json');
if (Config.logs) {
Util.log('log param setted up in config.json\n' +
'from now all logs will be writed to log.txt');
writeLogsToFile();
}
lParams = {
appcache : appCacheProcessing,
rest : rest,
route : route
},
lFiles = [FILE_TMPL, PATH_TMPL];
if (Config.ssl)
lFiles.push(CA, KEY, CERT);
main.readFiles(lFiles, function(pErrors, pFiles) {
if (pErrors)
Util.log(pErrors);
else {
FileTemplate = pFiles[FILE_TMPL].toString();
PathTemplate = pFiles[PATH_TMPL].toString();
if (Config.ssl)
lParams.ssl = {
ca : pFiles[CA],
key : pFiles[KEY],
cert : pFiles[CERT]
};
server.start(lParams);
}
});
}
function readConfig(pCallBack){
fs.readFile(CONFIG_PATH, function(pError, pData){
if (!pError){
Util.log('config: readed');
function readConfig(pCallBack) {
fs.readFile(CONFIG_PATH, function(pError, pData) {
var msg, status, str, readed;
if (pError)
status = 'error';
else {
status = 'ok';
str = pData.toString(),
readed = Util.parseJSON(str);
var lStr = pData.toString(),
lReadedConf = Util.parseJSON(lStr);
if (!Config.minify)
main.config = Config = lReadedConf;
Util.tryCatchLog(function(){
Config.minify = lReadedConf.minify;
Config.cache = lReadedConf.cache;
Minify.setAllowed(Config.minify);
});
main.config = Config = readed;
}
else
Util.log(pError);
msg = CloudFunc.formatMsg('read', 'config', status);
Util.log(msg);
Util.exec(pCallBack);
});
@ -257,13 +188,13 @@
/**
* routing of server queries
*/
function route(pParams){
function route(pParams) {
var lRet = main.checkParams(pParams);
if (lRet){
if (lRet) {
var p = pParams;
if ( Util.strCmp(p.name, ['/auth', '/auth/github']) ){
if ( Util.strCmp(p.name, ['/auth', '/auth/github']) ) {
Util.log('* Routing' +
'-> ' + p.name);
@ -280,14 +211,14 @@
return lRet;
}
function sendCommanderContent(pParams){
function sendCommanderContent(pParams) {
var p, lRet = main.checkParams(pParams);
if (lRet){
if (lRet) {
p = pParams;
p.name = Util.removeStrOneTime(p.name, CloudFunc.FS) || main.SLASH;
fs.stat(p.name, function(pError, pStat){
fs.stat(p.name, function(pError, pStat) {
if (!pError)
if ( pStat.isDirectory() )
processCommanderContent(pParams);
@ -301,22 +232,22 @@
return lRet;
}
function processCommanderContent(pParams){
function processCommanderContent(pParams) {
var lRet = main.checkParams(pParams);
if (lRet){
if (lRet) {
var p = pParams;
main.commander.getDirContent(p.name, function(pError, pJSON){
if (!pError){
main.commander.getDirContent(p.name, function(pError, pJSON) {
if (!pError) {
var lQuery = main.getQuery(p.request);
if ( Util.isContainStr(lQuery, 'json') ){
if ( Util.isContainStr(lQuery, 'json') ) {
p.data = Util.stringifyJSON(pJSON);
p.name +='.json';
main.sendResponse(p);
main.sendResponse(p, null, true);
}
else{ /* get back html*/
p.name = Minify.allowed ? Minify.getName(INDEX) : INDEX;
fs.readFile(p.name, function(pError, pData){
fs.readFile(p.name, function(pError, pData) {
if (!pError) {
var lPanel = CloudFunc.buildFromJSON(pJSON, FileTemplate, PathTemplate),
lList = '<ul id=left class=panel>' + lPanel + '</ul>' +
@ -325,7 +256,7 @@
main.sendResponse(p, indexProcessing({
additional : lList,
data : pData.toString(),
}));
}), true);
}
else
main.sendError(pParams, pError);

57
css/config.css Normal file
View file

@ -0,0 +1,57 @@
.config {
white-space: normal;
}
.list li{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.config .form-control{
padding: 0 12px;
font-size: 16px;
line-height: 1.428571429;
color: #555555;
background-color: #ffffff;
border: 1px solid #cccccc;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
}
.config .form-control:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 1px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 1px rgba(102, 175, 233, 0.6);
}
.config .form-control:-moz-placeholder {
color: #999999;
}
.config .form-control::-moz-placeholder {
color: #999999;
}
.config .form-control:-ms-input-placeholder {
color: #999999;
}
.config .form-control::-webkit-input-placeholder {
color: #999999;
}
.config .list {
margin : 5%;
text-align : left;
}
.config .border{
width : 300px;
margin : 10% auto;
}

View file

@ -10,7 +10,10 @@
html{
color: #222;
}
body { margin: 0; font-size: 1em; line-height: 1.4; }
body {
margin: 0;
}
/*
* Remove text-shadow in selection highlight: h5bp.com/i

View file

@ -92,7 +92,7 @@ body {
}
.cmd-button {
width: 8%;
width: 9%;
margin: 20px 2px 0 2px;
overflow: hidden;
color: rgb(49,123,249);

16
html/config.html Normal file
View file

@ -0,0 +1,16 @@
<div class="border">
<ul class="list" >
<li><span><input type="checkbox" id="appcache" {{ appcache }} ></input></span><label for="appcache"> App cache</label></li>
<li><span><input type="checkbox" id="analytics" {{ analytics }} ></input></span><label for="analytics"> Analytics</label></li>
<li><span><input type="checkbox" id="localStorage" {{ localStorage }} ></input></span><label for="localStorage"> Local Storage</label></li>
<li><span><input type="checkbox" id="minify" {{ minify }} ></input></span><label for="minify"> Minify</label></li>
<li><span><input type="checkbox" id="online" {{ online }} ></input></span><label for="online"> Online</label></li>
<li><span><input type="checkbox" id="cache" {{ cache }} ></input></span><label for="cache"> Cache</label></li>
<li><span><input type="checkbox" id="logs" {{ logs }} ></input></span><label for="logs"> Logs</label></li>
<li><span><input type="checkbox" id="show_keys_panel" {{ show_keys_panel }}></input></span><label for="show_keys_panel"> Show keys panel</label></li>
<li><span><input type="checkbox" id="socket" {{ socket }} ></input></span><label for="socket"> Socket</label></li>
<li><input class="form-control" placeholder="Port" id="port" value="{{ port }}" title="Port"></input></li>
<li><input class="form-control" placeholder="Ssl Port" id="sslPort" value="{{ sslPort }}" title="SSL Port"></input></li>
<li><span><input type="checkbox" id="ssl" {{ ssl }} ></input></span><label for="ssl"> SSL</label></li>
</div>
</div>

View file

@ -26,6 +26,7 @@
<button id=f7 class=cmd-button>F7 - make dir</button>
<button id=f8 class=cmd-button>F8 - delete</button>
<button id=f9 class=cmd-button>F9 - menu</button>
<button id=f10 class=cmd-button>F10 - config</button>
<button id=~ class=cmd-button>~ - console</button>
</div>
<script src=/lib/util.js></script>

BIN
img/screen/config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
img/screen/console.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
img/screen/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
img/screen/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -3,6 +3,7 @@
"menu",
"view",
"help",
"config",
"console", {
"name": "storage",
"data": [{

View file

@ -4,7 +4,7 @@
*/
var Util, DOM, CloudFunc, CloudCmd;
(function(Util, DOM){
(function(Util, DOM) {
'use strict';
var Key, Config, Modules, FileTemplate, PathTemplate, Listeners,
@ -19,7 +19,7 @@ var Util, DOM, CloudFunc, CloudCmd;
MIN_ONE_PANEL_WIDTH : 1155,
OLD_BROWSER : false,
HOST : (function(){
HOST : (function() {
var lLocation = document.location;
return lLocation.protocol + '//' + lLocation.host;
})()
@ -32,8 +32,8 @@ var Util, DOM, CloudFunc, CloudCmd;
* @param pLink - ссылка
* @param pNeedRefresh - необходимость обязательной загрузки данных с сервера
*/
CloudCmd.loadDir = function(pLink, pNeedRefresh){
return function(pEvent){
CloudCmd.loadDir = function(pLink, pNeedRefresh) {
return function(pEvent) {
/* показываем гиф загрузки возле пути папки сверху
* ctrl+r нажата? */
@ -43,7 +43,7 @@ var Util, DOM, CloudFunc, CloudCmd;
lLink += '?json';
if(lLink || lCurrentLink.target !== '_blank'){
if (lLink || lCurrentLink.target !== '_blank') {
DOM.Images.showLoad(pNeedRefresh ? {top:true} : null);
/* загружаем содержимое каталога */
@ -61,13 +61,13 @@ var Util, DOM, CloudFunc, CloudCmd;
* в верх по файловой структуре
* @param pDirName - имя каталога с которого мы пришли
*/
function currentToParent(pDirName){
function currentToParent(pDirName) {
var lRootDir;
/* убираем слэш с имени каталога */
pDirName = Util.removeStr(pDirName, '/');
lRootDir = DOM.getCurrentFileByName(pDirName);
if (lRootDir){
if (lRootDir) {
DOM.setCurrentFile(lRootDir);
DOM.scrollIntoViewIfNeeded(lRootDir, true);
}
@ -77,36 +77,36 @@ var Util, DOM, CloudFunc, CloudCmd;
* function load modules
* @pParams = {name, path, func, dobefore, arg}
*/
function loadModule(pParams){
if(pParams){
function loadModule(pParams) {
if (pParams) {
var lName = pParams.name,
lPath = pParams.path,
lFunc = pParams.func,
lDoBefore = pParams.dobefore;
if( Util.isString(pParams) )
if ( Util.isString(pParams) )
lPath = pParams;
if(lPath && !lName){
if (lPath && !lName) {
lName = Util.getStrBigFirst(lPath);
lName = Util.removeStr(lName, '.js');
var lSlash = lName.indexOf('/');
if(lSlash > 0){
if (lSlash > 0) {
var lAfterSlash = lName.substr(lSlash);
lName = Util.removeStr(lName, lAfterSlash);
}
}
if( !Util.isContainStr(lPath, '.js') )
if ( !Util.isContainStr(lPath, '.js') )
lPath += '.js';
if(!CloudCmd[lName])
CloudCmd[lName] = function(pArg){
if (!CloudCmd[lName])
CloudCmd[lName] = function(pArg) {
Util.exec(lDoBefore);
return DOM.jsload(CloudCmd.LIBDIRCLIENT + lPath, lFunc ||
function(){
function() {
Util.exec(CloudCmd[lName].init, pArg);
});
};
@ -117,7 +117,7 @@ var Util, DOM, CloudFunc, CloudCmd;
* выполняет весь функционал по
* инициализации
*/
CloudCmd.init = function(){
CloudCmd.init = function() {
var lCallBack, lFunc, lHeight;
/* устанавливаем размер высоты таблицы файлов
* исходя из размеров разрешения экрана
@ -141,14 +141,14 @@ var Util, DOM, CloudFunc, CloudCmd;
'}'
});
lCallBack = function(){
lCallBack = function() {
Util.loadOnLoad([
Util.retExec(CloudCmd.route, location.hash),
Util.retFunc(CloudCmd.route, location.hash),
baseInit,
initModules,
]);
},
lFunc = function(pCallBack){
lFunc = function(pCallBack) {
CloudCmd.OLD_BROWSER = true;
var lSrc = CloudCmd.LIBDIRCLIENT + 'polyfill.js';
@ -160,7 +160,7 @@ var Util, DOM, CloudFunc, CloudCmd;
Util.ifExec(document.body.scrollIntoViewIfNeeded, lCallBack, lFunc);
};
CloudCmd.route = function(pPath){
CloudCmd.route = function(pPath) {
var lQuery, lModule, lFile, lCurrent, lMsg;
if (pPath.length > 0) {
@ -181,11 +181,11 @@ var Util, DOM, CloudFunc, CloudCmd;
}
};
function initModules(pCallBack){
function initModules(pCallBack) {
loadModule({
/* привязываем клавиши к функциям */
path : 'key.js',
func : function(){
func : function() {
Key = CloudCmd.Key;
Key.bind();
}
@ -214,14 +214,14 @@ var Util, DOM, CloudFunc, CloudCmd;
for (i = 0, n = pModules.length; i < n ; i++) {
var lModule = pModules[i];
if( Util.isString(lModule) )
if ( Util.isString(lModule) )
lLoad(null, lModule, lDoBefore[lModule]);
}
var lStorageObj = Util.findObjByNameInArr( pModules, lStorage ),
lMod = Util.getNamesFromObjArray( lStorageObj );
for (i = 0, n = lMod.length; i < n; i++){
for (i = 0, n = lMod.length; i < n; i++) {
var lName = lMod[i],
lPath = lStorage + '/_' + lName.toLowerCase();
@ -270,7 +270,7 @@ var Util, DOM, CloudFunc, CloudCmd;
/* выделяем строку с первым файлом */
var lFmHeader = DOM.getByClass('fm-header');
if(lFmHeader && lFmHeader[0]){
if (lFmHeader && lFmHeader[0]) {
var lCurrent = lFmHeader[0].nextSibling;
DOM.setCurrentFile(lCurrent);
}
@ -282,18 +282,17 @@ var Util, DOM, CloudFunc, CloudCmd;
CloudCmd.Key();
}
function getSystemFile(pGlobal, pURL){
function getSystemFile(pGlobal, pURL) {
function lGetSysFile(pCallBack){
Util.ifExec(pGlobal, pCallBack, function(pCallBack){
if(!pGlobal)
DOM.ajax({
url : pURL,
success : function(pLocal){
pGlobal = pLocal;
Util.exec(pCallBack, pLocal);
}
});
function lGetSysFile(pCallBack) {
Util.ifExec(pGlobal, pCallBack, function(pCallBack) {
DOM.ajax({
url : pURL,
success : function(pLocal) {
pGlobal = pLocal;
Util.exec(pCallBack, pLocal);
}
});
});
}
@ -307,20 +306,20 @@ var Util, DOM, CloudFunc, CloudCmd;
CloudCmd.getFileTemplate = getSystemFile(FileTemplate, CloudCmd.HTMLDIR + 'file.html');
CloudCmd.getPathTemplate = getSystemFile(PathTemplate, CloudCmd.HTMLDIR + 'path.html');
CloudCmd.execFromModule = function(pModuleName, pFuncName, pParams){
CloudCmd.execFromModule = function(pModuleName, pFuncName, pParams) {
var lObject = CloudCmd[pModuleName];
Util.ifExec(Util.isObject(lObject),
function(){
function() {
var lObj = CloudCmd[pModuleName];
Util.exec( lObj[pFuncName], pParams);
},
function(pCallBack){
function(pCallBack) {
Util.exec(lObject, pCallBack);
});
};
CloudCmd.refresh = function(pCurrent){
CloudCmd.refresh = function(pCurrent) {
var lNEEDREFRESH = true,
lPanel = pCurrent && pCurrent.parentElement,
lPath = DOM.getCurrentDirPath(lPanel),
@ -338,8 +337,8 @@ var Util, DOM, CloudFunc, CloudCmd;
* @param pOptions
* { refresh, nohistory } - необходимость обновить данные о каталоге
*/
CloudCmd.ajaxLoad = function(pPath, pOptions){
if(!pOptions)
CloudCmd.ajaxLoad = function(pPath, pOptions) {
if (!pOptions)
pOptions = {};
/* Отображаем красивые пути */
@ -350,12 +349,12 @@ var Util, DOM, CloudFunc, CloudCmd;
lOldURL = window.location.pathname;
if(lCleanPath === lSLASH)
if (lCleanPath === lSLASH)
lNOJSPath = lSLASH;
Util.log ('reading dir: "' + lCleanPath + '";');
if(!pOptions.nohistory)
if (!pOptions.nohistory)
DOM.setHistory(lNOJSPath, null, lNOJSPath);
DOM.setTitle( CloudFunc.getTitle(lCleanPath) );
@ -369,10 +368,10 @@ var Util, DOM, CloudFunc, CloudCmd;
* перезагружаемся
*/
var lRet = pOptions.refresh;
if(!lRet){
if (!lRet) {
var lJSON = Cache.get(lCleanPath);
if (lJSON){
if (lJSON) {
lJSON = Util.parseJSON(lJSON);
createFileTable(lPanel, lJSON);
}
@ -380,17 +379,17 @@ var Util, DOM, CloudFunc, CloudCmd;
lRet = true;
}
if(lRet)
if (lRet)
DOM.getCurrentFileContent({
url : lFSPath,
dataType: 'json',
error : function(){
error : function() {
DOM.setHistory(lOldURL, null, lOldURL);
},
success : function(pData){
success : function(pData) {
createFileTable(lPanel, pData);
/* переводим таблицу файлов в строку, для *
@ -400,7 +399,7 @@ var Util, DOM, CloudFunc, CloudCmd;
/* если размер данных не очень бошьой *
* сохраняем их в кэше */
if(lJSON_s.length < 50000 )
if (lJSON_s.length < 50000 )
Cache.set(lCleanPath, lJSON_s);
}
});
@ -411,7 +410,7 @@ var Util, DOM, CloudFunc, CloudCmd;
* @param pEleme - родительский элемент
* @param pJSON - данные о файлах
*/
function createFileTable(pElem, pJSON){
function createFileTable(pElem, pJSON) {
var lElem = DOM.getById(pElem),
/* getting current element if was refresh */
lPath = DOM.getByClass('path', lElem),
@ -438,28 +437,28 @@ var Util, DOM, CloudFunc, CloudCmd;
/* если нажали на ссылку на верхний каталог*/
var lFound;
/* searching current file */
if(lWasRefresh_b){
if (lWasRefresh_b) {
var n = lElem.childNodes.length;
for(i = 2; i < n ; i++){
for(i = 2; i < n ; i++) {
var lVarCurrent = lElem.childNodes[i],
lVarName = DOM.getCurrentName(lVarCurrent);
lFound = lVarName === lName;
if(lFound){
if (lFound) {
lCurrent = lElem.childNodes[i];
break;
}
}
}
if(!lFound) /* .. */
if (!lFound) /* .. */
lCurrent = lElem.childNodes[2];
DOM.setCurrentFile(lCurrent);
Listeners.changeLinks(pElem);
if(lName === '..' && lDir !== '/')
if (lName === '..' && lDir !== '/')
currentToParent(lDir);
});
}
@ -468,7 +467,7 @@ var Util, DOM, CloudFunc, CloudCmd;
* Функция генерирует JSON из html-таблицы файлов и
* используеться при первом заходе в корень
*/
function getJSONfromFileTable(){
function getJSONfromFileTable() {
var lLeft = DOM.getById('left'),
lPath = DOM.getByClass('path')[0].textContent,
@ -487,7 +486,7 @@ var Util, DOM, CloudFunc, CloudCmd;
*/
/* пропускам Path и Header*/
for(i = 2, n = lLI.length; i < n; i++){
for(i = 2, n = lLI.length; i < n; i++) {
var lCurrent = lLI[i],
lName = DOM.getCurrentName(lCurrent),
lSize = DOM.getCurrentSize(lCurrent),
@ -495,7 +494,7 @@ var Util, DOM, CloudFunc, CloudCmd;
lMode = DOM.getCurrentMode(lCurrent);
lMode = CloudFunc.getNumericPermissions(lMode);
if(lName !== '..')
if (lName !== '..')
lFileTable[ j++ ] = {
name: lName,
size: lSize,
@ -505,5 +504,5 @@ var Util, DOM, CloudFunc, CloudCmd;
return Util.stringifyJSON(lFileTable);
}
DOM.Events.addOneTime('load', CloudCmd.init);
DOM.Events.addOnce('load', CloudCmd.init);
})(Util, DOM);

152
lib/client/config.js Normal file
View file

@ -0,0 +1,152 @@
var CloudCmd, Util, DOM;
(function(CloudCmd, Util, DOM){
'use strict';
CloudCmd.Config = new ConfigProto(CloudCmd, Util, DOM);
function ConfigProto(CloudCmd, Util, DOM){
var Key = CloudCmd.Key,
Images = DOM.Images,
Events = DOM.Events,
ESC = CloudCmd.Key.ESC,
INPUT = 'INPUT',
CONFIG,
TEMPLATE,
Config = this;
this.init = function(pCallBack){
Util.loadOnLoad([
Config.show,
CloudCmd.View,
]);
DOM.Events.addKey(listener);
DOM.setButtonKey('f10', Config.show);
delete Config.init;
};
this.show = function() {
var funcs = [
getTemplate,
cssLoad
];
Images.showLoad({top:true});
Util.asyncCall(funcs, fillTemplate);
};
function cssLoad(callback) {
DOM.cssLoad({
src : '/css/config.css',
func: Util.retExec(callback)
});
}
function getTemplate(callback) {
Util.ifExec(TEMPLATE, callback, function (execCall) {
DOM.ajax({
url : '/html/config.html',
success : function(data) {
TEMPLATE = data;
execCall();
},
error : Images.showError
});
});
}
function fillTemplate() {
Util.ifExec(CONFIG, function() {
var i, n, div, data, li, param, obj = {};
Util.copyObj(CONFIG, obj);
changeConfig(obj);
data = Util.render(TEMPLATE, obj);
div = DOM.anyload({
name : 'div',
className : 'config',
inner : data.toString()
});
li = DOM.getByTag(INPUT, div);
n = li.length;
for (i = 0; i < n; i++) {
param = li[i];
Events.add('change', change, param);
Events.addKey(key, param);
}
Images.hideLoad();
CloudCmd.View.show(div, null, {
autoSize: true
});
}, function(callback) {
CloudCmd.getConfig(function(config){
CONFIG = config;
callback();
});
});
}
this.hide = function() {
CloudCmd.View.hide();
};
function listener(pEvent){
var f10 = Key.F10,
isBind = Key.isBind(),
key = pEvent.keyCode;
/* если клавиши можно обрабатывать */
if (isBind && key === f10)
Config.show();
}
function changeConfig(config) {
var name;
for (name in config)
if (Util.isBoolean(config[name]))
config[name] = setState(config[name]);
}
function setState(state) {
var ret = "";
if (state)
ret = " checked";
return ret;
}
function change(event) {
var data,
obj = {},
el = event.target,
name = el.id,
type = el.type;
if (el.type === 'checkbox')
data = el.checked;
else
data = el.value;
obj[name] = data;
CONFIG[name] = data;
DOM.RESTful.config(obj);
}
function key(event) {
var keyCode = event.keyCode;
if (keyCode === ESC)
Config.hide();
}
}
})(CloudCmd, Util, DOM);

View file

@ -1,10 +1,15 @@
var CloudCmd, Util, DOM, $;
(function(CloudCmd, Util, DOM){
(function(CloudCmd, Util, DOM) {
'use strict';
var Buffer = {
log : '',
error : ''
};
CloudCmd.Console = new ConsoleProto(CloudCmd, Util, DOM);
function ConsoleProto(CloudCmd, Util, DOM){
function ConsoleProto(CloudCmd, Util, DOM) {
var Name = 'Console',
Loading,
jqconsole,
@ -72,10 +77,10 @@ var CloudCmd, Util, DOM, $;
handler();
}
CloudCmd.View.show(Element, function(){
CloudCmd.View.show(Element, function() {
var l$Console = jqconsole.$console,
l$Input = jqconsole.$input_source,
lFocus = function(){
lFocus = function() {
var x = window.scrollX,
y = window.scrollY;
@ -102,32 +107,33 @@ var CloudCmd, Util, DOM, $;
}
};
this.hide = function(){
this.hide = function() {
CloudCmd.View.hide();
};
this.log = function(pText){
if (jqconsole)
jqconsole.Write( addNewLine(pText), 'log-msg');
this.log = function(pText) {
log(pText, 'log');
};
this.error = function(pText){
if (jqconsole)
jqconsole.Write( addNewLine(pText), 'error-msg');
this.error = function(pText) {
log(pText, 'error');
};
function addNewLine(pText){
var lNewLine = '',
n = pText && pText.length;
function log(msg, status) {
var ret;
if(n && pText[n-1] !== '\n')
lNewLine = '\n';
return pText + lNewLine;
if (msg) {
Buffer[status] += msg;
ret = Util.isContainStr(Buffer[status], '\n');
if (jqconsole && ret) {
jqconsole.Write(Buffer[status], status + '-msg');
Buffer[status] = '';
}
}
}
function load(pCallBack){
function load(pCallBack) {
Util.time(Name + ' load');
var lDir = CloudCmd.LIBDIRCLIENT + 'console/',
@ -137,7 +143,7 @@ var CloudCmd, Util, DOM, $;
lDir + 'ansi.css'
];
DOM.anyLoadInParallel(lFiles, function(){
DOM.anyLoadInParallel(lFiles, function() {
Util.timeEnd(Name + ' load');
Loading = false;
@ -145,15 +151,15 @@ var CloudCmd, Util, DOM, $;
});
}
function listener(pEvent){
function listener(pEvent) {
var lTRA = Key.TRA,
lESC = Key.ESC,
lIsBind = Key.isBind(),
lKey = pEvent.keyCode;
switch(lKey){
switch(lKey) {
case lTRA:
if (lIsBind){
if (lIsBind) {
Console.show();
DOM.preventDefault(pEvent);
}

View file

@ -1,4 +1,4 @@
var CloudCmd, Util, DOM, CloudFunc;
var CloudCmd, Util, DOM, CloudFunc, Dialog;
(function(Util) {
'use strict';
@ -6,6 +6,12 @@ var CloudCmd, Util, DOM, CloudFunc;
var DOMFunc = function() {},
DOMProto,
DialogProto = function() {
this.alert = alert.bind(window);
this.prompt = prompt.bind(window);
this.confirm = confirm.bind(window);
},
ImagesProto = function() {
var LImagesProto = function() {
function getImage(pName) {
@ -95,14 +101,13 @@ var CloudCmd, Util, DOM, CloudFunc;
}
/* если файла не существует*/
if ( Util.isContainStr(lText, 'Error: ENOENT, ') )
if (Util.isContainStr(lText, 'Error: ENOENT, '))
lText = lText.replace('Error: ENOENT, n','N');
/* если не хватает прав для чтения файла*/
else if ( Util.isContainStr(lText, 'Error: EACCES,') )
else if (Util.isContainStr(lText, 'Error: EACCES,'))
lText = lText.replace('Error: EACCES, p','P');
DOM.show(lErrorImage);
lErrorImage.title = lText;
@ -114,14 +119,14 @@ var CloudCmd, Util, DOM, CloudFunc;
if (lText) {
Util.log(lText);
setTimeout(Util.retExec(alert, lText), 100);
setTimeout(Util.retFunc(Dialog.alert, lText), 100);
}
return lErrorImage;
};
},
RESTfullProto = function() {
RESTfulProto = function() {
this.delete = function(pUrl, pData, pCallBack, pQuery) {
sendRequest({
method : 'DELETE',
@ -176,6 +181,16 @@ var CloudCmd, Util, DOM, CloudFunc;
callback : pCallBack
});
};
this.config = function(pData, pCallBack) {
sendRequest({
method : 'PUT',
url : '/config',
data : pData,
callback : pCallBack,
imgPosition : { top: true }
});
};
function sendRequest(pParams) {
var lRet = Util.checkObjTrue(pParams, ['method']);
@ -343,7 +358,7 @@ var CloudCmd, Util, DOM, CloudFunc;
* @param pUseCapture
* @param pElement {document by default}
*/
this.addOneTime = function(pType, pListener, pElement, pUseCapture) {
this.addOnce = function(pType, pListener, pElement, pUseCapture) {
var lRet = this,
lOneTime = function (pEvent) {
lRet.remove(pType, lOneTime, pElement, pUseCapture);
@ -1098,10 +1113,10 @@ var CloudCmd, Util, DOM, CloudFunc;
if (lName === '..')
lName = '';
lName = prompt(lMsg, lName);
lName = Dialog.prompt(lMsg, lName);
if (lName)
RESTfull.save(lDir + lName + lType, null, CloudCmd.refresh);
RESTful.save(lDir + lName + lType, null, CloudCmd.refresh);
};
/**
@ -1117,7 +1132,7 @@ var CloudCmd, Util, DOM, CloudFunc;
};
if (lName && lName !== '..')
RESTfull.zip(lFiles, CloudCmd.refresh);
RESTful.zip(lFiles, CloudCmd.refresh);
};
@ -1173,9 +1188,9 @@ var CloudCmd, Util, DOM, CloudFunc;
}
if (lName !== '..')
lRet = confirm(lMsg);
lRet = Dialog.confirm(lMsg);
else
alert('No files selected!');
Dialog.alert('No files selected!');
if (lRet) {
var lUrl;
@ -1188,7 +1203,7 @@ var CloudCmd, Util, DOM, CloudFunc;
}
if (lCurrent || lSelected)
RESTfull.delete(lUrl, lSelected, function() {
RESTful.delete(lUrl, lSelected, function() {
if (n > 1)
DOM.deleteSelected(lFiles);
else
@ -1317,7 +1332,7 @@ var CloudCmd, Util, DOM, CloudFunc;
/* если это папка - возвращаем слово dir вместо размера*/
if (lName !== '..')
RESTfull.read(lLink, function(pSize) {
RESTful.read(lLink, function(pSize) {
DOM.setCurrentSize(pSize, lCurrent);
Util.exec(pCallBack, lCurrent);
}, '?size');
@ -1813,7 +1828,7 @@ var CloudCmd, Util, DOM, CloudFunc;
var lCurrent = pCurrentFile || Cmd.getCurrentFile(),
lFrom = Cmd.getCurrentName(lCurrent),
lTo = prompt('Rename', lFrom) || lFrom,
lTo = Dialog.prompt('Rename', lFrom) || lFrom,
lDirPath = Cmd.getCurrentDirPath();
if ( !Util.strCmp(lFrom, lTo) ) {
@ -1822,7 +1837,7 @@ var CloudCmd, Util, DOM, CloudFunc;
to : lDirPath + lTo
};
RESTfull.mv(lFiles, function() {
RESTful.mv(lFiles, function() {
DOM.setCurrentName(lTo, lCurrent);
});
}
@ -1842,7 +1857,7 @@ var CloudCmd, Util, DOM, CloudFunc;
lFromPath = Cmd.getCurrentPath(),
lToPath = Cmd.getNotCurrentDirPath() + lName;
lToPath = prompt( 'Rename/Move file "' + lName + '"', lToPath );
lToPath = Dialog.prompt('Rename/Move file "' + lName + '"', lToPath);
if ( lToPath && !Util.strCmp(lFromPath, lToPath) ) {
var lFiles = {
@ -1850,7 +1865,7 @@ var CloudCmd, Util, DOM, CloudFunc;
to : lToPath
};
RESTfull.mv(lFiles, function() {
RESTful.mv(lFiles, function() {
DOM.deleteCurrent(lCurrent);
var lPanel = DOM.getPanel(true),
@ -1875,7 +1890,7 @@ var CloudCmd, Util, DOM, CloudFunc;
lName = Cmd.getCurrentName(lCurrent),
lFromPath = Cmd.getCurrentPath(),
lToPath = Cmd.getNotCurrentDirPath() + lName;
lToPath = prompt( 'Copy file "' + lName + '" to', lToPath );
lToPath = Dialog.prompt( 'Copy file "' + lName + '" to', lToPath );
if ( lToPath && !Util.strCmp(lFromPath, lToPath) ) {
var lFiles = {
@ -1883,7 +1898,7 @@ var CloudCmd, Util, DOM, CloudFunc;
to : lToPath
};
RESTfull.cp(lFiles, function() {
RESTful.cp(lFiles, function() {
var lPanel = DOM.getPanel(true),
lDotDot = DOM.getById( '..(' + lPanel.id + ')');
@ -1940,16 +1955,18 @@ var CloudCmd, Util, DOM, CloudFunc;
Events = Util.extendProto(EventsProto),
Loader = Util.extendProto(LoaderProto),
Images = Util.extendProto(ImagesProto),
RESTfull = Util.extendProto(RESTfullProto),
RESTful = Util.extendProto(RESTfulProto),
Cache = Util.extendProto(CacheProto);
DOMProto = DOMFunc.prototype = new CmdProto();
Dialog = new DialogProto();
Util.extend(DOMProto, [
DOMTree,
Loader, {
Events : Events,
RESTfull: RESTfull,
RESTful: RESTful,
Images : Images,
Cache : Cache
}

View file

@ -49,7 +49,6 @@ var CloudCmd, Util, DOM, CloudFunc, JsDiff, ace;
if (!Element) {
Element = DOM.anyload({
name : 'div',
className : 'edit',
style :
'width : 100%;' +
'height : 100%;' +
@ -122,7 +121,7 @@ var CloudCmd, Util, DOM, CloudFunc, JsDiff, ace;
var lPath = DOM.getCurrentPath(),
lValue = Ace.getValue();
DOM.RESTfull.save(lPath, lValue, Edit.showMessage);
DOM.RESTful.save(lPath, lValue, Edit.showMessage);
}
});
}
@ -161,7 +160,7 @@ var CloudCmd, Util, DOM, CloudFunc, JsDiff, ace;
if (!Msg) {
DOM.cssSet({
id : 'msg-css',
inner : '.msg {' +
inner : '#view .msg {' +
'z-index' + ': 1;' +
'background-color' + ': #7285B7;' +
'color' + ': #D1F1A9;' +

View file

@ -9,7 +9,7 @@ var CloudCmd, Util, DOM;
Images = DOM.Images,
Help = this;
this.init = function(pCallBack){
this.init = function(pCallBack) {
Util.loadOnLoad([
Help.show,
CloudCmd.View,
@ -21,12 +21,26 @@ var CloudCmd, Util, DOM;
delete Help.init;
};
this.show = function(){
this.show = function() {
Images.showLoad({top:true});
DOM.cssSet({
id : 'help-css',
inner : '#help {' +
'white-space' + ': normal;' +
'margin' + ': 25px;' +
'}' +
'#help li {' +
'list-style-type' + ': disc;' +
'}'
});
DOM.ajax({
url: '/HELP.md',
success: function (pData){
success: function (pData) {
var lData = {text: pData};
DOM.ajax({
method : 'post',
url : 'https://api.github.com/markdown',
@ -34,7 +48,7 @@ var CloudCmd, Util, DOM;
success:function(pResult){
var lDiv = DOM.anyload({
name : 'div',
style : 'white-space: normal;',
id : 'help',
inner : pResult.toString()
});
@ -50,10 +64,11 @@ var CloudCmd, Util, DOM;
});
};
this.hide = function() {
CloudCmd.View.hide();
};
this.hide = CloudCmd.View.hide;
function listener(pEvent){
function listener(pEvent) {
var lF1 = Key.F1,
lIsBind = Key.isBind(),
lKey = pEvent.keyCode;

View file

@ -39,6 +39,7 @@ var CloudCmd, Util, DOM;
F7 : 118,
F8 : 119,
F9 : 120,
F10 : 121,
TRA : 192 /* Typewritten Reverse Apostrophe (`) */
};
@ -112,7 +113,7 @@ var CloudCmd, Util, DOM;
if ( DOM.isCurrentIsDir(lCurrent) )
lUrl += '?dir';
DOM.RESTfull.delete(lUrl, function() {
DOM.RESTful.delete(lUrl, function() {
DOM.deleteCurrent(lCurrent);
});
}
@ -163,6 +164,12 @@ var CloudCmd, Util, DOM;
break;
case Key.F10:
Util.exec(CloudCmd.Config);
DOM.preventDefault(pEvent);
break;
case Key.TRA:
DOM.Images.showLoad({top: true});
Util.exec(CloudCmd.Console);

View file

@ -16,7 +16,7 @@ var Util, DOM, CloudCmd;
online = config.online;
if (analytics && online) {
Events.addOneTime('mousemove', function(){
Events.addOnce('mousemove', function(){
var FIVE_SECONDS = 5000,
lUrl = CloudCmd.LIBDIRCLIENT + 'analytics.js';
@ -43,24 +43,25 @@ var Util, DOM, CloudCmd;
lFuncs =[
null,
CloudCmd.Help, /* f1 */
DOM.renameCurrent, /* f2 */
CloudCmd.View, /* f3 */
CloudCmd.Edit, /* f4 */
DOM.copyCurrent, /* f5 */
DOM.moveCurrent, /* f6 */
DOM.promptNewDir, /* f7 */
DOM.promptDeleteSelected, /* f8 */
CloudCmd.Menu, /* f9 */
CloudCmd.Help, /* f1 */
DOM.renameCurrent, /* f2 */
CloudCmd.View, /* f3 */
CloudCmd.Edit, /* f4 */
DOM.copyCurrent, /* f5 */
DOM.moveCurrent, /* f6 */
DOM.promptNewDir, /* f7 */
DOM.promptDeleteSelected, /* f8 */
CloudCmd.Menu, /* f9 */
CloudCmd.Config, /* f10 */
];
for (i = 1; i <= 9; i++) {
for (i = 1; i <= 10; i++) {
lButton = 'f' + i,
lEl = DOM.getById('f' + i);
lKeysPanel[lButton] = lEl;
if (i === 1 || i === 3 || i === 4 || i === 9)
Events.addOneTime('click', lFuncs[i], lEl);
if (i === 1 || i === 3 || i === 4 || i === 9 || i === 10)
Events.addOnce('click', lFuncs[i], lEl);
else
Events.addClick(lFuncs[i], lEl);
}
@ -68,7 +69,7 @@ var Util, DOM, CloudCmd;
lButton = '~',
lEl = DOM.getById('~');
lKeysPanel[lButton] = lEl;
Events.addOneTime('click', CloudCmd.Console, lEl);
Events.addOnce('click', CloudCmd.Console, lEl);
return lKeysPanel;
};
@ -232,7 +233,7 @@ var Util, DOM, CloudCmd;
var path = dir + file.name,
data = event.target.result;
DOM.RESTfull.save(path, data, CloudCmd.refresh);
DOM.RESTful.save(path, data, CloudCmd.refresh);
};
};
@ -291,7 +292,7 @@ var Util, DOM, CloudCmd;
}
function online() {
var cssSet = Util.retExec(DOM.cssSet, {
var cssSet = Util.retFunc(DOM.cssSet, {
id :'local-droids-font',
element : document.head,
inner : '@font-face {font-family: "Droid Sans Mono";' +
@ -301,7 +302,7 @@ var Util, DOM, CloudCmd;
});
if (navigator.onLine)
Events.addOneTime('offline', cssSet);
Events.addOnce('offline', cssSet);
else
cssSet();
}

View file

@ -174,12 +174,12 @@ var CloudCmd, Util, DOM, CloudFunc, $;
function getConfig (){
var lRet,
lMenuItems = {
'View' : Util.retExec(show, 'View'),
'Edit' : Util.retExec(show, 'Edit'),
'View' : Util.retFunc(show, 'View'),
'Edit' : Util.retFunc(show, 'Edit'),
'Rename' : function(){
setTimeout( Util.retExec(DOM.renameCurrent), 100);
setTimeout( Util.retFunc(DOM.renameCurrent), 100);
},
'Delete' : Util.retExec(DOM.promptDeleteSelected),
'Delete' : Util.retFunc(DOM.promptDeleteSelected),
'(Un)Select All': DOM.toggleAllSelectedFiles,
'Zip file' : DOM.zipFile
};
@ -187,7 +187,7 @@ var CloudCmd, Util, DOM, CloudFunc, $;
if (UploadToItemNames.length)
lMenuItems['Upload to'] = getUploadToItems(UploadToItemNames);
lMenuItems.Download = Util.retExec(downloadFromMenu);
lMenuItems.Download = Util.retFunc(downloadFromMenu);
lMenuItems.New = {
'File' : DOM.promptNewFile,
@ -197,7 +197,7 @@ var CloudCmd, Util, DOM, CloudFunc, $;
CloudCmd.execFromModule('FilePicker', 'saveFile', function(pName, pData){
var lPath = DOM.getCurrentDirPath() + pName;
DOM.RESTfull.save(lPath, pData, CloudCmd.refresh);
DOM.RESTful.save(lPath, pData, CloudCmd.refresh);
});
}
};

View file

@ -1,6 +1,6 @@
/* module make possible connectoin thrue socket.io on a client */
var CloudCmd, Util, DOM, io;
(function(CloudCmd, Util, DOM){
(function(CloudCmd, Util, DOM) {
'use strict';
var Messages = [],
@ -11,24 +11,22 @@ var CloudCmd, Util, DOM, io;
'npm i socket.io';
DOM.jsload('/socket.io/lib/socket.io.js', {
onerror : Util.retExec(Util.log, ERROR_MSG),
onerror : Util.retFunc(Util.log, ERROR_MSG),
onload : connect
});
function connect() {
var FIVE_SECONDS = 5000;
socket = io.connect(CloudCmd.HOST, {
'reconnect' : true,
'reconnection delay' : 500,
'max reconnection attempts' : Math.pow(2, 32),
'reconnect_failed' : function() {
Util.log('Could not reconnect. Reload page.');
}
'reconnection limit' : FIVE_SECONDS
});
CloudCmd.Socket = socket;
socket.on('connect', function () {
outToTerminal({stdout: 'socket connected'});
outToTerminal({stdout: 'socket connected\n'});
});
socket.on('message', function (msg) {
@ -39,28 +37,32 @@ var CloudCmd, Util, DOM, io;
});
socket.on('disconnect', function () {
outToTerminal({stderr: 'socket disconected'});
outToTerminal({stderr: 'socket disconected\n'});
});
socket.on('reconnect_failed', function () {
Util.log('Could not reconnect. Reload page.');
});
}
function outToTerminal(pMsg){
function outToTerminal(pMsg) {
var i, n, lResult, lStdout, lStderr,
lConsole = CloudCmd.Console;
DOM.Images.hideLoad();
if( Util.isObject(lConsole) ){
if(Messages.length){
if (Util.isObject(lConsole)) {
if (Messages.length) {
/* show oll msg from buffer */
for(i = 0, n = Messages.length; i < n; i++){
for (i = 0, n = Messages.length; i < n; i++) {
lStdout = Messages[i].stdout;
lStderr = Messages[i].stderr;
if(lStdout)
if (lStdout)
lConsole.log(lStdout);
if(lStderr){
if (lStderr) {
/* if it's object - convert is to string' */
if( Util.isObject(lStderr) )
if (Util.isObject(lStderr))
lStderr = Util.stringifyJSON(lStderr);
lConsole.error(lStderr);
@ -72,11 +74,11 @@ var CloudCmd, Util, DOM, io;
lStdout = pMsg.stdout;
lStderr = pMsg.stderr;
if(lStdout)
if (lStdout)
lResult = lConsole.log(lStdout);
if(lStderr && lStderr.code !== 1)
lResult = lConsole.error(lStderr.toString());
if (lStderr)
lResult = lConsole.error(lStderr);
}
else
/* if term not accesable save msg to buffer */

View file

@ -42,7 +42,7 @@ var CloudCmd, Util, DOM, CloudFunc, $;
padding : 0
};
this.init = function(pCallBack){
this.init = function(pCallBack) {
var lFunc, lIsFunc, lIsCallBack;
Loading = true;
@ -71,9 +71,9 @@ var CloudCmd, Util, DOM, CloudFunc, $;
/**
* function shows FancyBox
*/
this.show = function(pData, pCallBack){
var lPath, lElement,
lAfterFunc, lFunc;
this.show = function(pData, pCallBack, pConfig) {
var lPath, lElement, lAfterFunc, lFunc, name,
config = {};
if (!Loading) {
Element = $('<div id=view tabindex=0>');
@ -87,7 +87,12 @@ var CloudCmd, Util, DOM, CloudFunc, $;
Config.afterShow = lFunc;
$.fancybox(lElement, Config);
Util.copyObj(Config, config);
for (name in pConfig)
config[name] = pConfig[name];
$.fancybox(lElement, config);
} else {
lPath = CloudFunc.FS + DOM.getCurrentPath();
@ -103,7 +108,7 @@ var CloudCmd, Util, DOM, CloudFunc, $;
}
};
this.hide = function(){
this.hide = function() {
$.fancybox.close();
};
@ -112,7 +117,7 @@ var CloudCmd, Util, DOM, CloudFunc, $;
* @pParent - this
* @pCallBack - executes, when everything loaded
*/
function load(pCallBack){
function load(pCallBack) {
Util.time(Name + ' load');
var lDir = CloudCmd.LIBDIRCLIENT + 'view/fancyBox/source/',
lFiles = [ lDir + 'jquery.fancybox.css',
@ -147,12 +152,12 @@ var CloudCmd, Util, DOM, CloudFunc, $;
}
function view(){
function view() {
Images.showLoad();
View.show();
}
function listener(pEvent){
function listener(pEvent) {
var lF3 = Key.F3,
lIsBind = Key.isBind(),
lKey = pEvent.keyCode;

View file

@ -21,7 +21,7 @@ var Util, exports, CloudFunc = {};
Util = global.cloudcmd.main.util;
CloudFunc = exports;
}
/* Путь с которым мы сейчас работаем */
CloudFunc.Path = '';
@ -43,7 +43,8 @@ var Util, exports, CloudFunc = {};
CloudFunc.formatMsg = function(pMsg, pName, pStatus) {
var status = pStatus || 'ok',
msg = pMsg + ': ' + status + '("' + pName + '")';
name = !pName ? '': '("' + pName + '")',
msg = pMsg + ': ' + status + name;
return msg;
};

View file

@ -1,7 +1,7 @@
(function() {
'use strict';
if(!global.cloudcmd)
if (!global.cloudcmd)
return console.log(
'# server.js' + '\n' +
'# -----------' + '\n' +
@ -20,30 +20,24 @@
Querystring = main.querystring,
Minify = main.minify,
CloudFunc = main.cloudfunc,
AppCache = main.appcache,
Socket = main.socket,
http = main.http,
https = main.https,
Util = main.util,
express = main.express,
expressApp = express.getApp(controller),
Server, Rest, Route, Minimize;
Server, Rest, Route;
/* базовая инициализация */
function init(pAppCachProcessing) {
var lConfig = main.config,
lMinifyAllowed = lConfig.minify;
/* Change default parameters of
* js/css/html minification
*/
Minify.setAllowed(lMinifyAllowed);
/* Если нужно минимизируем скрипты */
Util.exec(Minimize, lMinifyAllowed);
var config = main.config;
/* создаём файл app cache */
if( lConfig.appcache && AppCache && lConfig.server )
if (config.appcache && AppCache && config.server )
Util.exec( pAppCachProcessing );
}
@ -56,12 +50,11 @@
function start(pProcessing) {
var lConfig = main.config;
if(!pProcessing)
if (!pProcessing)
pProcessing = {};
Rest = pProcessing.rest;
Route = pProcessing.route;
Minimize = pProcessing.minimize;
init(pProcessing.appcache);
@ -69,7 +62,7 @@
process.env.app_port || /* nodester */
process.env.VCAP_APP_PORT || /* cloudfoundry */
lConfig.port,
lIP = process.env.IP || /* c9 */
lConfig.ip ||
(main.WIN32 ? '127.0.0.1' : '0.0.0.0'),
@ -80,15 +73,19 @@
lHTTPS = 'https://',
lSockets = function(pServer) {
var lListen;
if(lConfig.socket && Socket)
var lListen, msg, status;
if (lConfig.socket && Socket)
lListen = Socket.listen(pServer);
Util.log('* Sockets ' + (lListen ? 'running' : 'disabled'));
status = lListen ? 'on' : 'off';
msg = CloudFunc.formatMsg('sockets', '', status);
Util.log(msg);
},
lHTTPServer = function() {
Server = http.createServer( controller );
Server = http.createServer(expressApp || controller);
Server.on('error', Util.log);
Server.listen(lPort, lIP);
lServerLog(lHTTP, lPort);
@ -127,10 +124,9 @@
Server.listen(lSSLPort, lIP);
lServerLog(lHTTPS, lSSLPort);
}
else
} else
lHTTPServer();
}else
} else
Util.log('Cloud Commander testing mode');
}
@ -146,13 +142,14 @@
var lRet, lName, lMin, lExt, lResult,
lConfig = main.config,
lParsedUrl = URL.parse(pReq.url),
lQuery = lParsedUrl.search || '',
lPath = lParsedUrl.pathname;
/* added supporting of Russian language in directory names */
lPath = Querystring.unescape(lPath);
Util.log('pathname: ' + lPath);
Util.log("request for " + lPath + " received...");
if (!expressApp)
Util.log(pReq.method + ' ' + lPath + lQuery);
var lData = {
name : lPath,
@ -160,24 +157,21 @@
response : pRes
};
if( lConfig.rest )
if (lConfig.rest )
lRet = Util.exec(Rest, lData);
if( !lRet && Route)
if (!lRet && Route)
lRet = Util.exec(Route, lData);
if(!lRet) {
if (!lRet) {
lName = lData.name;
Util.log('reading ' + lName);
/* watching is file changed */
if(lConfig.appcache)
if (lConfig.appcache)
AppCache.watch(lName);
Util.log(Path.basename(lName));
lName = Path.join(DIR, lName);
lMin = Minify.allowed,
lMin = lConfig.minify,
lExt = Util.getExtension(lName),
lResult = lMin && Util.strCmp(lExt, ['.js', '.css', '.html']);

View file

@ -1,7 +1,7 @@
(function(){
(function() {
'use strict';
if(!global.cloudcmd)
if (!global.cloudcmd)
return console.log(
'# commander.js' + '\n' +
'# -----------' + '\n' +
@ -14,9 +14,10 @@
fs = main.fs,
Util = main.util;
exports.getDirContent = function(pPath, pCallBack){
exports.getDirContent = function(pPath, pCallBack) {
var lRet = Util.isString(pPath);
if( lRet )
if (lRet)
fs.readdir(pPath, Util.call(readDir, {
callback: pCallBack,
path : pPath
@ -33,16 +34,17 @@
* @param pError
* @param pFiles
*/
function readDir(pParams){
function readDir(pParams) {
var lRet = checkParams(pParams);
lRet = lRet && Util.checkObj(pParams.params, ['path']);
if(lRet){
if (lRet) {
var p = pParams,
c = pParams.params,
lFiles = p.data,
lDirPath = getDirPath(c.path);
if(!p.error && lFiles){
if (!p.error && lFiles) {
lFiles.data = lFiles.sort();
/* Получаем информацию о файлах */
@ -55,12 +57,10 @@
path : c.path
},
lFill = function(){
fillJSON(lFilesData);
};
lFill = Util.retFunc(fillJSON, lFilesData);
if(n){
for(var i = 0; i < n; i++){
if (n)
for (var i = 0; i < n; i++) {
var lName = lDirPath + lFiles[i],
lParams = {
callback : lFill,
@ -69,13 +69,11 @@
stats : lStats,
};
fs.stat( lName, Util.call(getFilesStat, lParams) );
fs.stat(lName, Util.call(getFilesStat, lParams));
}
}
else
fillJSON(lFilesData);
}
else
} else
Util.exec(c.callback, p.error.toString());
}
}
@ -84,12 +82,12 @@
* async getting file states
* and putting it to lStats object
*/
function getFilesStat(pParams){
function getFilesStat(pParams) {
var lRet = checkParams(pParams);
lRet = lRet && Util.checkObjTrue(pParams.params,
['callback', 'stats', 'name', 'count']);
if(lRet){
if (lRet) {
var p = pParams,
c = p.params;
@ -99,7 +97,7 @@
'isDirectory' : Util.retFalse
};
if(c.count === Object.keys(c.stats).length)
if (c.count === Object.keys(c.stats).length)
Util.exec(c.callback);
}
}
@ -112,11 +110,10 @@
*
* @param pFiles - array of files of current directory
*/
function fillJSON(pParams){
function fillJSON(pParams) {
var lRet = Util.checkObjTrue(pParams, ['files', 'stats', 'path']);
if(lRet)
{
if (lRet) {
var p = pParams,
i, n = p.files.length || 0,
@ -131,12 +128,12 @@
};
var lName, lStats, lMode, lIsDir;
for( i = 0; i < n; i++ ){
for (i = 0; i < n; i++ ) {
/* Переводим права доступа в 8-ричную систему */
lName = p.files[i],
lStats = p.stats[lName];
if(lStats){
if (lStats) {
lMode = (lStats.mode - 0).toString(8),
lIsDir = lStats.isDirectory();
}
@ -158,14 +155,14 @@
}
}
function checkParams(pParams){
function checkParams(pParams) {
return Util.checkObj(pParams, ['error', 'data', 'params']);
}
function getDirPath(pPath){
function getDirPath(pPath) {
var lRet = pPath;
if(lRet !== '/')
if (lRet !== '/')
lRet += '/';
return lRet;

View file

@ -29,8 +29,7 @@
lTotal += lSize;
}
processDir(pDir, calcSize, function(){
Util.log(pDir + ' -> ' + lTotal);
processDir(pDir, calcSize, function() {
Util.exec(pCallBack, null, lTotal);
});
};
@ -80,7 +79,7 @@
for (var i = 0; i < n; i++) {
lDirPath = path.join(lPath, pFiles[i]);
process.nextTick( Util.retExec(getDirInfo, lDirPath) );
process.nextTick(Util.retFunc(getDirInfo, lDirPath));
}
}

23
lib/server/express.js Normal file
View file

@ -0,0 +1,23 @@
(function() {
'use strict';
if (!global.cloudcmd)
return console.log(
'# express.js' + '\n' +
'# -----------' + '\n' +
'# Module is part of Cloud Commander,' + '\n' +
'# easy to use web server.' + '\n' +
'# http://cloudcmd.io' + '\n');
var main = global.cloudcmd.main,
express = main.require('express'),
app = express && express();
exports.getApp = function(controller) {
if (app)
app.use(express.logger('dev'))
.all('*', controller);
return app;
};
})();

View file

@ -1,4 +1,4 @@
(function(){
(function() {
'use strict';
/* Global var accessible from any loaded module */
@ -11,7 +11,7 @@
SLASH,
ISWIN32,
ext,
path, fs, zlib, url, pipe,
path, fs, zlib, url, pipe, CloudFunc,
OK, FILE_NOT_FOUND, MOVED_PERMANENTLY,
REQUEST, RESPONSE,
@ -101,11 +101,12 @@
exports.VOLUMES = getVolumes(),
/* Additional Modules */
exports.cloudfunc = CloudFunc = librequire('cloudfunc'),
exports.pipe = pipe = srvrequire('pipe'),
exports.socket = srvrequire('socket'),
exports.express = srvrequire('express'),
exports.auth = srvrequire('auth').auth,
exports.appcache = srvrequire('appcache'),
exports.cloudfunc = librequire('cloudfunc'),
exports.dir = srvrequire('dir'),
exports.rest = srvrequire('rest').api,
exports.update = srvrequire('update'),
@ -121,49 +122,51 @@
* function do safe require of needed module
* @param {Strin} pSrc
*/
function mrequire(pSrc){
var lModule,
lError = Util.tryCatch(function(){
lModule = require(pSrc);
});
function mrequire(pSrc) {
var lModule, msg,
lError = Util.tryCatch(function() {
lModule = require(pSrc);
});
if(lError)
Util.log('Module ' + pSrc + ' not connected');
if (lError)
msg = CloudFunc.formatMsg('require', pSrc, 'no');
Util.log(msg);
return lModule;
}
function quietrequire(pSrc){
function quietrequire(pSrc) {
var lModule;
Util.tryCatch(function(){
Util.tryCatch(function() {
lModule = require(pSrc);
});
return lModule;
}
function rootrequire(pSrc){ return mrequire(DIR + pSrc); }
function rootrequire(pSrc) { return mrequire(DIR + pSrc); }
function librequire(pSrc){ return mrequire(LIBDIR + pSrc); }
function librequire(pSrc) { return mrequire(LIBDIR + pSrc); }
function srvrequire(pSrc){ return mrequire(SRVDIR + pSrc); }
function srvrequire(pSrc) { return mrequire(SRVDIR + pSrc); }
function jsonrequire(pSrc){ return mrequire(JSONDIR + pSrc);}
function jsonrequire(pSrc) { return mrequire(JSONDIR + pSrc);}
/**
* function check is current platform is win32
*/
function isWin32(){ return process.platform === 'win32'; }
function isWin32() { return process.platform === 'win32'; }
/**
* get volumes if win32 or get nothing if nix
*/
function getVolumes(){
function getVolumes() {
var lRet = ISWIN32 ? [] : '/';
if(ISWIN32)
srvrequire('win').getVolumes(function(pVolumes){
if (ISWIN32)
srvrequire('win').getVolumes(function(pVolumes) {
console.log(pVolumes);
exports.VOLUMES = pVolumes;
});
@ -181,20 +184,20 @@
* query
* https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
*/
function generateHeaders(pParams){
function generateHeaders(pParams) {
var lRet = Util.checkObjTrue(pParams, ['name']);
if(lRet){
if (lRet) {
var p = pParams,
lExt = Util.getExtension(p.name),
lType = ext[lExt] || 'text/plain',
lContentEncoding = '';
/* if type of file any, but img - then we shoud specify charset */
if( !Util.isContainStr(lType, 'img') )
if (!Util.isContainStr(lType, 'img'))
lContentEncoding = '; charset=UTF-8';
if( Util.isContainStr(p.query, 'download') )
if (Util.isContainStr(p.query, 'download'))
lType = 'application/octet-stream';
lRet = {
@ -204,10 +207,10 @@
'Vary' : 'Accept-Encoding'
};
if( !Util.strCmp(lExt, '.appcache') && p.cache)
if (!Util.strCmp(lExt, '.appcache') && p.cache)
lRet['cache-control'] = 'max-age=' + 31337 * 21;
if(p.gzip)
if (p.gzip)
lRet['content-encoding'] = 'gzip';
}
@ -221,29 +224,37 @@
* @param pName - имя файла
* @param pGzip - данные сжаты gzip'ом
*/
function sendFile(pParams){
var lRet = checkParams(pParams);
function sendFile(pParams) {
var header, lRet = checkParams(pParams);
if (lRet) {
var p = pParams,
lGzip = isGZIP(p.request) && p.gzip;
p.response.writeHead(OK, generateHeaders({
name : p.name,
cache : p.cache,
gzip : lGzip,
query : getQuery(p.request)
}) );
pipe.create({
from: p.name,
write: p.response,
zip : lGzip && !p.gziped,
callback: function(pError) {
var lError = pError && pError.toString();
if (pError) {
p.response.writeHead(FILE_NOT_FOUND, 'OK');
p.response.end(lError);
}
fs.stat(p.name, function(error, stat) {
if (error)
sendError(pParams, error);
else {
header = generateHeaders({
name : p.name,
cache : p.cache,
gzip : lGzip,
query : getQuery(p.request)
});
//p.response.writeHead(OK, header);
setHeader(header, p.response);
p.response.statusCode = p.status || OK;
pipe.create({
from : p.name,
write : p.response,
zip : lGzip && !p.gziped,
callback: function(error) {
if (error)
sendError(pParams, error);
}
});
}
});
}
@ -258,13 +269,12 @@
* @param Data - данные
* @param pName - имя отсылаемого файла
*/
function sendResponse(pParams, pData){
function sendResponse(pParams, pData, pNotLog) {
var lRet = checkParams(pParams);
if(lRet){
var p = pParams;
var lQuery = getQuery(p.request),
if (lRet) {
var p = pParams,
lQuery = getQuery(p.request),
/* download, json */
lGzip = isGZIP(p.request),
lHead = generateHeaders({
@ -273,21 +283,24 @@
gzip : lGzip,
query : lQuery
});
setHeader(lHead, p.response);
if (!pNotLog)
Util.log(pData || p.data);
/* если браузер поддерживает gzip-сжатие - сжимаем данные*/
Util.ifExec(!lGzip,
function(pParams) {
var lRet = Util.checkObj(pParams, ['data']);
if(lRet) {
if (lRet) {
p.status = pParams.status || p.status;
p.data = pParams.data;
}
p.response.writeHead(p.status || OK, lHead);
p.response.statusCode = p.status || OK;
p.response.end(p.data);
Util.log( p.name + ' sended');
},
function(pCallBack) {
@ -302,14 +315,19 @@
/**
* redirect to another URL
*/
function redirect(pParams){
var lRet = Util.checkObjTrue(pParams,
[RESPONSE]);
function redirect(pParams) {
var p, header,
lRet = Util.checkObjTrue(pParams, [RESPONSE]);
if(lRet){
var p = pParams;
if (lRet) {
p = pParams;
p.response.writeHead(MOVED_PERMANENTLY, {'Location': p.url});
header = {
'Location': p.url
},
setHeader(header, p.response);
p.response.statusCode = MOVED_PERMANENTLY;
p.response.end();
}
}
@ -337,18 +355,18 @@
* @param pHeader - заголовок файла
* @pName
*/
function gzipData(pParams){
function gzipData(pParams) {
var lRet = checkCallBackParams(pParams),
p = pParams;
if(lRet)
if (lRet)
lRet = Util.checkObj(pParams.params, ['callback']);
if(lRet){
if (lRet) {
var lCallBack = p.params.callback,
lParams = {};
if(!p.error)
if (!p.error)
lParams.data = p.data;
else{
lParams.status = FILE_NOT_FOUND;
@ -360,39 +378,46 @@
}
function checkCallBackParams(pParams){
function checkCallBackParams(pParams) {
return Util.checkObj(pParams, ['error', 'data', 'params']);
}
function readFiles(pFiles, pCallBack){
function readFiles(pFiles, pCallBack) {
var lDone = [],
lFiles,
lErrors,
lReadedFiles = {},
lDoneFunc = function (pParams){
var lRet = Util.checkObj(pParams, ['error', 'data', 'params']);
lDoneFunc = function (pParams) {
var msg, status,
lRet = Util.checkObj(pParams, ['error', 'data', 'params']);
if(lRet){
if (lRet) {
lDone.pop();
var p = pParams,
lName = p.params;
if(p.error){
if(!lErrors) lErrors = {};
if (p.error) {
status = 'error';
if (!lErrors) lErrors = {};
lErrors[lName] = p.error;
}
else{
Util.log(lName + ' readed');
status = 'ok';
lReadedFiles[lName] = p.data;
}
if( !lDone.length )
lName = path.basename(lName);
msg = CloudFunc.formatMsg('read', lName, status);
Util.log(msg);
if ( !lDone.length )
Util.exec(pCallBack, lErrors, lReadedFiles);
}
};
if( Util.isArray(pFiles) )
if ( Util.isArray(pFiles) )
lFiles = pFiles;
else
lFiles = [pFiles];
@ -405,7 +430,7 @@
}
}
function checkParams(pParams, pAdditional){
function checkParams(pParams, pAdditional) {
var lRet = Util.checkObjTrue( pParams, ['name', REQUEST, RESPONSE] );
if (lRet && pAdditional)
@ -414,7 +439,7 @@
return lRet;
}
function getQuery(pReq){
function getQuery(pReq) {
var lQuery, lParsedUrl;
if (pReq) {
@ -425,7 +450,7 @@
return lQuery;
}
function isGZIP(pReq){
function isGZIP(pReq) {
var lEnc, lGZIP;
if (pReq) {
lEnc = pReq.headers['accept-encoding'] || '';
@ -435,4 +460,12 @@
return lGZIP;
}
function setHeader(header, response) {
var name;
if (Util.isObject(header))
for (name in header)
response.setHeader(name, header[name]);
}
})();

View file

@ -28,48 +28,24 @@
exports.Minify = {
/* pathes to directories */
INDEX : HTMLDIR + 'index.html',
/* приватный переключатель минимизации */
allowed : true,
/* функция разрешает или
* запрещает минимизировать
* css/js/html
* @pAllowed: - структура, в которой
* передаються параметры
* минификации, вида
* {js:true,css:true,html:false; img:true}
* img отвечает за перевод картинок в base64
* и сохранение их в css-файл
*/
setAllowed :function(pAllowed) {
this.allowed = pAllowed && Minify;
},
optimize: function(pName, pParams) {
var lRet;
if (Minify) {
if (!Minify)
Util.log(COULD_NOT_MINIFY);
else {
pParams.name = Minify.getName(pName);
lRet = this.allowed;
if(!this.MinFolder)
if (!this.MinFolder)
this.MinFolder = Minify.MinFolder;
if(pParams && pParams.force)
Minify.optimize(pName, pParams);
else if(lRet)
IsChanged.isFileChanged(pName, function(pChanged) {
if(pChanged)
Minify.optimize(pName, pParams);
else
Util.exec(pParams.callback, pParams);
});
}
else {
this.allowed = false;
Util.log(COULD_NOT_MINIFY);
IsChanged.isFileChanged(pName, function(pChanged) {
if(pChanged)
Minify.optimize(pName, pParams);
else
Util.exec(pParams.callback, pParams);
});
}
return lRet;

View file

@ -1,4 +1,4 @@
/* RESTfull module */
/* RESTful module */
(function() {
'use strict';
@ -20,7 +20,10 @@
pipe = main.pipe,
CloudFunc = main.cloudfunc,
dir = main.dir,
JSONDIR = main.JSONDIR,
OK = 200,
sendError = main.sendError,
sendResponse= main.sendResponse,
Header = main.generateHeaders({
name:'api.json'
});
@ -38,8 +41,8 @@
lRet = Util.isContainStr(p.name, lAPIURL);
if (lRet) {
p.name = Util.removeStrOneTime(p.name, lAPIURL);
sendData( pParams);
p.name = Util.removeStrOneTime(p.name, lAPIURL) || '/';
sendData(pParams);
}
}
return lRet;
@ -106,42 +109,41 @@
case 'GET':
if (Util.strCmp(lQuery, 'size'))
dir.getSize(p.name, function(pErr, pSize) {
if (!pErr){
if (pErr)
sendError(p, pErr);
else {
lSize = CloudFunc.getShortSize(pSize);
Util.log(lSize);
main.sendResponse(p, lSize);
sendResponse(p, lSize);
}
else
main.sendError(p, pErr);
});
else
fs.stat(p.name, function(pError, pStat) {
if (!pError)
if (pStat.isDirectory())
if (pError)
sendError(p, pError);
else
if (!pStat.isDirectory())
main.sendFile(p);
else
main.commander.getDirContent(p.name, function(pError, pData) {
if (!pError){
if (pError)
sendError(p, pError);
else {
p.name += '.json';
p.data = Util.stringifyJSON(pData);
main.sendResponse(p);
sendResponse(p);
}
else
main.sendError(p, pError);
});
else
main.sendFile(p);
else
main.sendError(p, pError);
});
break;
case 'PUT':
if (lQuery === 'dir')
fs.mkdir(p.name, function(pError) {
if (!pError)
sendMsg(pParams, 'make dir', p.name);
if (pError)
sendError(pParams, pError);
else
main.sendError(pParams, pError);
sendMsg(pParams, 'make dir', p.name);
});
else
@ -151,10 +153,8 @@
callback : function(pError) {
var lName;
if (pError) {
Util.log(pError);
main.sendError(pParams, pError);
}
if (pError)
sendError(pParams, pError);
else {
lName = path.basename(p.name);
sendMsg(pParams, 'save', lName);
@ -166,17 +166,17 @@
case 'DELETE':
if (lQuery === 'dir')
fs.rmdir(p.name, function(pError){
if (!pError)
sendMsg(pParams, 'delete', p.name);
if (pError)
sendError(pParams, pError);
else
main.sendError(pParams, pError);
sendMsg(pParams, 'delete', p.name);
});
else if (lQuery === 'files') {
getBody(p.request, function(pBody) {
var lFiles = Util.parseJSON(pBody),
n = lFiles.length,
lDir = p.name,
log = Util.retExec(Util.log),
log = Util.log,
lAssync = 0;
function stat(pStat) {
@ -190,8 +190,8 @@
++lAssync;
if (p.error){
main.sendError(pParams, p.error);
Util.log(p.error);
sendError(pParams, p.error);
log(p.error);
}
else
if (p.data.isDirectory())
@ -216,10 +216,10 @@
});
}else
fs.unlink(p.name, function(pError) {
if (!pError)
sendMsg(pParams, 'delete', p.name);
if (pError)
sendError(pParams, pError);
else
main.sendError(pParams, pError);
sendMsg(pParams, 'delete', p.name);
});
break;
@ -247,10 +247,6 @@
};
send(p);
break;
case 'proxy':
break;
case 'zip':
main.sendFile(pParams);
@ -281,7 +277,9 @@
* @param pParams {command, method, body, requrest, response}
*/
function onPUT(pParams) {
var lRet = main.checkParams(pParams, ['body']);
var name, data, json, config,
lRet = main.checkParams(pParams, ['body']);
if (lRet) {
var p = pParams,
lCmd = p.command,
@ -301,22 +299,22 @@
main.child_process.exec(p.body, function(pError, pStdout, pStderr) {
var lError = pError || pStderr;
if (!lError)
main.sendResponse(pParams, pStdout);
sendResponse(pParams, pStdout);
else
main.sendError(pParams, lError);
sendError(pParams, lError);
});
break;
case 'mv':
if( Util.checkObjTrue(lFiles, ['from', 'to']) )
fs.rename(lFiles.from, lFiles.to, function(pError) {
if(!pError)
main.sendResponse(pParams);
if (pError)
sendError(pParams, pError);
else
main.sendError(pParams, pError);
sendResponse(pParams);
});
else
main.sendError(pParams, p.data);
sendError(pParams, p.data);
break;
case 'cp':
@ -326,13 +324,13 @@
to : lFiles.to,
callback : function(pError) {
if (pError)
main.sendError(pParams, pError);
sendError(pParams, pError);
else
sendMsg(pParams, 'copy', lFiles.to);
}
});
else
main.sendError(pParams, p.data);
sendError(pParams, p.data);
break;
case 'zip':
@ -345,7 +343,7 @@
var lName;
if (pError)
main.sendError(pParams, pError);
sendError(pParams, pError);
else {
lName = path.basename(lFiles.from);
sendMsg(pParams, 'zip', lName);
@ -353,7 +351,24 @@
}
});
else
main.sendError(pParams, p.data);
sendError(pParams, p.data);
break;
case 'config':
config = main.config;
for (name in lFiles)
config[name] = lFiles[name];
json = Util.stringifyJSON(config) + '\n';
fs.writeFile(JSONDIR + 'config.json', json, function(error) {
if (error)
sendError(pParams, error);
else
sendMsg(pParams, 'config', name);
});
break;
default:
@ -385,7 +400,7 @@
function sendMsg(pParams, pMsg, pName) {
var msg = CloudFunc.formatMsg(pMsg, pName);
main.sendResponse(pParams, msg);
sendResponse(pParams, msg);
}
})();

View file

@ -1,6 +1,6 @@
/* module make possible connectoin thru socket.io on a server */
(function(){
(function() {
'use strict';
var main = global.cloudcmd.main,
@ -39,10 +39,10 @@
* function listen on servers port
* @pServer {Object} started server object
*/
exports.listen = function(pServer){
exports.listen = function(pServer) {
var lRet, lListen, lConnNum, lMsg, lConn_func;
if(io){
if (io) {
lListen = io.listen(pServer),
lConnNum = 0;
@ -63,18 +63,23 @@
lListen.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);
lRet = lListen.sockets.on('connection', function (socket){
lRet = lListen.sockets.on('connection', function (socket) {
var lJSON;
++lConnNum;
if(!OnMessageFuncs[lConnNum]) {
lMsg = log(lConnNum, 'connected');
socket.send('{"stdout":"' + lMsg + '"}');
lMsg = log(lConnNum, 'connected\n');
lJSON = {
stdout : lMsg
};
lMsg = Util.stringifyJSON(lJSON);
socket.send(lMsg);
OnMessageFuncs[lConnNum] = onMessage(lConnNum, socket);
lConn_func = OnMessageFuncs[lConnNum];
@ -93,7 +98,7 @@
return lRet;
};
function disconnect(pParams){
function disconnect(pParams) {
var lConnNum, lRet = Util.checkObj(pParams, ['params']);
if(lRet) {
@ -112,17 +117,17 @@
*
* @param pConnNum, pSocket
*/
function onMessage(pConnNum, pSocket){
function onMessage(pConnNum, pSocket) {
return function(pCommand) {
var lMsg, lJSON, lWinCommand, lExec_func, lDir,
lHome, lError, lRet;
lHome, lError, lRet, lExecSymbols, isContain;
Util.log('#' + pConnNum + ': ' + pCommand);
if( Util.isContainStrAtBegin(pCommand, CLOUDCMD) ) {
if (Util.isContainStrAtBegin(pCommand, CLOUDCMD)) {
pCommand = Util.removeStr(pCommand, CLOUDCMD);
if( Util.isContainStrAtBegin(pCommand, ' ') ){
if( Util.isContainStrAtBegin(pCommand, ' ') ) {
pCommand = Util.removeStr(pCommand, ' ');
if( Util.isContainStrAtBegin(pCommand, 'update') && update )
@ -154,7 +159,7 @@
if ( Util.isContainStr(lDir, '~') )
lDir = Util.replaceStr(lDir, '~', lHome);
lError = Util.tryCatchLog(function(){
lError = Util.tryCatchLog(function() {
process.chdir(lDir);
});
@ -176,7 +181,7 @@
* change code page to unicode becouse
* windows use unicode on non English versions
*/
if(WIN32){
if(WIN32) {
lWinCommand = pCommand.toUpperCase();
if( Win32Commands.indexOf(lWinCommand) >= 0 )
@ -186,9 +191,14 @@
if(!ClientFuncs[pConnNum])
ClientFuncs[pConnNum] = getExec(pSocket, pConnNum);
lExec_func = ClientFuncs[pConnNum];
lExec_func = ClientFuncs[pConnNum];
lExecSymbols = ['*','#', '&', '{', '}', '|', '\'', '"'];
isContain = Util.isContainStr(pCommand, lExecSymbols);
exec(pCommand, lExec_func);
if (pCommand[0] === ' ' || isContain)
exec(pCommand, lExec_func);
else
getSpawn(pSocket, pConnNum, pCommand);
}
};
}
@ -198,24 +208,26 @@
* function send result of command to client
* @param pSocket
*/
function getExec(pSocket, pConnNum){
function getExec(pSocket, pConnNum) {
return function(pError, pStdout, pStderr) {
var lErrorStr, lExecStr, lExec,
lError = pStderr || pError;
if (lError)
if ( Util.isString(lError) )
if (lError) {
if (Util.isString(lError))
lErrorStr = lError;
else
lErrorStr = Util.stringifyJSON( lError );
lErrorStr = lError.toString();
lErrorStr = Util.addNewLine(lErrorStr);
}
lExec = {
stdout : pStdout,
stderr : lError
stderr : lErrorStr || lError
};
lExecStr = JSON.stringify(lExec);
lExecStr = Util.stringifyJSON(lExec);
log(pConnNum, pError, 'error');
log(pConnNum, pStderr, 'stderror');
@ -224,7 +236,38 @@
};
}
function log(pConnNum, pStr, pType){
function getSpawn(pSocket, pConnNum, pCommand) {
var send, cmd, spawn,
args = pCommand.split(' ');
pCommand = args.shift();
spawn = main.child_process.spawn;
cmd = spawn(pCommand, args);
send = function(data, isError) {
var lExecStr,
lExec = {},
msg = data.toString();
if (isError)
lExec.stderr = msg;
else
lExec.stdout = msg;
lExecStr = JSON.stringify(lExec);
pSocket.send(lExecStr);
};
cmd.stdout.on('data', send);
cmd.stderr.on('data', function(data) {
send(data, true);
});
cmd.on('error', Util.retFalse);
}
function log(pConnNum, pStr, pType) {
var lRet, lType = ' ';
if (pStr) {

View file

@ -12,30 +12,54 @@ Util = exports || {};
Util.asyncCall = function(pFuncs, pOnLoad, pContext) {
var i, element, name, func,
n = pFuncs.length,
funcsCount = pFuncs.length,
count = 0,
data = [];
for (i = 0; i < n; i++) {
for (i = 0; i < funcsCount; i++) {
func = pFuncs[i];
callCheckFunc(i, func);
}
function checkFunc(pNum, pData) {
++count;
data[pNum] = pData;
var i, m = pData.length,
params = [];
if (count === n)
++count;
if (m >= 2) {
for (i = 0; i < m; i++)
params[i] = pData[i];
data[pNum] = params;
} else
data[pNum] = pData[0];
if (count === funcsCount)
pOnLoad.apply(pContext, data);
}
function callCheckFunc(pNum, pFunc) {
Util.exec(pFunc, function(pData){
checkFunc(pNum, pData);
Util.exec(pFunc, function() {
checkFunc(pNum, arguments);
});
}
},
/**
* ad new line (if it's not)
* @param {string} pText
*/
Util.addNewLine = function(pText){
var lNewLine = '',
n = pText && pText.length;
if(n && pText[n-1] !== '\n')
lNewLine = '\n';
return pText + lNewLine;
};
/** setting function context
* @param {function} pFunction
* @param {object} pContext
@ -119,6 +143,7 @@ Util = exports || {};
var lProp = pPropArr[i];
lRet = pObj.hasOwnProperty( lProp );
if (!lRet) {
console.trace();
Util.logError(lProp + ' not in Obj!');
Util.log(pObj);
break;
@ -152,6 +177,7 @@ Util = exports || {};
lRet = pObj[lProp];
if (!lRet) {
console.trace();
Util.logError(lProp + ' not true!');
Util.log(pObj);
break;
@ -171,15 +197,10 @@ Util = exports || {};
*/
Util.copyObj = function(pFromObj, pToObj, pProps) {
var lRet = pToObj || pProps || {},
copy = function(name, obj) {
var value = obj[name];
if (value)
pToObj[name] = obj[name];
},
forIn = function(obj) {
Util.forIn(obj, function(name) {
copy(name, obj);
pToObj[name] = obj[name];
});
};
@ -395,7 +416,7 @@ Util = exports || {};
lShift = Util.bind([].shift, lArg),
lJoin = Util.bind([].join, lArg);
if (lConsole && lArg.length) {
if (lConsole && lArg.length && lArg[0]) {
lUnShift(lDate);
lConsole.log.apply(lConsole, lArg);
lShift();

View file

@ -1,9 +1,9 @@
{
"name": "cloudcmd",
"version": "0.5.0",
"version": "0.6.0",
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
"description": "Cloud Commander - file manager with console and editor",
"homepage": "https://github.com/coderaiser/cloudcmd",
"homepage": "http://cloudcmd.io",
"repository": {
"type": "git",
"url": "git://github.com/coderaiser/cloudcmd.git"
@ -15,14 +15,14 @@
"test": "sh ./test/test.sh",
"start": "cloudcmd.js"
},
"node": "0.6.17",
"subdomain": "cloudcmd",
"dependencies": {
"dropbox": "0.10.1",
"minify": "0.2.2",
"socket.io": "0.9.16"
"dropbox": "0.10.2",
"minify": "0.2.3",
"socket.io": "0.9.16",
"express": "3.4.x"
},
"devDependencies": {},
"license": "MIT",
"engines": {
"node": ">=0.4.x"
},

View file

@ -3,7 +3,7 @@ if test -z $1
then
echo "log.sh <tag>"
else
git log $1..HEAD --pretty=format:"* %s" --grep feature
git log $1..HEAD --pretty=format:"* %s" --grep fix
git log $1..HEAD --pretty=format:"* %s" --grep refactor
git log $1..HEAD --pretty=format:"- %s" --grep feature
git log $1..HEAD --pretty=format:"- %s" --grep fix
git log $1..HEAD --pretty=format:"- %s" --grep refactor
fi